DependencyProperty.Register 和 DependencyProperty.RegisterAttached 这两个方法都属于 WinUI 3(Windows App SDK)中的 Microsoft.UI.Xaml 命名空间,用于注册依赖属性,但用途和语义有显著区别。
🔍 一、总体对比概览
| 特性 | Register | RegisterAttached |
|---|---|---|
| 用途 | 注册普通依赖属性(属于自身类) | 注册附加属性(可被其他类使用) |
| 定义位置 | 在属性所属类中定义 | 在拥有该附加属性的类中定义(通常是服务类或布局类) |
| 调用时机 | 类初始化时(静态构造) | 类初始化或应用启动时 |
| 典型场景 | 自定义控件的属性(如 MyControl.Value) | 布局系统(如 Grid.Row)、行为扩展 |
| Getter/Setter 模式 | 普通属性包装(GetValue/SetValue) | 必须提供 GetXXX 和 SetXXX 静态方法 |
| 返回值用途 | 存入 public static readonly 字段 | 存入 public static readonly 字段 |
📚 二、逐项分析两个方法的描述
1. DependencyProperty.Register(普通依赖属性注册)
✅ 方法签名(C#)
public static DependencyProperty Register(
string name,
Type propertyType,
Type ownerType,
PropertyMetadata typeMetadata)✅ 参数说明(来自网页)
name: 要注册的依赖属性的名称(如"Value")。propertyType: 属性的类型(如typeof(int))。ownerType: 注册该属性的类的类型(如typeof(MyControl))。typeMetadata: 属性元数据,可包含默认值、属性变更回调等。
✅ 返回值
- 一个
DependencyProperty标识符,应赋值给类中的public static readonly字段(如ValueProperty)。
✅ 关键描述(来自网页)
“Registers a dependency property with the specified property name, property type, owner type, and property metadata for the property.”
“Use this method when defining or initializing a DependencyObject derived class that will own the registered dependency property.”
“A dependency property identifier that typically is stored in a public static readonly field in your DependencyObject derived class.”
“How to register a custom dependency property is described in detail (with examples) in the topic Custom dependency properties.”
✅ 示例代码(简化)
public class MyControl : Control
{
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(int),
typeof(MyControl),
new PropertyMetadata(0)
);
public int Value
{
get => (int)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
}✅ 重点:这是为
MyControl自身定义一个叫Value的属性。
2. DependencyProperty.RegisterAttached(附加属性注册)
✅ 方法签名(C#)
public static DependencyProperty RegisterAttached(
string name,
Type propertyType,
Type ownerType,
PropertyMetadata defaultMetadata)✅ 参数说明(与 Register 几乎相同)
name: 附加属性的名称(如"Dock")。propertyType: 属性类型。ownerType: 拥有该附加属性的类的类型(如typeof(DockPanel))。defaultMetadata: 默认元数据。
✅ 返回值
- 同样是一个
DependencyProperty标识符,也应存入public static readonly字段。
✅ 关键描述(来自网页)
“Registers an attached dependency property with the specified property name, property type, owner type, and property metadata for the property.”
“A dependency property identifier that should be used to set the value of a public static readonly field in your class. That identifier is then used to reference the attached property later, for operations such as setting its value programmatically or attaching a Binding.”
示例代码:
public abstract class AquariumServices : DependencyObject
{
public enum Buoyancy { Floats, Sinks, Drifts }
public static readonly DependencyProperty BuoyancyProperty =
DependencyProperty.RegisterAttached(
"Buoyancy",
typeof(Buoyancy),
typeof(AquariumServices),
new PropertyMetadata(Buoyancy.Floats)
);
// 必须提供静态 Get/Set 方法
public static void SetBuoyancy(DependencyObject element, Buoyancy value)
{
element.SetValue(BuoyancyProperty, value);
}
public static Buoyancy GetBuoyancy(DependencyObject element)
{
return (Buoyancy)element.GetValue(BuoyancyProperty);
}
}✅ 重点:
AquariumServices类本身可能不是 UI 元素,但它“提供”了一个可以被其他 UI 元素使用的属性Buoyancy。
🔁 三、核心区别总结
| 对比维度 | Register | RegisterAttached |
|---|---|---|
| 属性归属 | 属性属于 ownerType 类自身 | 属性由 ownerType 类“提供”,但可被任何 DependencyObject 子类使用 |
| 使用方式 | 实例直接访问:control.Value = 100; | 静态方法访问:DockPanel.SetDock(button, Dock.Left); |
| XAML 语法 | <local:MyControl Value="100" /> | <Button local:DockPanel.Dock="Left" /> |
| 设计意图 | 扩展控件自身功能 | 实现“跨类扩展”或“服务注入”机制 |
| Getter/Setter | 普通实例属性包装 | 必须提供 public static GetXXX 和 SetXXX 方法 |
| 典型应用 | 自定义控件属性 | 布局(Grid.Row)、行为(i:InvokeCommandAction)、附加服务 |
🎯 四、通俗类比
| 类比 | Register | RegisterAttached |
|---|---|---|
| 现实比喻 | 给手机加一个“音量键”功能 | 给所有电器加一个“智能插座”状态(如“是否通电”) |
| 代码比喻 | 为 Person 类添加 Age 属性 | 为所有 UIElement “附加”一个 TooltipService.ToolTip 属性 |
| XAML 比喻 | <Button Content="OK" /> | <Button ToolTip="点击提交" /> |
✅ 五、总结:两个方法的本质区别
Register | RegisterAttached | |
|---|---|---|
| 谁拥有? | 属性属于类自己 | 类“提供”属性,但别人使用 |
| 怎么用? | 实例属性访问 | 静态方法 + XAML 扩展语法 |
| 为什么用? | 实现控件的可绑定属性 | 实现跨类功能扩展(布局、行为、服务) |