基于Cairngorm的Silverlight开发 - part3
使用ModelLocator来管理视图
之前只是简单的介绍了一下ModelLocator的用法,在这里要把模型和视图结合起来,通过模型来来控制视图。在Silverlight中我们可以看到所有新建立的xaml都是继承自UserControl,所以在这里更新欢称视图为控件。
至此给出一个项目的结构图出来。这里我是习惯把从网上下载的第三方类库放在项目中一个Lib的目录下,如果有源码的话直接加入解决方案中也是可以的。
所有的用户控件都是创建在Controls目录下。这里提到了创建用户控件,所以就不得不提一下控件的DependencyProperty属性,他是控件的一个静态的属性,主要用来做数据绑定。
为控件创建DependencyProperty属性
创建了DependencyProperty后能更方便的和ModelLocator进行绑定。处理一些界面上的动画效果也能更加的灵活。
这里给出一个标准的代码
// Using a DependencyProperty as the backing store for TheName.
// This enables animation, styling, binding, etc
public static readonly DependencyProperty TheNameProperty =
DependencyProperty.Register("TheName",
typeof(string),
typeof(Page),
new PropertyMetadata("",
new PropertyChangedCallback(
OnTheNameChanged)));
static void OnTheNameChanged(object sender,
DependencyPropertyChangedEventArgs args)
{
// Get reference to self
Page source = (Page)sender;
// Add Handling Code
string newValue = (string)args.NewValue;
}更多关于创建自定义用户控件的请查看winter-cn 前辈的《Silverlight 2 Customized Control 开发》 ,写的非常的详细。(我这里就不再去重复的发明轮子了)
创建一个会变色的控件
送上视频 :) ViewManagerP1.wmv学习是一个温故知新的过程,之前我写过一篇《动态创建Storyboard》这里就用上他再结合DependencyProperty做一个会变色的控件。
运用DependencyProperty结合Storyboard创建控件
public partial class BackGorund : UserControl
{
public byte R
{
get { return (byte)GetValue(RProperty); }
set { SetValue(RProperty, value); }
}
// Using a DependencyProperty as the backing store for R.
// This enables animation, styling, binding, etc
public static readonly DependencyProperty RProperty =
DependencyProperty.Register("R",
typeof(byte),
typeof(BackGorund),
new PropertyMetadata((byte)0,
new PropertyChangedCallback(OnRChanged)));
static void OnRChanged(object sender, DependencyPropertyChangedEventArgs args)
{
// Get reference to self
BackGorund source = (BackGorund)sender;
source.changeColor();
}
public byte G
{
get { return (byte)GetValue(GProperty); }
set { SetValue(GProperty, value); }
}
// Using a DependencyProperty as the backing store for G.
// This enables animation, styling, binding, etc
public static readonly DependencyProperty GProperty =
DependencyProperty.Register("G",
typeof(byte),
typeof(BackGorund),
new PropertyMetadata((byte)0,
new PropertyChangedCallback(OnGChanged)));
static void OnGChanged(object sender, DependencyPropertyChangedEventArgs args)
{
// Get reference to self
BackGorund source = (BackGorund)sender;
source.changeColor();
}
public byte B
{
get { return (byte)GetValue(BProperty); }
set { SetValue(BProperty, value); }
}
// Using a DependencyProperty as the backing store for B.
// This enables animation, styling, binding, etc
public static readonly DependencyProperty BProperty =
DependencyProperty.Register("B",
typeof(byte),
typeof(BackGorund),
new PropertyMetadata((byte)0,
new PropertyChangedCallback(OnBChanged)));
static void OnBChanged(object sender, DependencyPropertyChangedEventArgs args)
{
// Get reference to self
BackGorund source = (BackGorund)sender;
source.changeColor();
}
public void changeColor()
{
colorAnim.To = Color.FromArgb(255, R, G, B);
storyboard.Begin();
}
private ColorAnimation colorAnim;
private Storyboard storyboard;
public BackGorund()
{
InitializeComponent();
storyboard = new Storyboard();
Brush br = this.LayoutRoot.Background;
colorAnim = new ColorAnimation();
colorAnim.To = Color.FromArgb(255, R, G, B);
colorAnim.Duration = TimeSpan.FromSeconds(1);
colorAnim.RepeatBehavior = new RepeatBehavior(1);
colorAnim.AutoReverse = false;
Storyboard.SetTarget(colorAnim, br);
Storyboard.SetTargetProperty(colorAnim, new PropertyPath("Color"));
storyboard.Children.Add(colorAnim);
Resources.Add("colorsb", storyboard);
this.Loaded += new RoutedEventHandler(BackGorund_Loaded);
}
}创建ModelLocatorpublic class BackGroundModel : ModelLocator
{
private static readonly BackGroundModel _instance = new BackGroundModel();
public static BackGroundModel Instance { get { return _instance; } }
static BackGroundModel()
{
}
private BackGroundModel()
: base()
{
}
private byte _R = (byte)0;
public byte R
{
get { return _R; }
set
{
_R = value;
NotifyPropertyChanged("R");
}
}
private byte _G = (byte)0;
public byte G
{
get { return _G; }
set
{
_G = value;
NotifyPropertyChanged("G");
}
}
private byte _B = (byte)0;
public byte B
{
get { return _B; }
set
{
_B = value;
NotifyPropertyChanged("B");
}
}
}
控件Load时绑定属性,通过模型来控制视图
void BackGorund_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = BackGroundModel.Instance;
Binding bindR = new Binding("R");
bindR.Mode = BindingMode.TwoWay;
this.SetBinding(RProperty, bindR);
Binding bindG = new Binding("G");
bindG.Mode = BindingMode.TwoWay;
this.SetBinding(GProperty, bindG);
Binding bindB = new Binding("B");
bindB.Mode = BindingMode.TwoWay;
this.SetBinding(BProperty, bindB);
}
提高效率
Shawn Wildermuth 写了一个Code Snippets能帮我们快速的创建DependencyProperty属性,具体用法与下载地址请访问这里 。我自己写了一个快速创建ModelLocator的Code Snippets,用法都是一样,点击这里 下载。