依赖属性机制

时间:2016-07-12 14:40:08

标签: c# wpf data-binding wpf-controls

依赖属性本质上是静态的,所以如果我创建一个名为“IsGrayProperty”的bool类型自定义依赖属性,并在两个按钮上实现它。 然后,如果我在btn1中设置值,为什么它不应该反映在btn2中,因为dependencyproperty是静态的并且它们是.net包装器属性“IsGray”

2 个答案:

答案 0 :(得分:0)

名为DependencyProperty的静态只读IsGrayProperty是一个标识符 - 可以说是一个键值。它还包含有关该属性的元数据。这不是实际的财产本身。每个DependencyObject实例在内部存储自己的DependencyProperty值。

依赖属性语义非常类似于常规实例属性,但它们具有其他功能,可以让它们执行常规实例属性无法执行的操作(例如,您可以更改其元数据)运行时,与常规属性上的Attributes不同,您可以创建附加属性)。这就是他们存在的原因。

例如,TextBlock.Text是依赖属性。

//
// Summary:
//     Identifies the System.Windows.Controls.TextBlock.Text dependency property.
//
// Returns:
//     The identifier of the System.Windows.Controls.TextBlock.Text dependency property.
[CommonDependencyProperty]
public static readonly DependencyProperty TextProperty;

它有一个"常规财产"包装器也是:

//
// Summary:
//     Gets or sets the text contents of a System.Windows.Controls.TextBlock.
//
// Returns:
//     The text contents of this System.Windows.Controls.TextBlock. Note that all
//     non-text content is stripped out, resulting in a plain text representation
//     of the System.Windows.Controls.TextBlock contents. The default is System.String.Empty.
[Localizability(LocalizationCategory.Text)]
public string Text { get; set; }

当您设置一个Text的{​​{1}}时,其他TextBlock是否共享相同的文字?不,当然不。如果他们这样做,依赖属性将是完全无用的。

TextBlock的{​​{1}}参数告诉DependencyProperty从依赖项对象自己的内部属性值存储中检索哪个值;如果该值存储在GetValue本身,您将查询DependencyObject而不是 DependencyProperty

DependencyProperty

如果DependencyObject只有一个全局值,并且 <{em> public void ForExample(TextBlock tb) { var oldtext = tb.GetValue(TextBlock.TextProperty) as String; tb.SetValue(TextBlock.TextProperty, "Test value"); } 中存储了,那么我们为什么要调用TextBlock.TextPropertyTextBlock.TextProperty的某个随机实例上的GetValue()?为什么要将特定的SetValue()实例添加到该行为中?

相反,我们会调用TextBlock

它就像一个词典:

TextBlock

您对TextBlock.TextProperty.SetValue()的期望是什么?您会期望 nothing ,因为您从未向var d1 = new Dictionary<String, Object>(); var d2 = new Dictionary<String, Object>(); var keyValue = "Foo"; d1.Add(keyValue, 32); Console.WriteLine( d2[keyValue] ); 提供d2[keyValue]的值。 d2不会将整数keyValue存储在字符串d1.Add("Foo",32)中。它将它存储在字典中。

每个字典都存储自己的键值。每个32都存储自己的属性值。在内部,它可能将存储在 a "Foo"中;为什么不?如果.NET团队可以编写比DependencyObject更有效的方式来存储键/值对,那么他们就称之为Dictionary

当您对某种语言或框架功能的含义有所了解时,请始终问问自己,&#34;如果我的想法是真的,那么该功能是完全无用还是大规模有害?&#34;如果该问题的答案是&#34;是&#34;,那么你猜错了该功能的含义。这是100%保证,因为语言和框架设计人员和实施者不习惯浪费数月的努力来设计完全无用的功能(classes in Perl 5 come close, though)。

答案 1 :(得分:0)

真正的静态是依赖属性描述符:

public static readonly DependencyProperty IsGrayProperty =    
    DependencyProperty.Register(
        "IsGray",
        typeof(bool),
        typeof(MyButton));

描述符仅包含有关属性的元数据,并且它不包含其值。

与数据绑定一起使用并从代码访问的实际属性是实例1:

public bool IsGray
{
    get
    {
        return (bool)GetValue(IsGrayProperty);
    }
    set
    {
        SetValue(IsGrayProperty, value);
    }
}

如您所见,它委托get并设置为基础GetValue的实例方法SetValueDependencyObject

在内部,DependencyObject维护一个条目数组(在实例字段中),其中存储了依赖项属性的实际值。每个实例都有自己的数组,实际值位于其中一个条目中。因此,它永远不会与其他实例共享。因此,SetValue改变当前按钮实例的状态,而不是任何静态状态。

静态IsGrayProperty描述符仅用于确定条目数组的索引,执行验证等。IsGrayProperty是静态的这一事实使得它有点反直觉,但是尽管如此,依赖项属性值是每个依赖项对象的实例,并且不会被共享。