WPF 初识依赖属性

依赖属性的意义和作用

  • 核心模块
  • 内存共享,节省空间
  • 数据绑定、样式、模板、动画。。。。
  • 如果没有依赖属性,这个框架就是一个控件框架 相当于Winform

依赖属性的基本定义

基本过程:声明、注册、包装

在需要写依赖属性的类中,继承DependencyObject,或者DependencyObject以下的类都行:

声明

public static readonly DependencyProperty ValueProperty;

注意:

声名 DependencyProperty

约定:名字命名为:名字+Property

readonly 只能被赋值一次,不能被二次修改

注意:readonly这里的只读是限制注册的,不包含里面的值,所以可以动态赋值SetValue

注册

基本的三个参数: 属性名称、属性类型、所属类型(所使用的类的名称)

ValueProperty = DependencyProperty.Register(
    "Value",
    typeof(double),
    typeof(DependencyPropertyStudy));

包装

将依赖属性,包装成普通属性,修改和创建

必须继承DependencyObject及以上的类,才可以写GetValue和SetValue:

 public double Value
 {
     get { return (double)GetValue(ValueProperty); }
     set
     {
         SetValue(ValueProperty, value);
     }
 }

代码片段:propdp

输入propdp + tab 自动生成

和上面注册是一样的,不过多了一个默认值(PropertyMetadata),加粗的部分是需要自定义的,根据自己的需求来。

 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));

依赖属性的主要参数与回调参数

默认值

ValueProperty = DependencyProperty.Register(
    "Value",
    typeof(double),
    typeof(DependencyPropertyStudy));
属性值变化回调:
ValueProperty = DependencyProperty.Register(
    "Value",
    typeof(double),
    typeof(DependencyPropertyStudy),
    new PropertyMetadata(
        1d,
        new PropertyChangedCallback(OnValueChanged)));

// 属性值变化回调参数
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    // 静态回调 本方法体的非静态方法
    (d as DependencyPropertyStudy).Refresh();
}

属性值变化的时候,进入此回调函数e.NewValue 将被修改。

如果调用成功 这里将之后对应的依赖值发生了变化

当两次值一样的时候,不触发

验证回调:
ValueProperty = DependencyProperty.Register(
    "Value",
    typeof(double),
    typeof(DependencyPropertyStudy),
    new PropertyMetadata(
        1d),
    new ValidateValueCallback(OnValueValidation));


/// <summary>
/// 对数据的判断结果 编译能触发限制报错信息
/// 需要强制回调的时候,就不要给验证信息False 否则不走强制回调
/// </summary>
/// <param name="v">依赖属性所接受到的最新的值</param>
/// <returns>对数据的判断结果</returns>
private static bool OnValueValidation(object v)
{
    //if((double)v > 2000d)
    //    return false;
    return true;
}
强制回调
ValueProperty = DependencyProperty.Register(
    "Value",
    typeof(double),
    typeof(DependencyPropertyStudy),
    new PropertyMetadata(
        1d,
        new PropertyChangedCallback(OnValueChanged),
        new CoerceValueCallback(OnValueCoerce)));

// 强制回调参数
// 如果值超限,可以强制改回需要的值范围
 private static object OnValueCoerce(DependencyObject d, object v)
 {
     if ((double)v > 255d)
         return 255d;
     if ((double)v < 0d)
         return 0d;
     return v;
 }

完整代码:三个回调一起

 ValueProperty = DependencyProperty.Register(
     "Value",
     typeof(double),
     typeof(DependencyPropertyStudy),
     new PropertyMetadata(
         1d,
         new PropertyChangedCallback(OnValueChanged),
         new CoerceValueCallback(OnValueCoerce)),
     new ValidateValueCallback(OnValueValidation));

 // 属性值变化回调:处理的是监听属性值的变化
 private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
 {
     
     // 如果调用成功 这里将之后对应的依赖值发生了变化
     // 当两次值一样的时候,不触发
     // 静态回调 本方法体的非静态方法
     (d as DependencyPropertyStudy).Refresh();
 }

 /// <summary>
 /// 对数据的判断结果 编译能触发限制报错信息
 /// </summary>
 /// <param name="v">依赖属性所接受到的最新的值</param>
 /// <returns>对数据的判断结果</returns>
 private static bool OnValueValidation(object v)
 {
     //if((double)v > 2000d)
     //    return false;
     return true;
 }

 // 强制回调参数
 private static object OnValueCoerce(DependencyObject d, object v)
 {
     if ((double)v > 255d)
         return 255d;
     if ((double)v < 0d)
         return 0d;
     return v;
 }

