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