当前位置: 首页 > 编程语言 > .NET综合 > 正文

WPF学习之依赖属性和附加属性

时间:2010-07-18 cnblogs zlgcool Allan

依赖属性(Dependency Property)

.NET Framework 3.0引入了一个新的属性类型叫依赖属性, WPF,WF都在使用依赖属性用来实现样式化,数据绑定等.我们更多的使用依赖属性是为了让父元素的属性值在逻辑树上慢慢的传递到其子元素中,从而可以在整个可是父元素的逻辑子元素中共享属性值.WF就是依靠依赖属性来在工作流中的各Activity间传递属性值的. 所以,依赖属性内建的传递变更通知的能力是其最大特征.

如果你想让属性在一个包含内容子控件树的整个逻辑控件树中都有效并共享值时,你仅仅只需要将这个属性声明为依赖属性即可, WPF会通过内建的架构来支持属性的共享. 而在工作流中我们经常需要用到依赖属性,它保证了在一个工作流实例中,多个组件共享了同一个值. 幸运的是在WPF中大部分空间的属性都是依赖属性,这让我们应用时非常方便,而你并不需要着后边发生了什么。

依赖属性的实现

依赖属性其实也是普通的.NET属性,只是通过DependencyProperty.Register方法将普通的.NET属性注册为依赖属性。在依赖属性的声明中,其实对应的普通.NET属性并不是必需的,因为其内部的GetValue和SetValue方法是公开的,依赖属性的使用者可以通过调用GetValue/SetValue而放弃对普通.NET属性的依赖。但建立在普通.NET熟悉之上更符合我们通常的做法,而且这样有利于在XAML中设置属性。

下面的代码展示了定义依赖属性的通常做法:

public class Button:ButtonBase
{
  //依赖属性
  public static readonly DependencyProperty IsDependencyProperty;

  static Button()
  {
    //注册依赖属性
    Button.IsDependencyProperty = DependencyProperty.Register("IsDefault",
      typeof(bool), typeof(Button),
      new FrameworkPropertyMetadata(false,
      new PropertyChangedCallback(OnIsDefaultChanged)));
  }
  //.NET属性(可选)
  public bool IsDefault
  {
    get { return (bool)GetValue(Button.IsDefaultProperty); }
    set { SetValue(Button.IsDefaultProperty, value); }
  }

  //属性改变时的回调
private static void OnIsDefaultChanged(DependencyObject o,
DependencyPropertyChangedEventArgs e)
  {...}
}

在上面的示例代码中是标准的实现依赖属性定义的方法,这里需要注意的是依赖属性始终是定义在普通.NET属性之上的用Register静态方法注册的特殊属性,即便这里的.NET属性(如IsDefault属性)不是必需的。另一个需要注意的地方是,通过声明依赖属性,我们多了一个控制属性改变时的回调方法(即便这同样可以通过声明委托和事件来定义,但这里我们什么都没做,为什么不用呢?),这样的好处是我们可以在属性改变的时候做些我们想做的事情,而我们却省去了手动声明事件的任务。其实回调函数的存在是为了让我们保证在属性包装器中(IsDefault属性)仅仅使用标准的GetValue/SetValue而不用任何其他逻辑,转而将自定义逻辑写入回调函数--这样做是为了遵循WPF的统一设计原则,让XAML 设置属性与使用过程式代码设置属性保持一致。