1. Dependency Property

WPF里对.net中的属性进行了包装,WPF里用到的绝大部分属性都是Dependency property。

其实现大体如下:

//NOTE: This file is not meant to be compiled!  

 

public class Button : ButtonBase  

{  

    // The dependency property  

    public static readonly DependencyProperty IsDefaultProperty;  

 

    static Button()  

    {  

        // Register the property  

        Button.IsDefaultProperty = DependencyProperty.Register("IsDefault",  

        typeof(bool), typeof(Button),  

        new FrameworkPropertyMetadata(false,  

        new PropertyChangedCallback(OnIsDefaultChanged)));  

    }  

 

    // A .NET property wrapper (optional)  

    public bool IsDefault  

    {  

        get { return (bool)GetValue(Button.IsDefaultProperty); }  

        set { SetValue(Button.IsDefaultProperty, value); }  

    }  

 

    // A property changed callback (optional)  

    private static void OnIsDefaultChanged(  

        DependencyObject o, DependencyPropertyChangedEventArgs e) { }  

}

注意,DependencyProperty被声明为static readonly,那它就拥有唯一实例,为什么界面上有n个button,只对应一个IsDefaultProperty,而又可以正常工作呢,原来在注册dependency property时,wpf内部作了一些额外的事情,大体描述如下,可能不严格:

wpf内部,每个dependency property对应一个hash表,键是每个实例的唯一标识,值就是dependency property对应的值了。在new一个实例时,会生成一个唯一标识。

值得注意的是,wpf内部代码都是用GetValue和SetValue进行取/赋值操作,不是根据自己包装的属性也就是这个例子中的IsDefault,包不包装属性,对于wpf是不关心的,所以我们自己的对外属性的get,set中千万不要加入其他代码,以免出现预期结果和wpf执行结果不一致的情况。

Dependency property有什么好处或用处呢?

减少每个实例中属性占用的空间?不尽然,从效果上,并不明显,毕竟值都是要保存的。

MSDN上摘录如下:

The purpose of dependency properties is to provide a way to compute the value of a property based on the value of other inputs. These other inputs might include system properties such as themes and user preference, just-in-time property determination mechanisms such as data binding and animations/storyboards, multiple-use templates such as resources and styles, or values known through parent-child relationships with other elements in the element tree. In addition, a dependency property can be implemented to provide self-contained validation, default values, callbacks that monitor changes to other properties, and a system that can coerce property values based on potentially runtime information. Derived classes can also change some specific characteristics of an existing property by overriding dependency property metadata, rather than overriding the actual implementation of existing properties or creating new properties.

依赖项属性的用途在于提供一种方法来基于其他输入的值计算属性值。这些其他输入可以包括系统属性(如主题和用户首选项)、实时属性确定机制(如数据绑定和动画/演示图板)、重用模板(如资源和样式)或者通过与元素树中其他元素的父子关系来公开的值。另外,可以通过实现依赖项属性来提供独立验证、默认值、监视其他属性的更改的回调以及可以基于可能的运行时信息来强制指定属性值的系统。派生类还可以通过重写依赖项属性元数据(而不是重写现有属性的实际实现或者创建新属性)来更改现有属性的某些具体特征。

可以说,wpf里所有常用的特性都是基于dependency property的。

覆写metadate

public class SpinnerControl : ItemsControl
{
    static SpinnerControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(SpinnerControl),
            new FrameworkPropertyMetadata(typeof(SpinnerControl))
        );
    }
}

在从最初注册依赖项属性的类派生时,可以通过重写依赖项属性的元数据来更改该属性的某些行为。对元数据的重写依赖于 TextElement.IsValidFontSize));

代码和注册Dependency Property的很像,实际上两段代码功能也基本一样,只是RegiserAttached简化一了下。

如果我们要实现自己的类,什么时候用dependency property,什么时候用attached property呢?

如果只是这个类自己使用的属性,可以向外开放dependency property

如果不确定这个类的children是否有需要的denpendency property,而在某些时候需要children设置这样的property时,用attached property,典型的是用在构建UI时的那些Panel。

相关文章:

  • 2021-06-20
  • 2021-07-28
  • 2021-04-07
  • 2022-02-15
  • 2022-01-14
  • 2021-09-07
  • 2022-03-03
猜你喜欢
  • 2022-01-11
  • 2022-02-17
  • 2022-12-23
  • 2022-01-15
  • 2021-08-29
  • 2021-11-14
  • 2022-02-26
相关资源
相似解决方案