Freezable 对象(WPF)
2010-07-14 16:17 Clingingboy 阅读(3727) 评论(3) 编辑 收藏 举报
先看下图
Freezable继承自DependencyObject,同时添加了Freezable方法,用于冻结对象.
一.冻结对象
以此为示例
public class People : Freezable { public string Name { get { return (string)GetValue(NameProperty); } set { SetValue(NameProperty, value); } } public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(People), new UIPropertyMetadata()); protected override Freezable CreateInstanceCore() { throw new NotImplementedException(); } }
现实生活中,人的名字是不可以随意修改的,作为对象,当名字定下来以后,就把该对象冻结了.那么就不能再修改此对象的属性了,如下
People entity = new People(); entity.Name = "Terry"; entity.Freeze(); //error entity.Name = "Curry";在调用Freeze方法后,再次修改Name 会报错
二.依赖对象与冻结
当调用Freeze方法后,DependencyObject将成为一个密封类(Saled),一旦DependencyObject成为密封类,那么内部将无法修改依赖属性,
这也意味着如果定义普通的CLR属性则没有这个问题,在People中添加一个Age属性(人的年龄总是递增的),下面的代码没有问题
People entity = new People(); entity.Name = "Terry";因为Age 并非依赖属性.
entity.Freeze(); entity.Age = 1;
三.冻结状态
(1)在冻结之前,需要知道该对象是否已经冻结(IsFrozen),当冻结之后IsFrozen为True
(2)即使继承了Freezable的对象,并非随时都可以冻结,在调用Freeze方法前,需要查看CanFrozen属性判断对象是否可以冻结(如果该对象可以冻结,即使调用Freeze方法后,该属性还是为True),否则会抛错
(3)冻结后的对象无法解冻,必须采用克隆方法创建一个新的对象.
四.无法冻结的情况
1.绑定时.
当一个dp对象其中有dp有绑定时,无法冻结;当dp解除绑定后则可以(如果进行了绑定就意味着值可能会修改,那么该对象就不是冻结的了)
People entity = new People(); BindingOperations.SetBinding(entity, People.NameProperty, new Binding("Name") { Source = entity }); //first not freeze if (entity.CanFreeze) entity.Freeze();
entity.Name = "Terry"; //freeze if (entity.CanFreeze) entity.Freeze();
2.Freezable中定义的dp属性类型必须为值类型或者是Freezable类型
比如在其中定义一个Button类型(非Freezable类型)的dp,当其有值时,则无法冻结
五.Freezable特性
1.可子属性变更通知
现在给People添加一个Skin属性
public class People : Freezable { public string Name { get { return (string)GetValue(NameProperty); } set { SetValue(NameProperty, value); } } public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(string), typeof(People), new UIPropertyMetadata()); public int Age { get; set; } public SolidColorBrush Skin { get { return (SolidColorBrush)GetValue(SkinProperty); } set { SetValue(SkinProperty, value); } } public static readonly DependencyProperty SkinProperty = DependencyProperty.Register("Skin", typeof(SolidColorBrush), typeof(People), new UIPropertyMetadata(null)); protected override Freezable CreateInstanceCore() { throw new NotImplementedException(); } }
测试以下代码,将触发两次事件
void MainWindow_Loaded(object sender, RoutedEventArgs e) { People entity = new People(); SolidColorBrush brush = new SolidColorBrush(); entity.Changed += new EventHandler(brush_Changed); //execute event entity.Skin = brush; //execute event brush.Color = Colors.Red; } void brush_Changed(object sender, EventArgs e) { }2.克隆
如果定义的属性均为依赖属性,那么克隆就会变的很简单,调用父类方法就行,如
public SolidColorBrush Clone() { return (SolidColorBrush) base.Clone(); } 3.冻结之后的对象将与UI线程分离
其会将内部的Dispatcher属性设置为空,这是需要注意的.
总结:当对象不需要发生改变时,则冻结该对象,减少对象监听,提升性能