其他分享
首页 > 其他分享> > 【WPF】依赖属性

【WPF】依赖属性

作者:互联网

依赖属性DependencyProperty的诞生背景

WPF开发中,必须使用依赖对象作为依赖属性的宿主,使二者结合起来。依赖对象的概念被DependencyObject类所实现,依赖属性的概念则由DependencyProperty类所实现

WPF框架的编程经常和界面打交道,经常遇到的一个情况是某个属性的值的变化会影响到多个其他对象。比如当一个Button的改变大小超过了它的容器,他的容器应该自动调整大小。于是我们考虑在每个属性的set方法中触发一些事件,但很快我们发现现有的功能很难满足我们的需求,至少不能简洁漂亮的满足这些需求。
实际上我们的需求更加复杂,WPF中的数据绑定,XAML语法等很多地方都和属性密切相关,我们迫切需要一种功能更加强大的属性。

于是在WPF中,引入了一种特殊的属性,Dependency Property。这种属性和普通的属性最大不同在于,它的值的来源并不单一。对这种属性的取值和赋值都会能与其他对象有影响,因此能得到很大的灵活性

依赖属性和依赖对象

DependencyObject和DependencyPorperty两个类是WPF属性系统的核心。
在WPF中,依赖对象的概念被DependencyObject类实现;依赖属性的概念则由DependencyPorperty类实现。
必须使用依赖对象作为依赖属性的宿主,二者结合起来,才能实现完整的Binding目标被数据所驱动。DependencyObject具有GetValue和SetValue两个方法,用来获取/设置依赖属性的值。
DependencyObject是WPF系统中相当底层的一个基类,如下:

 

 

 继承树上可以看出,WPF的所有UI控件都是依赖对象。

依赖属性系统

 赖项属性的应用

 WPF中各个功能的实现都离不开依赖项属性的支持,如绑定,模板,动画,属性值的优先级

 动态资源——Background="{DynamicResource MyBrush}"

数据绑定——Background="{Binding MyBrush}"

样式——<Setter Property="Background" Value="Red"/>

动画——<ColorAnimation Storyboard.TargetName="MyButton" Storyboard.TargetProperty="Background" From="Red" To="Blue"/>

元数据重写——通过依赖属性的OverrideMetadata来重写父类的属性默认行为

属性值继承——继承元素树父级的属性值(DataContext,FontSize)

WPF设计器集成——使用WPF设计器时,可以在属性窗口编辑属性值

命名规则:

字段总是与属性同名,但其后面追加了 Property 后缀。 有关此约定及其原因的详细信息,

 

依赖属性创建

1、输入快捷键 "Propdp" 点击 TAB 按键自动生成默认 依赖属性如下为系统默认依赖属性

public int MyProperty
{
   get { return (int)GetValue(MyPropertyProperty); }
    set { SetValue(MyPropertyProperty, value); }
}

// Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
      DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0));

按照自己的需要修改依赖属性名称、属性名称。
依赖属性实例并非使用new操作符得到而是使用DependencyProperty.Register方法生成。

DependencyProperty.Register的参数说明

定义

  上面介绍了依赖属性所带来的好处,这时候,问题又来了,怎样自己定义一个依赖属性呢?C#属性的定义大家再熟悉不过了。下面通过把C#属性进行改写成依赖属性的方式来介绍依赖属性的定义。下面是一个属性的定义:

1 public class Person
2     {
3         public string Name { get; set; }
6     }

在属性系统中注册属性

为使属性成为依赖属性,必须在属性系统维护的表中注册该属性,并为属性指定一个唯一标识符。此唯一标识符会用作后续属性系统操作的限定符。 这些操作可能是内部操作,也可能使用你自己的代码调用属性系统 API。 若要注册属性,可在类的主体内(在类中但在所有成员定义外)调用 Register 方法。 Register 方法调用也会提供标识符字段作为返回值。 Register 调用在其他成员定义外完成的原因在于,需要使用此返回值分配并创建一个 DependencyProperty 类型的 public static readonly 字段,作为类的一部分。 此字段会作为依赖属性的标识符。

 在把上面属性改写为依赖属性之前,下面总结下定义依赖属性的步骤:

  1. 让依赖属性的所在类型继承自DependencyObject类。DependencyObject 类提供了GetValue、 SetValue方法
  2. 使用public static 声明一个DependencyProperty的变量,该变量就是真正的依赖属性。
  3. 提供一个依赖属性的包装属性,通过这个属性来完成对依赖属性的读写操作。

  根据上面的四个步骤,下面来把Name属性来改写成一个依赖属性,具体的实现代码如下所示:

 1. 使类型继承DependencyObject类
    public class Person : DependencyObject
    {
        // 2. 声明一个静态只读的DependencyProperty 字段 // 3. 注册定义的依赖属性 
        public static readonly DependencyProperty NameProperty=DependencyProperty.Register("Name", typeof(string), typeof(Person), new PropertyMetadata("Learning Hard",OnValueChanged)); 
       
      // 4. 属性包装器,通过它来读取和设置我们刚才注册的依赖属性 public void SetValue (DependencyProperty dp, object value);
        public string Name
        {
            get { return (string)GetValue(nameProperty); }
            set { SetValue(nameProperty, value); }
        }

        private static void OnValueChanged(DependencyObject dpobj, DependencyPropertyChangedEventArgs e)
        {
            // 当只发生改变时回调的方法
        }

    }

PropertyMetadata:依赖项属性元数据

第四个参数支持 PropertyMetadate 类型,同时它派生的UIPropertyMetadata类型
以及UIPropertyMetadata派生的FrameworkPropertyMetadata 在不同类型上实现的效果略有差异,此次提出一个典型

若依赖属性为ObservableCollection<T>的时候,必须要使用FrameworkPropertyMetadata作为参数,代码如下,给DefaultVaule、DefaultUpdateSourceTrigger 赋默认值。

        new FrameworkPropertyMetadata
                {
                    DefaultValue = new ObservableCollection<T>(),
                    DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                });

 

 自定义控件实现依赖属性有如下三个注意点

标签:依赖,DependencyProperty,public,DependencyObject,WPF,属性
来源: https://www.cnblogs.com/cdaniu/p/16318139.html