Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么DependencyProperties需要facade属性/getter/setter_C#_Wpf_Xaml - Fatal编程技术网

C# 为什么DependencyProperties需要facade属性/getter/setter

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

我使用WPF已经有一段时间了。但我仍然想知道,为什么在定义DependencyProperties时需要这些facade属性

这就是我的意思。要定义DependencyProperty,必须编写如下内容:

公共静态从属属性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()
。我自己也不使用这些属性(如果我在代码隐藏中需要它们,我也可以直接调用SetValueGetValue


所以,如果它们从未被使用过,为什么我不能省略这些属性呢?有人能给我解释一下吗?

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));
    }