# WPF 属性体系详解:ap(附加属性)、dp(依赖属性)、do(DependencyObject)

## 1. 依赖对象(do - DependencyObject)

### 定义
在WPF中,所有支持依赖属性的基类都继承自 `DependencyObject`。

### 作用
提供机制存储依赖属性(`DependencyProperty`)和值。

### 示例代码
```csharp
public class TextBlockHelper
{
    // 示例:通过Get/Set操作依赖属性
    public static string GetTitle(DependencyObject obj) => (string)obj.GetValue(TitleProperty);
    public static void SetTitle(DependencyObject obj, string value) => obj.SetValue(TitleProperty, value);
}

用途

  • 为对象动态存储和获取绑定属性

  • 响应属性变换

2. 依赖属性(dp - DependencyProperty)

定义

一种特殊的属性,用于支持绑定、样式、动画等WPF特性。

注册方式

通过 DependencyProperty.Register 静态方法注册。

示例代码

csharp

public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
    "Title",
    typeof(string),
    typeof(TextBlockHelper),
    new PropertyMetadata(null, callback)
);

参数说明

参数

说明

"Title"

依赖属性的名称

typeof(string)

属性类型

typeof(TextBlockHelper)

所属的注册类

new PropertyMetadata(null, callback)

默认值,及值变化的回调函数

使用方式

  • 设置值

    csharp

    TextBlockHelper.SetTitle(someObject, "示例标题");
  • 获取值

    csharp

    string title = TextBlockHelper.GetTitle(someObject);

3. 附加属性(ap - Attached Property)

定义

一种特殊的依赖属性,用于"附加"在其他控件上,为控件赋予额外的功能或状态。

注册方式

csharp

public static readonly DependencyProperty TitleProperty = DependencyProperty.RegisterAttached(
    "Title",
    typeof(string),
    typeof(TextBlockHelper),
    new PropertyMetadata(null, callback)
);

Setter/Getter

csharp

public static string GetTitle(DependencyObject obj) => (string)obj.GetValue(TitleProperty);
public static void SetTitle(DependencyObject obj, string value) => obj.SetValue(TitleProperty, value);

用途

  • 可以在XAML中作为属性使用:

    xml

    <TextBlock local:TextBlockHelper.Title="显示的标题" />

重要特点

  • 可绑定:可以绑定到数据源

  • 用于:布局控制、行为扩展、样式等

4. 属性变化的回调(callback 方法)

定义

当绑定目标的依赖属性值发生变化时,callback会被调用,用于响应变化。

示例代码

csharp

private static void callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    // 实现逻辑:如更新UI、触发动画等
    throw new NotImplementedException();
}

触发时机

  • 属性首次设置(初始化)

  • 绑定源变化

  • 通过代码调用 SetValue 修改

5. 结合示例

代码片段

csharp

public class TextBlockHelper
{
    public static string GetTitle(DependencyObject obj) => (string)obj.GetValue(TitleProperty);
    public static void SetTitle(DependencyObject obj, string value) => obj.SetValue(TitleProperty, value);
    
    public static readonly DependencyProperty TitleProperty = DependencyProperty.RegisterAttached(
        "Title",
        typeof(string),
        typeof(TextBlockHelper),
        new PropertyMetadata(null, callback)
    );

    private static void callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        throw new NotImplementedException(); // 属性变更可能会用到的逻辑
    }
}

作用

  • 定义了一个附加属性 Title,可以附加到任何支持 DependencyObject 的控件

  • Title 的值发生变化,callback 会被调用,可以写具体逻辑(更新UI、触发动画等)

6. 小结

概念

作用

使用场景

DependencyObject (do)

能存储和管理依赖属性

所有支持依赖属性的对象基类

DependencyProperty (dp)

注册和定义具体属性

支持绑定、样式、动画等

附加属性 (ap)

扩展控件,使其他控件也能拥有自定义属性

设计灵活、复用性强的UI行为

7. 简单示意图

text

+--------------------------------------------------+
| DependencyObject (控件)                           |
| +----------------------------------------------+ |
| | DependencyProperty (Title)                   | |
| +----------------------------------------------+ |
|                                                  |
| (支持绑定/样式/动画)                            |
+--------------------------------------------------+

附加属性(ap):可以附加到任何 DependencyObject,扩展其功能

不会做游戏