C# 依赖属性机制

C# 依赖属性机制,c#,wpf,data-binding,wpf-controls,C#,Wpf,Data Binding,Wpf Controls,依赖属性本质上是静态的,所以如果我创建一个称为“IsGrayProperty”的bool类型自定义依赖属性,并在两个按钮上实现它。 那么,如果我在btn1中设置值,为什么它不应该反映在btn2中,因为dependencyproperty是静态的,并且它们是.net包装器属性“IsGray”静态只读dependencyproperty命名的IsGrayProperty是一个标识符——可以说是一个键值。它还包含有关属性的元数据。它不是实际的财产本身。每个DependencyObject实例在内部存储

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

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

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

例如,
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; }
设置一个
TextBlock
Text
时,是否每隔一个
TextBlock
共享相同的文本?不,当然不是。如果他们这样做了,依赖属性将完全无用

dependencProperty
参数to
GetValue
告诉
DependencyObject
从依赖项对象自身的属性值内部存储中检索哪个值;如果值存储在
dependencProperty
本身中,则您将查询
dependencProperty
,而不是
DependencyObject

public void ForExample(TextBlock tb)
{
    var oldtext = tb.GetValue(TextBlock.TextProperty) as String;

    tb.SetValue(TextBlock.TextProperty, "Test value");
}
如果
TextBlock.TextProperty
只有一个全局值,并且它存储在
TextBlock.TextProperty
中,那么我们究竟为什么在
TextBlock
的某个随机实例上调用
GetValue()
SetValue()
?为什么要让一个特定的
TextBlock
实例参与进来呢

相反,我们将调用
TextBlock.TextProperty.SetValue()

就像一本字典:

var d1 = new Dictionary<String, Object>();
var d2 = new Dictionary<String, Object>();
var keyValue = "Foo";

d1.Add(keyValue, 32);

Console.WriteLine( d2[keyValue] );
var d1=newdictionary();
var d2=新字典();
var keyValue=“Foo”;
d1.增加(键值,32);
Console.WriteLine(d2[keyValue]);
您希望从
d2[keyValue]
中得到什么?你不会期望什么,因为你从来没有给
d2
一个
keyValue
的值<代码>d1。添加(“Foo”,32)不会将整数
32
存储在字符串
“Foo”
中。它把它储存在字典里

每个字典都存储自己的键值。每个
DependencyObject
都存储自己的属性值。在内部,它可能将它们存储在
字典中
;为什么不呢?如果.NET团队能够编写一种比
字典
更有效的方法来存储键/值对,他们会称之为
字典


当你对一种语言或框架特性的含义有了一个概念时,总是要问自己,“如果我的想法是真的,那么该特性是完全无用的还是非常有害的?”如果这个问题的答案是“是”,那么你对该特性的含义的猜测就错了。这是100%的保证,因为语言和框架设计者和实现者不会习惯性地浪费数月的精力来设计完全无用的特性()

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

public static readonly DependencyProperty IsGrayProperty =    
    DependencyProperty.Register(
        "IsGray",
        typeof(bool),
        typeof(MyButton));
描述符只包含有关属性的元数据,不包含其值

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

public bool IsGray
{
    get
    {
        return (bool)GetValue(IsGrayProperty);
    }
    set
    {
        SetValue(IsGrayProperty, value);
    }
}
如您所见,它将get和set委托给base
DependencyObject
的实例方法
GetValue
SetValue

public void ForExample(TextBlock tb)
{
    var oldtext = tb.GetValue(TextBlock.TextProperty) as String;

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


静态
IsGrayProperty
描述符仅用于确定条目数组的索引、执行验证等。事实上,
IsGrayProperty
是静态的,这使得思考起来有点不直观,但是依赖性属性值是依赖性对象的每个实例,和不共享。

因为btn2没有引用btn1的属性。感谢Felix,通过使用GetValue和SetValue,我正在访问注册的静态IsGrayproperty,在这种情况下,静态属性一次只有一个值,因此所有实现的控件都应该是相同的,但不会发生这种情况,我想知道dependency属性实际上是如何工作的no,no,no。通过使用GetValue和SetValue,您可以访问一个实例字段,该字段包含每个实例专用的条目数组。IsGrayProperty描述符仅用于确定数组的索引、执行验证等。GetValue和SetValue读取和写入的实际值位于entry数组的entry处,每个实例都有自己的entry数组。IsGrayProperty是静态的这一事实,让人觉得它有点不直观,但尽管如此,依赖性属性值是每个实例的,并且不是共享的。感谢Ed,是的,你是对的,但是没有了解静态属性如何为不同的控件具有不同的值,尽管GetValue,在访问静态只读属性的末尾设置值它完全等同于从字典中检索项:
var foo=new dictionary();/*添加stuff*/var x=foo[“Bar”]。如果你有六种不同的字典,每种字典都会为“Bar”存储自己的个人值。鳕鱼