zoukankan      html  css  js  c++  java
  • WPF知识4 依赖属性

    依赖项属性是通过调用 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
  • 相关阅读:
    SQL游标的小知识
    SQL游标的小知识
    SQL游标的小知识
    为什么程序员发现不了自己的BUG
    为什么程序员发现不了自己的BUG
    为什么程序员发现不了自己的BUG
    为什么程序员发现不了自己的BUG
    为什么程序员发现不了自己的BUG
    ACM1998
    Leetcode 946. Validate Stack Sequences 验证栈序列
  • 原文地址:https://www.cnblogs.com/xiepeixing/p/2995540.html
Copyright © 2011-2022 走看看