什么时候应该在 WPF 中使用依赖属性?

Posted

技术标签:

【中文标题】什么时候应该在 WPF 中使用依赖属性?【英文标题】:When should I use dependency properties in WPF? 【发布时间】:2013-09-06 17:00:21 【问题描述】:

它们是静态的,因此与使用 .NET 属性相比,我们可以节省大量内存。 使用依赖属性而不是 .NET 属性的其他好处是: 1)无需检查线程访问 2) 提示一个包含元素被渲染 等等……

所以看来我应该总是在我使用 WPF 的项目中使用依赖属性?

也许对于助手类的一些琐碎属性我可以 摆脱 .NET 属性...

【问题讨论】:

***.com/questions/5193144/…, ***.com/questions/617312/… 重要的是,依赖属性只能用于从 DependencyObject 继承的对象。不在 ViewModel 上使用它们的原因之一,因此并不总是在 WPF 项目中。它们对性能的影响也很小。 我不知道你为什么说“不需要检查线程访问”?据我所知,如果您从另一个线程而不是 UI 线程设置依赖属性的值,则会引发异常。 依赖属性不是静态的,不会节省任何内存。只有属性的定义是静态的。所有依赖属性都绑定到一个对象引用,因此该属性确实会为每个实例占用一块内存。 【参考方案1】:

依赖属性是一个宽泛的概念来解释它可能需要几页来编写。因此,只是为了回答您的主要问题,在哪里使用 Dependency 属性

    您知道该属性将成为绑定目标,即您正在创建用户控件/自定义控件并希望属性应该是绑定驱动的。

    您需要自动属性更改通知(强制和验证)。

    我们希望在样式、主题、父级或默认值中继承值。

    大多数时候不需要在 Model 或 ViewModel 层上创建属性作为依赖属性,因为这对节省内存没有太大帮助,因为我们在 model/VM 中定义的大多数属性都会每个实例都有值,因为它们会不断变化。解析 Dependency 属性值本身就是一种负担,因此不建议不必要地进行属性依赖。

谢谢

【讨论】:

是的,样式和动画是您必须使用依赖属性的一种上下文。 当您希望能够通过 XAML 绑定其值时,也应该使用它。 这不是一个完整的答案。您基本上需要为要在 XAML 中使用的所有属性定义依赖项属性。这是与 Silverlight 的主要区别,它允许您在 XAML 中使用普通属性。【参考方案2】:

创建DependencyProperty 的主要原因是当您编写自己的 WPF 控件时。 DependencyProperties 可以作为绑定源和目标,并且可以动画。 所有框架控件的属性都实现为DependencyProperty,这就是为什么您可以在XAML中进行强大的数据绑定。

但是在大​​多数情况下,例如在 MVVM 模式中,您不需要依赖属性,INotifyPropertyChanged 就足够了。

【讨论】:

【参考方案3】:

主要区别在于,普通 .NET 属性的值是直接从类中的私有成员读取的,而 DependencyProperty 的值是在调用从 DependencyObject 继承的 GetValue() 方法时动态解析的。

当您设置依赖属性的值时,它不会存储在对象的字段中,而是存储在基类 DependencyObject 提供的键和值的字典中。条目的键是属性的名称,值是您要设置的值。

依赖属性的优点是

    减少内存占用: 当您认为 UI 控件的 90% 以上的属性通常保持其初始值时,为每个属性存储一个字段是一种巨大的浪费。依赖属性通过仅在实例中存储修改后的属性来解决这些问题。默认值在依赖属性中存储一次。 值继承: 当您访问依赖属性时,使用值解析策略来解析值。如果没有设置本地值,则依赖属性会向上导航逻辑树,直到找到一个值。当您在根元素上设置 FontSize 时,它​​将应用于下面的所有文本块,除非您覆盖该值。 更改通知: 依赖属性具有内置的更改通知机制。通过在属性元数据中注册回调,您会在属性值发生更改时收到通知。这也被数据绑定使用。

查看下面的网址了解更多关于它背后的魔法的详细信息

dependency properties in WPF

【讨论】:

你基本上复制了这里的 msdn 文档而没有给出有用的评论。是的,所有这些都很好,但是你有什么建议,总是使用依赖属性?【参考方案4】:

CLR 属性与依赖属性

CLR 属性直接从类的私有成员中读取。类的 Get() 和 Set() 方法检索和存储属性的值。 而当您设置依赖属性的值时,它不会存储在对象的字段中,而是存储在基类 DependencyObject 提供的键和值的字典中。条目的键是属性的名称,值是您要设置的值。

依赖属性的优点 更少的内存消耗

依赖属性仅在更改或修改时存储属性。因此,大量的字段内存是空闲的。

属性值继承 这意味着如果没有为属性设置值,那么它将返回到继承树,直到它获取值。

更改通知和数据绑定 每当属性更改其值时,它都会使用 INotifyPropertyChange 在 Dependency Property 中提供通知,并且还有助于数据绑定。

参与动画、样式和模板 依赖属性可以设置动画,使用样式设置器设置样式,甚至为控件提供模板。

回调 每当更改属性时,您都可以调用回调。

资源 您可以为 XAML 中的依赖属性定义定义资源。

覆盖元数据 您可以使用 PropertyMetaData 定义依赖属性的某些行为。因此,从派生属性覆盖元数据不需要您重新定义或重新实现整个属性定义。

【讨论】:

“CLR 属性直接从类的私有成员中读取。”这是完全错误的。 CLR 属性映射到 getter/setter 函数。【参考方案5】:

也许您应该再看看 MSDN 上的 Dependency Properties Overview 页面。

就个人而言,我只会在我真正需要时创建DependencyProperty。在大多数情况下,我在数据类型和视图模型类中使用普通的 CLR 属性来绑定……这绝对没问题,只要我实现了INotifyPropertyChanged 接口。

所以对于我所有常用的数据绑定,我使用普通的 CLR 属性。我声明了一个Dependency Property,以便在UserControl 中提供一些附加功能。

【讨论】:

【参考方案6】:

当您希望在UserControl 中进行数据绑定时使用依赖属性,它是 WPF 框架控件数据绑定的标准方法。 DP 有slightly better binding performance,当在UserControl 中实现它们时,所有东西都提供给你。

否则,您通常使用INotifyPropertyChanged 在其他地方进行绑定,因为它更容易在独立类中实现并且开销更少。就您最初的假设而言:

    您的变量有一个本地实例,您绝对不会为属性节省任何开销,因为内置了重要的数据绑定逻辑。 They must be accessed on the main thread。

【讨论】:

那不正确,至少不准确。是的,依赖属性可以用在 UserControls 上,也可以用在 CustomControls 上,基本上每个派生自 DependencyObject 的对象。

以上是关于什么时候应该在 WPF 中使用依赖属性?的主要内容,如果未能解决你的问题,请参考以下文章

何时使用 WPF 依赖属性与 INotifyPropertyChanged

在依赖属性 WPF 上使用绑定时出现问题 [重复]

WPF属性依赖属性

WPF入门教程系列十三——依赖属性

WPF依赖属性详解

WPF中Line控件怎么添加依赖属性,这个类是密封的不能被继承!