是否有等同于System.ComponentModel.IExtenderProvider的WPF?
我是否必须使用依赖属性和附加属性来构建等效项,或者是否已经在烤箱中烘烤了等待我的东西?
谢谢,
帕特里克
答案 0 :(得分:5)
附属财产是前进的方式http://msdn.microsoft.com/en-us/library/ms749011.aspx
您还可以使用AttachedPropertyBrowsableForChildrenAttribute来告诉控件将新创建的属性扩展到其所有子节点(具有网格的行属性)。
答案 1 :(得分:0)
XAML 的 WPF 读写器不了解 Windows窗体中使用的System.ComponentModel.Container
概念。 XAML 部署了由 XamlType 类型组成的综合系统,包括 XamlMember , XamlPropery 等,所有这些都统一在< strong> XamlSchemaContext ,它们共同代表一个成熟的类型系统,该系统叠加在 .NET 类型系统(即“反射”)上,并在很大程度上独立于该类型。 XAML “附加属性”仅在此Universe内定义,因此存在于此范围内。
虽然其中的某些确实与System.ComponentModel
无关,但确实不幸的是,这两个主要的体系结构框架实际上并没有共谋,交流或勾勒出共同的关联,混淆或共同采用的概念。 要做 包含共同点。
但是,好消息-以及这篇迟钝帖子的原因以及您的问题的答案-是 XamlServices 确实有扩展点可以解决您的问题场景。因为我上面提到的所有这些“ Xaml ... ”类型类型都是由未密封且可以覆盖的公共类表示的。起点是创建您自己的自定义XamlSchemaContext
并覆盖GetXamlType
方法,以在您需要的情况下提供自己的自定义 XamlType 派生的对象。
XamlType 是您可以拦截,修改或注入所需的任何附加属性行为的地方。请参见LookupAttachableMember
或LookupAllAttachableMembers
方法替代。您可能需要特别关注的 XamlType 实现中的方法是XamlType.LookupInvoker(...)
,该方法可让您提供自定义的 XamlTypeInvoker 实例,该实例具有CreateInstance(...)
替代可以最终控制部署到生成的反序列化对象图的实例的所有方面。
在极端情况下,XamlTypeInvoker.CreateInstance
可以完全替代某些或所有XAML解析的CLR类型,但这开始无法实现更大的目标,因为任何此类“替换” CLR类型都像所有CLR类型一样由 XamlServices 实例化的-必须始终具有预先存在的CLR定义。换句话说,XAML 做的不是做的-但您当然可以通过此覆盖添加!-是对TypeBuilder等。 >合成还没有等效的CLR Type
的新类型或成员。
要明确,这意味着无法获取 WPF 来识别任何类型的假定“合成”定制类型实例,也无法将数据绑定到“虚拟” ”,只需通过单独操作 XamlType 或 XamlMember 即可。
同时,一旦您覆盖类型和属性以及其他成员,以在派生的 XamlSchemaContext 下创建自己的派生的 XAML 类型系统,则可以提供该实例 XamlServices 中的 XAML 读取器和写入器方法的架构。
您可以将自定义XAML架构上下文传递到标准 XAML 读取器/写入器的构造函数中,例如 XamlXmlReader 和 XamlObjectWriter 所谓的“加载路径”场景;在此我不会讨论“保存路径”。但是,更重要的是,您也可以覆盖这两个类,它们提供了一组丰富的虚拟方法来覆盖。作为一个伪代码示例(从我的工作代码中提取),您可以向transform(...)
派生的类中添加XamlXmlReader
方法,该方法可以完全控制反序列化的object
XAML结果:< / p>
// ...in your class derived from 'XamlXmlReader'
public void transform(my_xaml_obj_writer xow)
{
while (base.Read())
{
if (xow.ShouldProvideLineInfo)
xow.SetLineInfo(LineNumber, LinePosition);
switch (NodeType)
{
case XamlNodeType.NamespaceDeclaration:
xow.WriteNamespace(base.Namespace);
break;
case XamlNodeType.StartObject:
xow.WriteStartObject(base.Type);
break;
case XamlNodeType.EndObject:
xow.inject_ctor_arg(); // <--- !! (not shown)
xow.WriteEndObject();
break;
case XamlNodeType.StartMember:
xow.inject_ctor_arg(); // <--- !! (not shown)
xow.WriteStartMember(base.Member);
break;
case XamlNodeType.EndMember:
xow.WriteEndMember();
break;
case XamlNodeType.GetObject:
xow.WriteGetObject();
break;
case XamlNodeType.Value:
xow.WriteValue(base.Value);
break;
case XamlNodeType.None:
break;
}
}
}
使用此自定义阅读器,将 XAML 反序列化为内存中的CLR对象的过程如下:
void XamlToObject(FileStream fs, my_xaml_schema_context ctx)
{
using (var xxr = new xaml_xml_reader(fs, ctx))
using (var xow = new my_obj_writer(this))
{
try
{
xxr.transform(xow);
}
catch (XamlObjectWriterException xex)
{
// ...
}
}
}
作为结果的XAML“根对象”(即内存中的CLR对象)是完整的要点,将在此结尾的覆盖的 XamlObjectWriter 的Result
属性中找到处理。就我而言,实际上是在创建上述结果后,在上面显示的transform
方法中,较早地在XAML节点流中探查了结果对象,以查看其是否具有[UsableDuringInitialization]
属性,并因此在反序列化仍在进行时启用某些并发使用。
最后请注意,如果要添加其他设置,还可以使用自己的派生类覆盖 XamlObjectWriterSettings 和 XamlXmlReaderSettings 。通常,您可能只需要执行此操作即可向自己提供其他自定义数据,因为在 XamlServices 中使用覆盖的方法,您有时有时会发现自己陷入回调的深处,而看上去似乎不够用上下文信息。