执行顺序:

验证回调(首先给个默认值验证) --> 加载方法(load) --> 强制回调 --> 属性变化回调 --> 验证回调

元数据:FrameworkPropertyMetadataOptions

 public double ColumnSpace
 {
     get { return (double)GetValue(ColumnSpaceProperty); }
     set { SetValue(ColumnSpaceProperty, value); }
 }

 // Using a DependencyProperty as the backing store for ColumnSpace.  This enables animation, styling, binding, etc...
 public static readonly DependencyProperty ColumnSpaceProperty =
     DependencyProperty.Register(
         "ColumnSpace",
         typeof(double), 
         typeof(XHPanel),
         //new PropertyMetadata(0d,new PropertyChangedCallback(OnColumnSpaceChanged))
         // AffectsArrange: 影响排列  AffectsMeasure:影响测量 
         // 如果有多个用"|"分开
         new FrameworkPropertyMetadata(0d,FrameworkPropertyMetadataOptions.AffectsArrange 
             | FrameworkPropertyMetadataOptions.AffectsMeasure)
         );

此元数据使用在自定义控件的时候,修改属性时刷新UI是使用

扩展:FrameworkPropertyMetadataOptions 的属性:
None:未指定任何选项;依赖属性使用 WPF 属性系统的默认行为。
AffectsMeasure:更改此依赖属性的值会影响布局组合的测量过程。
AffectsArrange:更改此依赖属性的值会影响布局组合的排列过程。  
AffectsParentMeasure:更改此依赖属性的值会影响父元素上的测量过程。 
AffectsParentArrange:更改此依赖属性的值会影响父元素上的排列过程。  
AffectsRender:更改此依赖属性的值会影响呈现或布局组合的某一方面(不是测量或排列过程)。 
Inherits:此依赖属性的值将由子元素继承。
OverridesInheritanceBehavior:此依赖属性的值跨越分隔的树以实现属性值继承。
NotDataBindable:不允许将数据绑定到此依赖属性。
BindsTwoWayByDefault:此依赖属性上的数据绑定的 System.Windows.Data.BindingMode 默认为 System.Windows.Data.BindingMode.TwoWay。
Journal:此依赖属性的值应由日记记录进程或在由统一资源标识符 (URI) 导航时进行保存或存储。
SubPropertiesDoNotAffectRender:此依赖属性值上的子属性不会影响呈现的任何方面。

依赖属性的继承

允许元素树中的子元素从最近的父元素获取特定属性的值

由于父元素也可能通过属性值继承获得其属性值,因此系统可能递归回页面根

父亲依赖属性代码:

public int Test
 {
    get { return (int)GetValue(TestProperty); }
    set { SetValue(TestProperty, value); }
}

// Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty TestProperty =
    DependencyProperty.Register("Test", typeof(int), typeof(XHPanel),
                                 new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Inherits));

子类继承代码:

关键字:父类.依赖属性.AddOwner(类型,默认值)

 public int Test
 {
     get { return (int)GetValue(TestProperty); }
     set { SetValue(TestProperty, value); }
 }

 // 依赖属性的继承 继承于XHPanel 的 TestProperty
 // 允许元素树中的子元素从最近的父元素获取特定属性的值
 // 由于父元素也可以通过属性值继承获得其属性值,因此系统可能地归回页面根
 public static readonly DependencyProperty TestProperty =
     XHPanel.TestProperty.AddOwner(
         typeof(DependencyPropertyStudy),
         new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Inherits));

演示:XAML代码

<local:XHPanel Test="12" ColumnSpace="20" RowSpace="20" Visibility="Collapsed">
  <local:DependencyPropertyStudy x:Name="dps" />
</local:XHPanel>
<Button Width="200" Height="30"
  Content="测试依赖属性继承" FontSize="20" Click="Button_Click"/>

按钮事件代码:

private void Button_Click(object sender, RoutedEventArgs e)
{
    // 此时子没设置Test 属性,看是否可以弹出继承父的Test
    MessageBox.Show(this.dps.Test.ToString());
}

效果:

以上就是所有的依赖属性的基础使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值