WPF的扩展程序提供程序

时间:2009-09-17 16:42:02

标签: c# .net wpf

是否有等同于System.ComponentModel.IExtenderProvider的WPF?

我是否必须使用依赖属性和附加属性来构建等效项,或者是否已经在烤箱中烘烤了等待我的东西?

谢谢,

帕特里克

2 个答案:

答案 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 是您可以拦截,修改或注入所需的任何附加属性行为的地方。请参见LookupAttachableMemberLookupAllAttachableMembers方法替代。您可能需要特别关注的 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 中使用覆盖的方法,您有时有时会发现自己陷入回调的深处,而看上去似乎不够用上下文信息。

相关问题