5

(我对这个概念完全陌生,所以我可能会问一些非常基本的问题。)

使用以下代码注册依赖属性:

public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata);

从逻辑上讲,它只是将属性名称与所有者类型相关联。

因此,如果我有多个所有者类型的实例,并且每个实例都将 DP 设置为不同的值。

如何存储这些值?

更新 1 - 2013 年 10 月 30 日上午 10:04

我从这里了解了附加属性:http ://wpftutorial.net/DependencyProperties.html

附加属性

附加属性是一种特殊的 DependencyProperties。它们允许您将值附加到对该值一无所知的对象。

这个概念的一个很好的例子是布局面板。每个布局面板都需要不同的数据来对齐其子元素。Canvas 需要 Top 和 Left,DockPanel 需要 Dock 等。由于您可以编写自己的布局面板,因此列表是无限的。所以你看,不可能在所有 WPF 控件上都拥有所有这些属性。

解决方案是附加属性。它们由在特定上下文中需要来自另一个控件的数据的控件定义。例如,由父布局面板对齐的元素。

所以在下面的代码片段中:

<Canvas>
    <Button Canvas.Top="20" Canvas.Left="20" Content="Click me!"/>
    <Button Canvas.Top="40" Canvas.Left="20" Content="Click me!"/>
</Canvas>

显然我们不能将所有的对齐属性,如TopLeft给 Button。所以 Canvas 定义了这样的属性,它们被“附加”到 Button 控件。

当 Canvas.Top 在 XAML 中被指定为 Button 的“属性”时,它将调用在 Canvas 类型中定义的 SetTop() 方法。并且 Button 作为元素参数传入。 我认为这就是 Canvas 知道哪个 Button 使用哪个 Top 值的方式。

public static void SetTop(UIElement element, double length);

但我不明白为什么附加属性必须是依赖属性? 他们之间有什么联系?

谢谢!

4

3 回答 3

4

通常,当我们定义 a 时DependencyProperty,我们还定义了一个 CLR 'wrapper',它使我们能够使用DependencyPropertyin 代码:

public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
    "Items", typeof(ObservableCollection<string>), typeof(MainWindow), 
     new UIPropertyMetadata(new ObservableCollection<string>()));

public ObservableCollection<string> Items
{
    get { return (ObservableCollection<string>)GetValue(ItemsProperty); }
    set { SetValue(ItemsProperty, value); }
}

在这里,您可以看到@Clemens 所说的GetValue和方法。我们可以在 a和/或SetValue中访问这些方法,因为它们都扩展了类。您还可以看到这里的属性 is not ... 它只是that is的定义。WindowUserControlDependencyObjectItems staticDependencyPropertystatic


更新>>>

询问为什么 Attached Property 必须是 a 并没有什么意义DependencyProperty因为在 .NET 中,它们只是……它们就是这样设计的。一个更好的问题可能是,附属财产从成为DependencyProperty.

这个问题的答案就像被问到一个财产从成为一个财产中得到什么好处一样DependencyProperty主要的好处是这些属性可以用于Bindings、Styles、AnimationsResources等。对于任何 WPF 开发人员,可以从 MSDN 上的两个非常重要的页面(已在评论中链接到)找到更多详细信息:

依赖属性概述

附加属性概述

于 2013-10-29T15:45:07.370 回答
3

要回答您的问题,我需要从依赖系统的基础知识开始(您已经知道下面的大部分内容,但我认为阅读后您的问题可能会自行回答)

DependencyProperty应该在派生的类中定义,DependencyObject因为DependencyObject实现了一些方法和成员(其中大多数是私有的,开发人员看不到它们)。这些实现提供了DependencyObject使用对类的静态引用(而不是对类的实例的引用)来存储和检索数据的能力

我们存储和检索数据的方式是通过DependencyProperty' 包装器或直接通过 GetValue 和 SetValue(它们是DependencyObject' 的方法)或通过绑定。无论哪种方式,静态DependencyProperty都是找到正确值的“关键”。

当您注册 aDependencyProperty时,会通知 Dependency 系统将新DependencyProperty添加到其资源中(类似于列表,填充您已注册的 DependencyProperties)。现在,如果您将某些内容存储为[this.]SetValue(MyProperty, value),则本质上是在更新对象的资源this(您可以将其想象为this.Resources[MyProperty])。

这就像外部的普通属性一样工作,但考虑到UIPropertyMetadata其他Dependency东西,您DependencyProperty配备了一些独特的能力来强制,参与动画,更改时通知等,并且可以做的不仅仅是一个简单的属性。

还记得扩展名吗?

public static void MyExtension(this MyType target, string parameter, ...)
{
    target.MyFunction(parameter, ...);
}
var t = new MyType();
t.MyExtension("test");

AttachedProperty某种程度上是DependencyProperty和扩展的结合,有一些区别:

  1. 的包装AttachedProperty器是静态的,并且将类引用作为输入以了解它们的附加位置。a 的目标DependencyProperty通常是this(除非您将 GetValue 和 SetValue 更改为类似的东西otherObject.SetValue(MyProperty, value))。但与 不同DependencyProperty的是,an 的目标AttachedProperty(必须是DependencyObject本身)作为参数传递给它。再次,它必须是 a 的原因DependencyObject是只有 aDependencyObject能够拥有一组资源来存储 a DependencyProperty

  2. DependencyPropertywhich uses不同RegisterAttachedProperty使用RegisterAttached方法告诉依赖系统其他DependencyObjects 可以具有此属性,但实际的静态属性仍存储在DependencyObject具有AttachedProperty.

  3. 在 Extension 中,this在它的第一个参数用于“扩展”它旁边的类型之前。在AttachedProperty没有this,事实上它总是DependencyObject被扩展的类。

  4. 与 不同AttachedProperty的是,除非您编写几行类似于AttachedProperty. 例如实现一个静态列表KeyValuePairs(实际数据的值和知道它们属于谁的键)


编辑:

在克莱门斯的评论之后,我需要补充一点,AttachedProperty这实际上并不是一个扩展。我提出扩展的原因是,通过比较这两者,您可以看到普通属性无法附加到 a 的DependencyObject原因,因为为了将数据存储在其他对象中,需要一些像 Resource 这样的集合(DependencyObject有) .

于 2013-11-04T15:52:26.760 回答
3

我一直将其视为DependencyProperties与普通属性不同的属性定义。

属性定义包含属性类型、名称、默认值等,并包含一个指针,显示在哪里可以找到属性值。但它不包含值本身。

这允许您DependencyProperties在绑定中使用,因为您可以将属性设置为从绑定表达式而不是从对象本身获取其值。

这很重要,AttachedProperties因为它们的值并不存在于它们所附加的对象上。他们需要能够在与对象本身不同的位置查找其值,并DependencyProperties允许这样做。

您不能对常规属性执行此操作,因为普通属性的值应在对象本身上找到,但AttachedProperty在它所附加的对象上不存在。

那是简单的版本。:)

于 2013-11-05T20:01:48.533 回答