依赖项属性是通过调用 Register 方法(或 RegisterReadOnly)在 WPF 属性系统中注册,并通过 DependencyProperty 标识符字段备份的属性。 依赖项属性只能由 DependencyObject 类型使用,但 DependencyObject 在 WPF 类层次结构中的级别很高,因此,WPF 中的大多数可用类都支持依赖项属性。
我们大部分时间都会使用依赖属性,依赖项属性提供用来扩展属性功能的功能,这与字段支持的属性相反。 每个这样的功能通常都表示或支持整套 WPF 功能中的特定功能:
资源
<DockPanel.Resources> <SolidColorBrush x:Key="MyBrush" Color="Gold"/> </DockPanel.Resources>
<Button Background="{DynamicResource MyBrush}" Content="I am gold" />
数据绑定
<Button Content="{Binding XPath=Team/@TeamName}"/>
样式
<Style x:Key="GreenButtonStyle"> <Setter Property="Control.Background" Value="Green"/> </Style>
<Button Style="{StaticResource GreenButtonStyle}">I am green!</Button>
动画
<Button>I am animated <Button.Background> <SolidColorBrush x:Name="AnimBrush"/> </Button.Background> <Button.Triggers> <EventTrigger RoutedEvent="Button.Loaded"> <BeginStoryboard> <Storyboard> <ColorAnimation Storyboard.TargetName="AnimBrush" Storyboard.TargetProperty="(SolidColorBrush.Color)" From="Red" To="Green" Duration="0:0:5" AutoReverse="True" RepeatBehavior="Forever" /> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button>
元数据重写
public class SpinnerControl : ItemsControl { static SpinnerControl() { DefaultStyleKeyProperty.OverrideMetadata( typeof(SpinnerControl), new FrameworkPropertyMetadata(typeof(SpinnerControl)) ); } }
属性值继承
<StackPanel Canvas.Top="50" DataContext="{Binding Source={StaticResource XmlTeamsSource}}"> <Button Content="{Binding XPath=Team/@TeamName}"/> </StackPanel>
button的content属性值继承了stackpanel的datacontext源
虽然我们大部分时间都是使用依赖属性来做以上事情,仍然很多时候我们要创建自己的依赖属性,显然,自定义的WPF的控件库,及时不需要动画,数据绑定功能时候我们仍然需要创建自己的依赖属性。创建依赖属性很特殊和普通的.NET属性创建完全不同。
需要声明的是:只能为依赖对象添加依赖属性(继承自)DependencyObject,WPF基础结构大部分都继承自这个类。 |
自定义依赖项属性
首先,属性所在的类要直接或间接继承DependencyObject。这个类生成的对象表示一个具有依赖项属性的对象,这些对象,都能享用WPF的属性系统(属性系统主要是计算属性的值,并提供有关值已更改的系统通知)方面的服务。这个类有两个比较重要的方法,GetValue(返回当前对象依赖项属性的当前有效值)和SetValue(设置依赖项属性的本地值)。
其实,属性对应的字段必需是公有,静态,只读的,类型为DependencyProperty。即public static readonly DependencyProperty 字段名,同时字段的命名也有规范,属性名+Property,字段在定义时,通过DependencyProperty.Register来实注册属性(只有注册了,才能使用WPF属性系统的服务)。
Register方法有三种重载,如下:
名称 |
说明 |
Register(String, Type, Type) |
使用指定的属性名称、属性类型和属性所在对象的类型。 |
Register(String, Type, Type, PropertyMetadata) |
使用指定的属性名称、属性类型、属性所在对象的类型和属性元数据注册依赖项属性。 |
Register(String, Type, Type, PropertyMetadata, ValidateValueCallback) |
使用指定的属性名称、属性类型、属性所在对象的类型、属性元数据和属性的值验证回调来注册依赖项属性。 |
在Register中,各个参数解释如下:
String:依赖属性的名字(不加Property,即字段的名字);
Type:属性的类型;
Type:属性所属对象的类型;
PropertyMetadata:依赖项对象的属性元数据,是一个PropertyMetadata类型,可能赋初始值。PropertyMetadata有一个object的构造函数;
ValidateValueCallback:表示用作回调的方法,这个类型是一个委托,用于验证依赖项属性的值的有效性,因为是委托,故它的构造参数为一个方法名。
下面是2个开源自定义控件库的代码:分别是两种特殊的button
public class AppBarButton : Button { public AppBarButton() { DefaultStyleKey = typeof (AppBarButton); } public static readonly DependencyProperty MetroImageSourceProperty = DependencyProperty.Register("MetroImageSource", typeof(Visual), typeof(AppBarButton), new PropertyMetadata(default(Visual))); public Visual MetroImageSource { get { return (Visual)GetValue(MetroImageSourceProperty); } set { SetValue(MetroImageSourceProperty, value); } } }
public class Tile : Button { public Tile() { DefaultStyleKey = typeof (Tile); } public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(Tile), new PropertyMetadata(default(string))); public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } } public static readonly DependencyProperty CountProperty = DependencyProperty.Register("Count", typeof(string), typeof(Tile), new PropertyMetadata(default(string))); public string Count { get { return (string)GetValue(CountProperty); } set { SetValue(CountProperty, value); } } public static readonly DependencyProperty KeepDraggingProperty = DependencyProperty.Register("KeepDragging", typeof(bool), typeof(Tile), new PropertyMetadata(true)); public bool KeepDragging { get { return (bool)GetValue(KeepDraggingProperty); } set { SetValue(KeepDraggingProperty, value); } } public static readonly DependencyProperty TiltFactorProperty = DependencyProperty.Register("TiltFactor", typeof(int), typeof(Tile), new PropertyMetadata(5)); public int TiltFactor { get { return (Int32)GetValue(TiltFactorProperty); } set { SetValue(TiltFactorProperty, value); } } }
大致如下:
定义依赖属性并且注册依赖属性,根据约定,定义的依赖属性名称在普通属性末尾加上单词“Property”,完成注册后,添加属性包装器,使用DependencyObject的GetValue方法和SetValue方法。
创建依赖属性就完成了。
属性验证
wpf使用两种方法用于阻止非法值:
1,ValidateValueCallback 委托:
原型:
public delegate bool ValidateValueCallback( Object value )
true ,如果该值验证; false ,如果已提交的值无效。
例子:
private static bool ShirtValidateCallback(object value) { ShirtTypes sh = (ShirtTypes) value; return (sh==ShirtTypes.None || sh == ShirtTypes.Bowling || sh == ShirtTypes.Dress || sh == ShirtTypes.Rugby || sh == ShirtTypes.Tee); }
2,CoerceValue方法:略
见
http://msdn.microsoft.com/zh-cn/library/system.windows.dependencyobject.coercevalue.aspx