WPF依赖属性

依赖属性定义

可使用代码片段-propdp快速生成,输入propdp后按两次Tab键

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));
public class DependencyPropertyStudy : Control
{
    // 依赖属性    所在对象   必须是依赖对象
    // readonly   只能被赋值一次,不能被二次修改
    public static readonly DependencyProperty ValueProperty;
    
        // 基本三个参数:属性名称、属性类型、所属类型
        // 默认值一定要跟属性类型严格一致

        // 委托回调方法参数
        ValueProperty = DependencyProperty.Register(
            "Value",
            typeof(double),
            typeof(DependencyPropertyStudy),

            new PropertyMetadata(
                0.0,
                new PropertyChangedCallback(OnValueChanged),
                new CoerceValueCallback(OnValueCoerce)),

            new ValidateValueCallback(OnValueValidation)
            );
    // 利用普通属性对依赖属性的封装
    // 目的是为了在代码中方便访问      绑定过程是用不到这个的
    public double Value
    {
        get => (double)this.GetValue(ValueProperty);
        set
        {
            this.SetValue(ValueProperty, value);
        }
    }

}

属性名称:Xaml文档中访问的名称

属性类型:属性的具体类型

所属类型:当前类名(依赖对象)

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

默认值

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

    new PropertyMetadata(0.0)//默认值
    );

依赖属性初始化时后赋予的默认值

属性值变化回调

属性值发生变化时的回调,但注意两次数值相同时不触发

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

    new PropertyMetadata(
        0.0,
        new PropertyChangedCallback(OnValueChanged)//属性值发生变化时的回调
        );
        
// 属性值变化回调:处理的是监听属性值的变化
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    // 如果被调用成功,这里就将知道对应的依赖值发了生变化

    (d as DependencyPropertyStudy).Refresh();

    var a = e.NewValue;//新值
    var b = e.OldValue;//旧值    
}

private void Refresh()
{

}

 验证回调

属性值发生改变时触发,返回BOOL量结果

// 基本三个参数:属性名称、属性类型、所属类型
// 默认值一定要跟属性类型严格一致

// 委托回调方法参数
ValueProperty = DependencyProperty.Register(
    "Value",
    typeof(double),
    typeof(DependencyPropertyStudy),

    new PropertyMetadata(
        0.0,
        new PropertyChangedCallback(OnValueChanged)),

    new ValidateValueCallback(OnValueValidation)//验证回调
    );
    
/// <summary>
/// 
/// </summary>
/// <param name="v">依赖属性所接收到的最新的值</param>
/// <returns>对数据的判断结果,只有状态结果,True/False</returns>
private static bool OnValueValidation(object v)
{
    if ((double)v > 2000)
        return false;

    return true;
}

 强制回调

属性值发生改变时触发,返回最终的结果赋值给属性值

// 委托回调方法参数
ValueProperty = DependencyProperty.Register(
    "Value",
    typeof(double),
    typeof(DependencyPropertyStudy),

    new PropertyMetadata(
        0.0,
        new PropertyChangedCallback(OnValueChanged),
        new CoerceValueCallback(OnValueCoerce)),//强制回调

    new ValidateValueCallback(OnValueValidation)
    );
//返回最终结果值
private static object OnValueCoerce(DependencyObject d, object v)
{
    if ((double)v > 255) return 255.0;
    if ((double)v < 0) return 0.0;
    return v;
}

 元数据FrameworkPropertyMetadataOptions

namespace System.Windows
{
    [Flags]
    public enum FrameworkPropertyMetadataOptions
    {
        None = 0,
        AffectsMeasure = 1,
        AffectsArrange = 2,                            //AffectsMeasure和AffectsArrange一起使用,属性值变化时会导致对象的重新测量与排列
        AffectsParentMeasure = 4,
        AffectsParentArrange = 8,                      //AffectsParentMeasure和AffectsParentArrange一起使用,不导致对象的重新测量与排列,而是上一级对象的重新测量与排列
        AffectsRender = 16,
        Inherits = 32,
        OverridesInheritanceBehavior = 64,
        NotDataBindable = 128,                         //依赖属性是否可以被绑定的特性,默认为可绑定
        BindsTwoWayByDefault = 256,                    
        Journal = 1024,
        SubPropertiesDoNotAffectRender = 2048          //属性值变化时子项不进行渲染
    }
}

使用样例

public double RowSpace
{
    get { return (double)GetValue(RowSpaceProperty); }
    set { SetValue(RowSpaceProperty, value); }
}
public static readonly DependencyProperty RowSpaceProperty =
    DependencyProperty.Register(
        "RowSpace",
        typeof(double),
        typeof(ZxPanel),

        // 通过这个参数确定属性值发生变化时的一些影响
        //new PropertyMetadata(0.0)
        new FrameworkPropertyMetadata(
            0.0,//默认值
            FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)
        );

依赖属性的继承

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

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d" FontSize="30" 
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TextBox Text="12313"/>
    </Grid>
</Window>

在窗体中设置字体大小属性,子项TextBox中也有FontSize属性,就可以继承窗体的FontSize属性值

同理,当控件有自定义依赖属性后,会向上逐级查找父元素的该自定义属性值。

public class DependencyPropertyStudy : Control
{
    public int Test
    {
        get { return (int)GetValue(TestProperty); }
        set { SetValue(TestProperty, value); }
    }
    // 依赖属性的继承
    public static readonly DependencyProperty TestProperty =
        ZxPanel.TestProperty.AddOwner(
            typeof(DependencyPropertyStudy),
            new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Inherits));
}
public class ZxPanel : Panel
{
    public int Test
    {
        get { return (int)GetValue(TestProperty); }
        set { SetValue(TestProperty, value); }
    }
    public static readonly DependencyProperty TestProperty =
        DependencyProperty.Register("Test", typeof(int), typeof(ZxPanel),
            new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Inherits));

}

两个依赖对象有相同属性名称和属性类型的依赖属性

<Grid>
    <local:DependencyPropertyStudy Tag="123" Command="{Binding}" Grid.Column="1"/>
    <local:ZxPanel ColumnSpace="10" RowSpace="10" Test="123">
        <local:DependencyPropertyStudy/>
    </local:ZxPanel>
</Grid>

 local:DependencyPropertyStudy的依赖属性Test=local:ZxPanel的依赖属性值Test=123

posted @ 2023-11-21 19:53  ZHIZRL  阅读(48)  评论(0编辑  收藏  举报