gpt4 book ai didi

WPF:依赖属性与常规 CLR 属性的区别是什么?

转载 作者:行者123 更新时间:2023-12-04 13:00:35 26 4
gpt4 key购买 nike

在 WPF 中,作​​为“依赖属性”究竟意味着什么?

我读了微软的 Dependency Properties Overview ,但对我来说并没有真正陷入困境。那篇文章的部分内容是:

Styles and templates are two of the chief motivating scenarios for using dependency properties. Styles are particularly useful for setting properties that define application user interface (UI). Styles are typically defined as resources in XAML. Styles interact with the property system because they typically contain "setters" for particular properties, as well as "triggers" that change a property value based on the real-time value for another property.



然后示例代码是这样的:
<Style x:Key="GreenButtonStyle">
<Setter Property="Control.Background" Value="Green"/>
</Style>
....
<Button Style="{StaticResource GreenButtonStyle}">I am green!</Button>

但我不明白这有什么特别之处。这是否只是暗示,当我设置 Style 时在给定样式的按钮上,我实际上正在设置 Background隐含的?这是关键吗?

最佳答案

这是我一直希望有人为我写的关于依赖属性如何工作的解释。它不完整并且很可能是错误的,但它会帮助您对它们有足够的理解,从而能够掌握您阅读的文档。

依赖属性是类似属性的值,通过 DependencyObject 的方法获取和设置。类(class)。它们可以(并且通常确实)看起来非常像 CLR 属性,但它们不是。这是关于他们的第一个令人困惑的事情。依赖属性实际上由几个组件组成。

下面是一个例子:
DocumentRichTextBox 的属性目的。这是一个真正的 CLR 属性。也就是说,它具有名称、类型、getter 和 setter,就像任何其他 CLR 属性一样。但与“正常”属性不同,RichTextBox property 不仅仅在实例中获取和设置私有(private)值。在内部,它是这样实现的:

public FlowDocument Document
{
get { return (FlowDocument)GetValue(DocumentProperty); }
set { SetValue(DocumentProperty, value); }
}

当您设置 Document ,您传入的值将传递给 SetValue ,以及 DocumentProperty .那是什么?以及如何 GetValue得到它的值(value)?还有……为什么?

首先是什么。 RichTextBox 上定义了一个静态属性命名 DocumentProperty .当这个属性被声明时,它是这样完成的:
public static DependencyProperty DocumentProperty = DependencyProperty.Register(
"Document",
typeof(FlowDocument),
typeof(RichTextBox));
Register在这种情况下,方法告诉依赖属性系统 RichTextBox - 类型,而不是实例 - 现在有一个名为 Document 的依赖属性类型 FlowDocument .此方法存储此信息...某处。确切地说,是一个对我们隐藏的实现细节。

当 setter 为 Document属性(property)电话 SetValue , SetValue方法查看 DocumentProperty参数,验证它确实是属于 RichTextBox 的属性还有那个 value是正确的类型,然后将其新值存储在...某处。 DependencyObject 的文档对这个实现细节很腼腆,因为你真的不需要知道它。在我关于这些东西如何工作的心智模型中,我假设有一个类型为 Dictionary<DependencyProperty, object> 的属性。这是 DependencyObject 的私有(private)信息,所以派生类(如 RichTextBox )看不到它,但 GetValueSetValue可以更新它。但谁知道呢,也许是僧侣写在羊皮纸上。

无论如何,这个值现在就是所谓的“本地值”,也就是说它是这个特定的本地值 RichTextBox ,就像一个普通的属性(property)。

这一切的重点是:
  • CLR 代码不需要知道属性是依赖属性。它看起来与任何其他属性(property)完全一样。您可以拨打GetValueSetValue获取和设置它,但除非您正在对依赖属性系统做一些事情,否则您可能不需要。
  • 与普通属性不同,在获取和设置它时可以涉及到它所属的对象以外的其他东西。 (可以想象,您可以通过反射来做到这一点,但反射很慢。在字典中查找内容很快。)
  • 这个东西——它是依赖属性系统——本质上位于一个对象和它的依赖属性之间。它可以做各种各样的事情。

  • 什么样的东西?好吧,让我们看一些用例。

    捆绑。 当您绑定(bind)到一个属性时,它必须是一个依赖属性。这是因为 Binding object 实际上并没有在目标上设置属性,它调用 SetValue在目标对象上。

    样式。 当您将对象的依赖属性设置为新值时, SetValue告诉样式系统你已经这样做了。这就是触发器的工作原理:依赖属性系统告诉它们,它们不会通过魔法发现属性的值发生了变化。

    动态资源。 如果你写 XAML 像 Background={DynamicResource MyBackground} ,您可以更改 MyBackground 的值资源,并且引用它的对象的背景会更新。这也不是魔法。动态资源调用 SetValue .

    动画。 动画通过操纵属性值来工作。这些必须是依赖属性,因为动画正在调用 SetValue去对付他们。

    更改通知。 当你注册一个依赖属性时,你还可以指定一个函数 SetValue将在设置属性值时调用。

    值(value)传承。 注册依赖属性时,可以指定它参与属性值继承。当您拨打 GetValue获取对象依赖属性的值, GetValue查看是否有本地值。如果没有,它将遍历父对象链,查看该属性的本地值。

    这就是您可以设置 FontFamily 的方式在 Window并且神奇地(我经常使用这个词)窗口中的每个控件都使用新字体。此外,这就是为什么您可以在一个窗口中拥有数百个控件而每个控件都没有 FontFamily成员变量来跟踪它们的字体(因为它们没有本地值)但您仍然可以设置 FontFamily在任何一个控件上(因为每个 DependencyObject 都有的 seekrit 隐藏值字典)。

    关于WPF:依赖属性与常规 CLR 属性的区别是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2323082/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com