C# 为什么DependencyProperties需要facade属性/getter/setter
我使用WPF已经有一段时间了。但我仍然想知道,为什么在定义DependencyProperties时需要这些facade属性 这就是我的意思。要定义DependencyProperty,必须编写如下内容:C# 为什么DependencyProperties需要facade属性/getter/setter,c#,wpf,xaml,C#,Wpf,Xaml,我使用WPF已经有一段时间了。但我仍然想知道,为什么在定义DependencyProperties时需要这些facade属性 这就是我的意思。要定义DependencyProperty,必须编写如下内容: 公共静态从属属性IsActivityProperty= DependencyProperty.Register(“IsActive”)、typeof(bool)、typeof(MyClass), 新的FrameworkPropertyMetaData(假)); 但你也必须写: public
公共静态从属属性IsActivityProperty=
DependencyProperty.Register(“IsActive”)、typeof(bool)、typeof(MyClass),
新的FrameworkPropertyMetaData(假));
但你也必须写:
public bool IsActive
{
get => (bool)GetValue(IsActiveProperty);
set => SetValue(IsActiveProperty, value);
}
如果不定义“IsActive”属性,代码将不会运行。它将编译,但如果在XAML代码中使用“IsActive”,程序将崩溃
但是:IsActive的接受者和接受者从来没有被称为系统本身总是直接调用SetValue()
和GetValue()
。我自己也不使用这些属性(如果我在代码隐藏中需要它们,我也可以直接调用SetValue
和GetValue
)
所以,如果它们从未被使用过,为什么我不能省略这些属性呢?有人能给我解释一下吗?WPF调用GetValue和SetValue,而不是调用我们的属性访问器。因为WPF不使用我们的属性访问器,所以永远不会到达断点 属性访问器是必需的。如果我们不提供它们,那么我们就不能在XAML中引用它们;相反,如果我们提供了它们,那么我们可以在XAML中引用它们 如果我们引用XAML中的属性访问器,但它们不存在,那么我们的程序将绝对无法编译 为什么需要门面: 使用当前的XAML解析器,XAML类型映射到CLR类型 : …XAML本身是CLR运行时直接使用的公共语言之一,而不是XAML类型映射到CLR类型,以便在解析WPF的XAML时实例化运行时表示 : 根据XAML语言规范级别,XAML类型可以映射到任何其他类型系统,不必是CLR,但这需要创建和使用不同的XAML解析器 这就是为什么这段代码:
<Window.Resources>
<local:ViewModel x:Key="key" IsActive="true"/>
</Window.Resources>
get
{
var val = (bool)GetValue(IsActiveProperty);
DoCustomThing(val);
return val;
}
set
{
SetCustomThing(value);
SetValue(IsActiveProperty, value);
}
或者这个:
public bool IsActive
{
get { return false; }
set { }
}
将与此代码完全等效:
public bool IsActive
{
get => (bool)GetValue(IsActiveProperty);
set => SetValue(IsActiveProperty, value);
}
这就是为什么在文档中明确提到不应该在依赖项属性的getter和setter中编写任何内容的原因。(从XAML运行的代码与从后台运行的代码不同是一种不好的做法。换句话说:不要触摸getter/setter)
改用PropertyChangedCallback
或强制值回调
为什么需要依赖性属性:
XAML属性系统。此外,一些WPF功能(如动画)需要dependencProperty
出于实现原因,将属性标识为依赖性属性并访问属性系统SetValue方法对其进行设置,而不是使用属性包装器及其setter,在计算上成本较低
dependencProperty
是XAML
唯一的内容。XAML可以按照dependencProperty.Register
中定义的名称解析绑定路径。当将依赖对象
树绑定到数据上下文
时,XAML不会查找getter和setter,因为它已经从注册的信息中了解了关于它的一切
请注意,dependencProperty
对象必须是public
,因为dependencProperty.Register
将其添加到其父DependencyObject
的ResourceDictionary
中,绑定系统将在那里找到它
例如,这段xaml代码:
<StackPanel>
<CheckBox IsChecked="{Binding Path=IsActive}"/>
<CheckBox IsChecked="{Binding Path=IsActive}"/>
</StackPanel>
尽管您可以将公共属性分配给Binding.Path
。它可以使用公共索引器、公共集合、附加属性和依赖属性
欲了解更多信息,请阅读
结论:
如果删除getter和setter:
您将很难从C#访问DependencyProperty
(有时您可能会故意删除一个访问器或整个包装器)
如果在XAML中的任何位置使用该DependencyProperty
(除了BindingPath
),代码将无法编译
如果删除dependencProperty
并拥有CLR属性,则将失去WPF属性系统的所有好处。虽然您可以轻松地设置绑定,但它们在性能方面效率较低
如果修改getter和setter内部的代码,将损害代码的简单性和可读性。WPF需要某种方法来指示属性是只读、只读还是只读。有几种方法可以做到这一点。例如,它们可以使其成为您在注册DependencyProperty时指定的内容
我认为他们之所以选择“makeyouwriteget/set方法”,是因为它们以一个方法的价格获得了两个好处:方法告诉XAML编译器属性是否可写;它们也是运行时代码可以用来读取和写入属性的机制。如果你不使用“得者”或“得者”,你就是在向两位听众传达你的意图。因此,您最终编写了一组同时满足这两个目的的代码,并确保在以后改变主意时它们保持同步。您必须按照预期的方式使用某个东西,对于血淋淋的细节,你可以随时查看WPF是如何编写的:@Bizhan我已经用错误的截图更新了我的帖子,显示getter和setter确实是必需的。你有没有一个例子来演示你描述的行为?我撤回了我的投票,因为我不知道这个场景,但在绑定中,我100%确定你不需要访问器。你误解了
<StackPanel>
<CheckBox IsChecked="{Binding Path=IsActive}"/>
<CheckBox IsChecked="{Binding Path=IsActive}"/>
</StackPanel>
public class ViewModel : DependencyObject
{
private static readonly DependencyProperty IsActiveProperty =
DependencyProperty.Register("IsActive",
typeof(bool),
typeof(ViewModel),
new PropertyMetadata(false));
}