WPF扩展属性与依赖属性详解
一、依赖属性(Dependency Property)详解
1. 什么是依赖属性?
依赖属性是WPF框架的核心特性之一,它允许属性值依赖于:
- 父元素的属性值(继承)
- 样式和模板
- 动画
- 数据绑定
- 资源查找
2. 依赖属性的特点
- 属性值继承:子元素可以继承父元素的属性值
- 属性值变更通知:自动通知UI更新
- 属性值存储优化:只在值改变时存储实际值
- 支持动画和样式:可直接用于动画和样式设置
- 值强制转换:可通过验证和强制转换器控制值
3. 定义依赖属性的标准模式
using System.Windows;
using System.Windows.Controls;
public class CustomControl : Control
{
// 1. 定义依赖属性标识符
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register(
nameof(MyProperty), // 属性名称
typeof(string), // 属性类型
typeof(CustomControl), // 所属类型
new PropertyMetadata("默认值")); // 属性元数据
// 2. 定义CLR包装属性
public string MyProperty
{
get => (string)GetValue(MyPropertyProperty);
set => SetValue(MyPropertyProperty, value);
}
}
4. 依赖属性元数据选项
new PropertyMetadata(
defaultValue: "默认值", // 默认值
propertyChangedCallback: OnMyPropertyChanged, // 值改变回调
coerceValueCallback: CoerceMyProperty, // 值强制回调
isAnimationProhibited: false // 是否禁止动画
);
// 值改变回调示例
private static void OnMyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (CustomControl)d;
// 处理属性变化逻辑
}
// 值强制回调示例
private static object CoerceMyProperty(DependencyObject d, object baseValue)
{
var control = (CustomControl)d;
if (baseValue is string str && str.Length > 10)
{
return str.Substring(0, 10); // 限制最大长度为10
}
return baseValue;
}
5. 附加属性(Attached Property)
public class GridHelper
{
// 定义附加属性
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.RegisterAttached(
"Column", // 属性名称
typeof(int), // 属性类型
typeof(GridHelper), // 所属类型
new PropertyMetadata(0)); // 默认值
// CLR包装器 - 获取方法
public static int GetColumn(DependencyObject obj)
{
return (int)obj.GetValue(ColumnProperty);
}
// CLR包装器 - 设置方法
public static void SetColumn(DependencyObject obj, int value)
{
obj.SetValue(ColumnProperty, value);
}
}
XAML中使用:
<Grid>
<Button GridHelper.Column="1" Content="附加属性示例"/>
</Grid>
二、扩展属性(Attached Property)详解
1. 什么是扩展属性?
扩展属性(Attached Property)是一种特殊的依赖属性,它:
- 可以附加到任何DependencyObject上
- 由非所有者类型定义
- 通常用于提供附加功能
2. 扩展属性的应用场景
- 布局控制:如Grid.Row、Canvas.Left等
- 行为附加:为现有控件添加新功能
- 样式定制:在不修改原有控件的情况下添加新属性
3. 扩展属性实现示例
示例1:简单扩展属性
public class DragDropHelper
{
// 定义扩展属性