依赖属性背后的框架机制是什么?

问题描述 投票:18回答:4

我已经在几本书中读到了依赖属性,但是它们都有一个共同点,它们只是告诉我们它们是如何实现的(使用static readonly DependencyProperty等),而没有告诉它们从内部工作的确切方式。

我的意思是它们被实现为静态,但仍然适用于所有对象。第二点困惑是附加属性。

有没有可用的教程可以轻松解释所有这些概念?

c# wpf dependency-properties
4个回答
32
投票
我关于依赖项属性如何工作的思维模型:

任何DependencyObject类实现两个特殊属性。一个是类的静态属性,是DependencyProperty对象的字典。该类的每个实例都可以在字典中查找有关每个DependencyProperty的元信息-属性的名称,其类型,在获取和设置时必须调用的任何回调,它如何参与属性继承等等。注册依赖项属性时,您正在向此字典添加一个条目。

另一个属性是一个实例属性:这是一个由DependencyProperty键控的字典,它包含每个DependencyProperty的本地

value(如果已设置)。

在CLR属性的setter和getter中实现的[SetValueGetValue方法基本上是对类固醇的惰性评估。他们没有在后备字段中存储和检索属性的值,而是在值字典中存储和检索属性的值。

依赖属性的魔力在于GetValueSetValue的实际作用。

GetValue在对象的值字典中查找属性的值。如果找不到,它将在父元素上调用GetValue,以获取父元素认为的值。例如,当您在TextBox中创建Window时,任何看TextBoxFontFamily的对象实际上都是在调用GetValue。除非您明确设置字体,否则在其字典中没有该属性的条目。因此,GetValue向父元素询问该值。父元素可以设置FontFamily,也可以不设置。如果不是,则调用GetValue

its

以从its父级返回值。依此类推,直到到达Window对象并找到实际的FontFamily值。如果在FontFamily上设置TextBox,则SetValue将值存储在值字典中。下次需要获取该FontFamilyTextBox值时,GetValue在字典中找到该值并将其返回,因此不需要询问父元素。

如果在FontFamily上设置Window,则SetValue不仅会更新Window的值字典中的值,还会触发一个属性更改事件,所有依赖于该属性的事件都会听到。 (记住,这就是为什么它们被称为依赖属性的原因。)如果依赖于该属性的事物本身是依赖属性,则它会触发自己的属性更改事件。就是这样,更改FontFamily上的Window会更改窗口中每个控件的字体,并提示WPF重新呈现已更改的控件。

附加属性使用相同的方法工作。任何可以具有附加属性的对象都具有一个字典,该属性存储了附加属性的值。在XAML中将Grid.Column设置为CheckBox时,您只是在该CheckBox的字典中添加了一个条目。当Grid需要知道CheckBox在哪一列时,它将从该字典中查找值。当您在对象上将Grid.IsSharedSizeScope设置为True时,该对象的字典将包含一个新属性-字典,其中每个SharedSizeKey都包含宽度/高度。

我应该强调,这是我的心理模型。我没有坐在Reflector上,而是研究了RegisterGetValueSetValue

actual

实现,以了解它们的实际工作方式。我可能在细节上是错的。但这是一个可以准确预测这些东西的行为的模型,因此足够好。
在字典中存储属性值的概念对于C#程序员来说很奇怪。不过,这对Python程序员来说是一顶老帽子。在Python中,所有类属性(实际上是所有对象)都存储在词典中,因此您可以通过属性访问器或通过查找它们来获取它们的值。依赖属性和附加属性只是.NET窃取Java值得窃取的所有内容而如今掠夺Python的另一种方式。 (或者从Python掠夺的任何地方。)学习Python使我成为了一个更好的C#程序员。我将其推荐给尚未完成的任何C#开发人员。

6
投票
这里是有关依赖项属性http://www.wpftutorial.net/DependencyProperties.html的教程,对它们如何工作进行了一些解释。

2
投票
[只看joshsmith的这篇文章,其中还有一些其他信息

2
投票
[您可以在下面看到dependency property的一个非常基本的示例,该示例创建了一个custom control text box,其中不允许有空格,这意味着用户无法在文本框中键入空格。
© www.soinside.com 2019 - 2024. All rights reserved.