【问题标题】:Creating an XML element with a prefix using XElement使用 XElement 创建带前缀的 XML 元素
【发布时间】:2012-10-22 13:48:08
【问题描述】:

我有一个使用包含多个 WPF 自定义组件的画布的应用程序。我想将这些组件导出到一个 XAML 文件中,以便另一个应用程序可以获取它,但是为了做到这一点,我需要为导出的组件添加前缀限定符。例如,如果我要导出一个 FrequencyButtonA 组件,我需要输出类似

<PanelControls:FrequencyButtonA Frequency="113.123" Width="250"/>

我尝试了以下方法,但由于使用了 ':' 字符而出现异常:

return new XElement("PanelControls:" + "FrequencyButtonA");

有什么想法吗?我在 SO 中发现了一些其他问题,这些问题似乎与我遇到的问题相似(例如,this link),但不是完全相同的情况。

提前致谢!

编辑 - 更多背景信息:这是我需要生成的完整输出的示例:

<Border x:Name="CommsPanelBorder"
    Style="{DynamicResource BorderTemplate}"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:PanelControls="clr-namespace:CommsPanelControlsLib.View;assembly=CommsPanelControlsLib"
    VerticalAlignment="Top">
        <PanelControls:FrequencyButtonB Frequency="113.123" Width="250"/>
        <PanelControls:FrequencyButtonA Frequency="102.3" Width="150"/>

我忘记在我的原始帖子中提到根节点(边框)是在方法中创建的。然后该方法循环遍历放置在画布中的所有元素,并在所述元素上调用一个方法,该方法返回一个 XElement,该 XElement 稍后将添加到根节点。因此,我需要让 XElements 能够自己创建。该方法的代码如下:

XNamespace aw = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
        XNamespace ns = "PanelControls";
        var root = new XElement(aw + "Border",
            new XAttribute("Style", "{DynamicResource BorderTemplate}"),
            new XAttribute("Name", "CommsPanelBorder"),
            new XAttribute(XNamespace.Xmlns + "x", "http://schemas.microsoft.com/winfx/2006/xaml"),
            new XAttribute(XNamespace.Xmlns + "PanelControls", "clr-namespace:CommsPanelControlsLib.View;assembly=CommsPanelControlsLib"),
            new XAttribute("VerticalAlignment", "Top")
        );

        IEnumerable<CommsPanelControl> commsPanelControls = editCanvas.Children.OfType<CommsPanelControl>();

        foreach (var commsPanelControl in commsPanelControls)
        {
            XElement xElement = commsPanelControl.AddXElement(root, ns);
            root.Add(xElement);
        }

编辑 2. 添加了一些代码,以便 Reinder 可以看到我当前的方法:

XNamespace aw = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
        XNamespace ns = "PanelControls";
        var root = new XElement(aw + "Border",
            new XAttribute("Style", "{DynamicResource BorderTemplate}"),
            new XAttribute("Name", "CommsPanelBorder"),
            new XAttribute(XNamespace.Xmlns + "x", "http://schemas.microsoft.com/winfx/2006/xaml"),
            new XAttribute(XNamespace.Xmlns + "PanelControls", "clr-namespace:CommsPanelControlsLib.View;assembly=CommsPanelControlsLib"),
            new XAttribute("VerticalAlignment", "Top")
        );

        XElement xElement = new XElement(ns + "FrequencyButtonA",
            new XAttribute("Frequency", "113.123"),
            new XAttribute("Width", "250"));
        root.Add(xElement);

编辑 3. 作为参考,这是我的问题的可能解决方案。感谢 Reiner 的意见!

XNamespace aw = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
        XNamespace ns = "clr-namespace:CommsPanelControlsLib.View;assembly=CommsPanelControlsLib";
        var root = new XElement(aw + "Border",
            new XAttribute("Style", "{DynamicResource BorderTemplate}"),
            new XAttribute("Name", "CommsPanelBorder"),
            new XAttribute(XNamespace.Xmlns + "x", "http://schemas.microsoft.com/winfx/2006/xaml"),
            new XAttribute(XNamespace.Xmlns + "PanelControls", "clr-namespace:CommsPanelControlsLib.View;assembly=CommsPanelControlsLib"),
            new XAttribute("VerticalAlignment", "Top")
        );

        XElement xElement = new XElement(ns + "FrequencyButtonA",
            new XAttribute("Frequency", "113.123"),
            new XAttribute("Width", "250"));
        root.Add(xElement);

【问题讨论】:

    标签: c# xelement prefix


    【解决方案1】:

    PanelControls 这样的前缀只有在声明与之相关的命名空间时才有意义。

    您需要在节点本身或例如在根中指定它。

    // create the root element, with the 'PanelControls' namespace
    XNamespace nSpace = "PanelControls";
    XElement element = new XElement("root",
              new XAttribute(XNamespace.Xmlns + "PanelControls", nSpace));
    
    element.Add(addXElement("FrequencyButtonA", nSpace ));
    
    ...
    
    private static XElement addXElement(string n, XNamespace ns)
    {
        return new XElement(ns + n,
            new XAttribute("Frequency", 113.123),
            new XAttribute("Width", 250));
    }
    

    方法 'addXElement()' 将在命名空间 ns 中创建新的 XElement,因此您最终会得到:

    <?xml version="1.0"?>
    <root xmlns:PanelControls="PanelControls">
        <PanelControls:FrequencyButtonA Width="250" Frequency="113.123"/>
    </root>
    

    【讨论】:

    • 感谢您的回复,但我希望输出更紧凑,例如我发布的那个。我了解您的解决方案有效,但我希望生成的 XAML 尽可能简洁。你能建议一种方法来获得像我的帖子中那样的输出吗?
    • 你稍后用返回的 XElement 做什么?
    • 我将它添加到根元素。目前,我在一个函数中创建了根对象(它是一个画布),然后遍历它包含的所有元素,并在每个元素上调用一个实例方法,以便将它们自己作为 XElement 返回,然后附加到根。
    • 那么您必须在该根对象上定义命名空间,就像 ghost 所说的那样。我已经更新了答案
    • 感谢您的回复。我不明白的一件事是如何修改代码,使 PanelControls 命名空间前缀指向“clr-namespace:CommsPanelControlsLib.View;assembly=CommsPanelControlsLib”。我已经通过第二次编辑更新了我的原始帖子,其中我展示了我根据您的解决方案完成的快速测试。程序编译,但 FrequencyButtonA 的输出不是我想要的。这就是我得到的: 有什么想法吗?
    【解决方案2】:
    using System;
    using System.Xml.Linq;
    
    
    class Program
    {
        static void Main(string[] args)
        {
    
            XNamespace @namespace = "PanelControls";
            XElement element = new XElement("root",
                new XAttribute(XNamespace.Xmlns + "PanelControls", @namespace),
                new XElement(@namespace + "FrequencyButtonA",
                    new XAttribute("Frequency", 113.123),
                    new XAttribute("Width", 250)));
            Console.WriteLine(element);
        }
    }
    

    【讨论】:

    • 感谢您的回复。您的解决方案输出了我需要的 FrequencyButtonA 代码,但是,我忘记在我的原始帖子中提到根元素是在不同的位置创建的,然后各个元素(例如频率按钮)被创建为 stadalone XElement 实例被添加到根目录。创建根元素后,有什么方法可以输出类似于我在原始帖子中提供的示例的内容?我尝试了不同的方法,但我得到了一个非常冗长的输出,我想保持输出紧凑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多