目录

WPF-依赖属性和附加属性

WPF 中的依赖属性(Dependency Property)附加属性(Attached Property) 是掌握 WPF 数据绑定和 UI 控件自定义的关键。

WPF 中的依赖属性和附加属性

在 WPF 中,依赖属性附加属性 是增强 UI 控件功能的武学秘笈,
它们帮助你创建动态、可绑定、易扩展的应用程序。

一、依赖属性(Dependency Property)

武侠比喻:依赖属性就像是内力的“渠道”,它依赖于“外界环境”,能被外部力量所影响。

WPF 控件通常不直接使用普通的 .NET 属性,而是通过 依赖属性 来代替。这是因为依赖属性支持 数据绑定、样式、动画等功能,而普通的 .NET 属性则不支持。

依赖属性的特点:

  • 自动支持数据绑定、动画、样式、模板
  • 可以通过 属性值计算 获取属性值(由 WPF 引擎计算)
  • 支持优先级:可以根据不同的来源(如控件本身、样式、数据绑定等)来确定属性值

如何定义依赖属性?

依赖属性是通过 DependencyProperty.Register 来注册的。

public class MyControl : Control
{
    // 定义一个依赖属性
    public static readonly DependencyProperty MyProperty =
        DependencyProperty.Register(
            "MyProperty",        // 属性名
            typeof(string),      // 属性类型
            typeof(MyControl),   // 所在控件类型
            new PropertyMetadata("默认值") // 默认值
        );

    // CLR 属性包装器
    public string MyProperty
    {
        get { return (string)GetValue(MyProperty); }
        set { SetValue(MyProperty, value); }
    }
}

解释:

  • MyProperty 是依赖属性的名字。
  • DependencyProperty.Register 用于注册依赖属性。
  • PropertyMetadata 中可以传入一个默认值,或者一个回调函数(用于处理属性变化)。

使用依赖属性:

MyControl control = new MyControl();
control.MyProperty = "新的值";  // 使用CLR属性
Console.WriteLine(control.MyProperty);  // 读取值

依赖属性的优势:

  • 支持数据绑定
    依赖属性支持与其他 UI 控件的绑定,当属性的值发生变化时,界面会自动更新。

    <TextBox Text="{Binding MyProperty}" />
  • 支持动画
    依赖属性可以参与 WPF 的动画系统。

    var animation = new DoubleAnimation
    {
        From = 0,
        To = 100,
        Duration = TimeSpan.FromSeconds(2)
    };
    Storyboard.SetTarget(animation, myControl);
    Storyboard.SetTargetProperty(animation, new PropertyPath(MyControl.MyProperty));
  • 支持样式
    你可以通过样式改变依赖属性的值。

二、附加属性(Attached Property)

武侠比喻:附加属性就像是“外功”,可以赋予本没有的能力给别人,不局限于你自己的武功体系。

附加属性通常用来给控件或元素添加额外的功能,最常见的用法是 布局系统。通过附加属性,可以让 WPF 元素具有某些特殊的行为,而无需直接修改它们的类。

附加属性的特点:

  • 允许为其他控件添加额外的属性
  • 不需要在控件自身定义附加属性
  • 常用场景:布局、事件、设计器支持等

如何定义附加属性?

附加属性通过 DependencyProperty.RegisterAttached 注册。

public static class MyAttachedProperties
{
    // 定义附加属性
    public static readonly DependencyProperty MyAttachedProperty =
        DependencyProperty.RegisterAttached(
            "MyAttached",           // 属性名
            typeof(string),         // 属性类型
            typeof(MyAttachedProperties),  // 附加属性所在类
            new PropertyMetadata("默认值") // 默认值
        );

    // 设置附加属性值
    public static void SetMyAttached(DependencyObject element, string value)
    {
        element.SetValue(MyAttachedProperty, value);
    }

    // 获取附加属性值
    public static string GetMyAttached(DependencyObject element)
    {
        return (string)element.GetValue(MyAttachedProperty);
    }
}

解释:

  • DependencyProperty.RegisterAttached 用于注册附加属性。
  • SetMyAttachedGetMyAttached 是帮助方法,用来设置和获取附加属性。

使用附加属性:

在 XAML 中,附加属性可以像普通属性一样使用,但需要使用附加属性的类来设置。

<Grid xmlns:local="clr-namespace:YourNamespace">
    <Button local:MyAttachedProperties.MyAttached="按钮附加属性" />
</Grid>

常见附加属性的例子:

  • Grid.RowGrid.Column:用于布局的附加属性。
  • Canvas.LeftCanvas.Top:控制控件位置的附加属性。

附加属性的优势:

  • 扩展控件功能
    你可以给已有的控件添加额外的行为或属性,而不必继承或修改控件本身。
  • 灵活性高
    附加属性可以被任何 DependencyObject 使用,而不限制于具体的控件类。

三、依赖属性 vs 附加属性

特性依赖属性附加属性注册方式DependencyProperty.RegisterDependencyProperty.RegisterAttached使用场景控件内部的动态属性、数据绑定、动画、样式等向控件或元素添加额外的功能,通常用于布局所属类在控件类内部定义在静态类中定义,通常应用于外部控件

关键点

  • 依赖属性 主要用于控件自身的动态属性,支持数据绑定、样式和动画。
  • 附加属性 主要用于扩展其他控件或元素的行为,尤其是布局系统中常见。

总结

关键点 依赖属性 附加属性

定义方式 DependencyProperty.Register DependencyProperty.RegisterAttached

使用方式 控件内部使用 外部控件或元素使用

常见用途 数据绑定,样式,动画 扩展功能,布局控制