依赖属性的意义和作用
- 核心模块
- 内存共享,节省空间
- 数据绑定、样式、模板、动画。。。。
- 如果没有依赖属性,这个框架就是一个控件框架 相当于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());
}
效果:
以上就是所有的依赖属性的基础使用。