zoukankan      html  css  js  c++  java
  • 《深入浅出WPF》学习笔记之深入浅出话属性

    依赖属性是一种可以从父级元素继承,并且可以通过Binding从数据源获取,当从父级继承时不占用内存的属性系统。拥有依赖属性的对象称为依赖对象。WPF允许在创建对象时并不分配用于存储数据的空间,而在需要时实时分配空间或直接借用父级数据,这种对象称为依赖对象(DependencyObject),这种实时获取数据的能力依靠依赖属性(Dependency Property)来实现。必须使用依赖对象作为依赖属性的宿主。DependencyObject是相当底层的一个基类,通过GetValue和SetValue获取或设置依赖属性的值。

    声明和使用依赖属性

        public class Student:DependencyObject
        {
            public readonly static DependencyProperty NameProperty = DependencyProperty.Register("Name", typeof(String), typeof(Student));
    
    
            public String Name
            {
                get { return (String)GetValue(Student.NameProperty); }
                set { SetValue(Student.NameProperty, value); }
            }
        }

    依赖属性一定被声明为public static readonly,并且约定依赖属性成员名称添加后缀“Property”表明这是一个依赖属性。依赖属性实例通过Register方法创建,Register的第一个参数为此依赖属性的CLR属性包装器的名称,第二个参数为依赖属性注册的类型,第三个参数为依赖属性的宿主类型。当依赖属性没有用CLR属性包装时,只能作为数据绑定的Target,使用CLR属性包装后,即可以作为Binding的Target,也可以作为Binding的Source。当依赖属性作为Binding的Source时,即使不实现INotifyPropertyChanged接口在属性值更改时也能通知Binding更改Target,依赖属性自带通知功能,因此当我们不想实现繁琐的INotifyPropertyChanged接口时可以使用依赖属性作为数据源。在Visual Studio中通过输入propdp在连按两次Tab键可以直接输入依赖属性模板,以加快编码速度。

    依赖属性值存取的原理

    创建一个DependencyProperty实例,并用它的CLR属性名和宿主类型名生成hash code,最后使用hash code作为DependencyProperty实例的key存入全局的名为DependencyProperty.PropertyFromName的Hashtable中。这样通过CLR属性名和宿主类型名检索出DependencyProperty实例,因此在同一个类型中不能声明CLR属性名相同的多个依赖属性实例。

    依赖属性的值被统一存储在DependencyObject中的EffectiveValueEntry[] _effectiveValues这样的数组中,数组根据算法和DependencyProperty的GlobalIndex属性进行排序,依赖属性值的存取、删除、等操作都是针对这个数组进行,DependencyProperty的实例只是依赖属性值的标识,用来检索属性值。

    附加属性

    顾名思义,附加属性是说一个属性本来不属于某个类,但由于某种需求而被后来附加上。也就是说把对象放到一个特殊的环境中对象才有的属性。附加属性的作用就是让属性与数据类型解耦,让数据类型的设计更加灵活,附加属性定义在更高层次语义的对象上,在需要时附加到与之关联的对象上。附加属性本质上是依赖属性,二者仅在注册与包装器上有区别。

        public class School:DependencyObject
        {
            public static int GetGrade(DependencyObject obj)
            {
                return (int)obj.GetValue(GradeProperty);
            }
    
            public static void SetGrade(DependencyObject obj, int value)
            {
                obj.SetValue(GradeProperty, value);
            }
    
            // Using a DependencyProperty as the backing store for Grade.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty GradeProperty =
                DependencyProperty.RegisterAttached("Grade", typeof(int), typeof(School), new PropertyMetadata(0));
        }

    声明附加属性时仅注册方法不同,参数和参数含义相同。附加属性的包装器与依赖属性不同,分别声明Get和Set方法用来存取附加属性,附加属性存取在要附加的对象上。实际上附加属性就是使用定义在其他类中的DependencyProperty存取属性值。附加属性的本质为依赖属性,因此可以使用Binding依赖其他对象的属性值。示例代码:

            <Slider x:Name="slider" Minimum="0" Maximum="100"></Slider>
            <Canvas Width="200" Height="200" Background="Gray">
                <Rectangle x:Name="rect" Width="20" Height="20" Canvas.Left="{Binding ElementName=slider, Path=Value,Mode=OneWay}" Fill="Red"></Rectangle>
            </Canvas>
    
    //等价的后台代码
                Binding binding = new Binding("Value");
                binding.ElementName = "slider";
                binding.Mode = BindingMode.OneWay;
                rect.SetBinding(Canvas.LeftProperty, binding);
  • 相关阅读:
    服务的有状态和无状态
    微服务-服务治理
    微服务-服务注册与发现
    微服务-技术的选型
    微服务的数据一致性
    微服务的服务拆分
    初识微服务
    REST API风格
    算法
    JS 判断PC、android、ios、微信浏览器
  • 原文地址:https://www.cnblogs.com/jefflee/p/5822470.html
Copyright © 2011-2022 走看看