Freezable 对象(WPF)

先看下图 
Freezable 对象(WPF)_第1张图片 

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";
entity.Freeze();
entity.Age = 1;
因为Age 并非依赖属性.

三.冻结状态

(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属性设置为空,这是需要注意的.
总结:当对象不需要发生改变时,则冻结该对象,减少对象监听,提升性能
(转自:http://www.cnblogs.com/Clingingboy/archive/2010/07/14/1777328.html)

你可能感兴趣的:(Freezable 对象(WPF))