'ownerType'在RegisterAttached中的作用是什么?这个问题困扰我已经几年了,所以我最近细看了WindowsBase中4.6.1版本的代码。
对于任何DependencyProperty
,无论是附加属性还是其他属性,最终的关键在于WPF为后期绑定的XAML访问获取了什么类型的PropertyDescriptor
,而且这不会在尝试访问的第一次(基于每种类型/属性配对)之前确定。这种推迟是必要的,因为PropertyDescriptor
封装了绑定到特定类型的属性,而附加属性的重点就是避免这种情况。
当XAML访问发生时,Register(...)
与RegisterAttached(...)
的区别已经失去了(运行)时间的意义。正如其他人在本页上指出的那样,“DependencyProperty”本身并没有编码区分附加与非附加属性的区别。每个DP都被认为有资格用于任何用途,只要在运行时可以找到。
例如,下面的.NET代码似乎依赖于在“tOwner”类型上找不到匹配的“实例属性”作为允许附加访问的第一个要求。为了确认这一诊断,它随后检查“tOwner”是否公开了其中一个静态访问方法。这是一个模糊的检查,因为它没有验证方法签名。这些签名只对XAML访问有影响;所有实际运行时目标的附加属性必须是“DependencyObject”,每当可能时WPF通过“DependencyObject.GetValue/SetValue”访问它们。(据报道,VS Designer确实使用静态访问器,你的XAML没有它们将无法编译)
相关的.NET代码是静态函数“DependencyPropertyDescriptor.FromProperty”,以下是我的注释(摘要如下):
internal static DependencyPropertyDescriptor FromProperty(DependencyProperty dp, Type tOwner, Type tTarget, bool _)
{
if (tOwner.GetProperty(dp.Name) != null)
{
DependencyPropertyDescriptor dpd;
var dict = descriptor_cache;
lock (dict)
if (dict.TryGetValue(dp, out dpd))
return dpd;
dpd = new DependencyPropertyDescriptor(null, dp.Name, tTarget, dp, false);
lock (dict)
dict[dp] = dpd;
return dpd;
}
if ((tOwner.GetMethod("Get" + dp.Name) == null) && (tOwner.GetMethod("Set" + dp.Name) == null))
return null;
var dopd = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, tTarget);
return dopd?.FromProperty(dopd);
}
总结:当调用
RegisterAttached
创建附加的
DependencyProperty
时,'ownerType'唯一的作用就是标识一个定义了适当的静态Get/Set访问器的类型。'ownerType'上必须存在至少一个这样的访问器,否则XAML附加访问将不能编译或静默失败。尽管在这种情况下,RegisterAttached不会失败,而是成功返回一个失效的DP。对于仅用于附加使用的DP,'tOwner'不必派生自DependencyObject。您可以使用任何常规的.NET类,静态或非静态,甚至可以是一个结构体!
SetDP/ADP()
和GetDP/ADP()
函数,但调用SetValue(DP/ADP, value)
和GetValue(DP/ADP)
则不会。 2:在XAML设计器中,Intellisense将使用SetDP/ADP()
和GetDP/ADP()
方法签名来确定是否显示依赖属性或附加依赖属性。因此,如果SetDP/ADP()
参数接受DependencyObject
而不是更具体的类,则会显示无效的依赖属性。 - Melodatron.RegisterAttached
的ownerType参数实际上是否有任何意义? - Melodatron