zoukankan      html  css  js  c++  java
  • Freezable 对象(WPF)

    先看下图
    image

    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属性设置为空,这是需要注意的.
    总结:当对象不需要发生改变时,则冻结该对象,减少对象监听,提升性能
  • 相关阅读:
    springboot整合shiro进行权限管理
    多线程基础(一)
    面试杂谈(一)
    Spring循环依赖问题
    记一次电话面试的题目
    Jvm垃圾回收器(终结篇)
    Jvm垃圾回收器(算法篇)
    Jvm垃圾回收器(基础篇)
    Java内存模型探秘
    Jvm类的加载机制
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/1777328.html
Copyright © 2011-2022 走看看