【问题标题】:Filling a Listview/Gridview dynamically with XML file使用 XML 文件动态填充 Listview/Gridview
【发布时间】:2023-03-13 00:27:01
【问题描述】:

男孩女孩们下午好!我正在尝试学习 c#(WPF) 大约 2 周,我遇到了一些谷歌到目前为止没有帮助我解决的问题:/

假设我有一个随机的 XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<XML>
  <ADRESSE>
    <NAME1>John</NAME1>
    <NAME2>Doe</NAME2>
    <STRASSE1>Heystreet</STRASSE1>
    <STRASSE2>9</STRASSE2>
    <LAND>AUT</LAND>
    <PLZ>1050</PLZ>
    <ORT>Vienna</ORT>
  </ADRESSE>
</XML>

假设这个 XML 有 100 个条目。

现在我将在我的 XAML 中创建一个名为“lv1”的简单列表视图和一个按钮。

        int counter = 0;
        GridView gv1 = new GridView();
        XDocument rndfile = XDocument.Load(@"C:\Users\...\random.xml");

        foreach (XElement xele in rndfile.Descendants("ADRESSE")) //#1
        {

            GridViewColumn gvc = new GridViewColumn();
            gvc.DisplayMemberBinding = new Binding("Feld"+counter); 
            gvc.Header = xele.Name.LocalName; // #2
            gv1.Columns.Add(gvc); 
            string feldx = string.Format(@"Feld{0}", counter);
           // MessageBox.Show(feldx+"||"+"Feld"+counter); //was for me to test if names are identical
            lv1.Items.Add(new { feldx = xele.Element("Childelement of ADRESSE").Value }); //#3+4
            counter++;

        }
        lv1.View = gv1;

1 和 3 是我的实际问题,我猜 1 和 2 是一样的。

所以基本上我想要做的是按下按钮,加载 XML 并为 ADRESSE 的每个子级创建一个具有当前子级名称的列,并直接用 XML 内容填充它。

我现在遇到的问题:#1 foreach 循环仅针对每个名为 ADRESSE 的条目而不是它的每个子元素运行,我只是无法弄清楚如何在不破坏任何语法的情况下获取它的子元素(尝试使用Elements() 但他不喜欢循环中的那个).. 所以现在上面的 XML 只会创建 1 行而不是 7 行,因为文件中只有一个 ADRESSE 条目。

对于第二个问题,我想用 XML 的子名命名列,但由于 #1 的问题,它不会按预期工作。 (或者这种想法通常是错误的?)

第三个问题是列的动态填充。据我所见,lv1.Items.Add({...}) 不接受上面的feldx,但认为它是一个自己的名称并且没有正确填写它,因为没有名为 feldx 的列绑定。对于#4,我需要feldx = xele.Element(@"{0}", ChildName).Value这样的内容来获取列的正确内容

我真的试图自己寻找和解决这个问题,但我在 XML 或 gridviews here 或 mycsharp/msdn 上找到的所有东西要么只有静态(硬编码)XAML 条目和绑定,要么只是你知道什么的 XML 文件那里的条目(所以实际上又是硬编码的)。所以我只是希望我的要求不要太露骨,有人可以启发我一点

编辑#1:

    var rootele = rndfile.Root.Element("ADRESSE").Elements(); //<-- worked like a charm. My problem was that i tried to fiddle this into the foreach loop itself, which wasn't accepted somehow - so many thanks har07
    int counter = 0;
    foreach (XElement xele in rootele)
    {
        GridViewColumn gvc = new GridViewColumn();
        gvc.DisplayMemberBinding = new Binding("Feld"+counter); 
        gvc.Header = xele.Name.LocalName; 
        gv1.Columns.Add(gvc); 
        lv1.Items.Add(new { feld_x_ = xele.Element("Childelement of ADRESSE").Value }); // <-- for this i am trying to find a solution and post it again, or maybe someone else knows how to add a changing Binding Name  into the .Add()
        counter++;

    }
    lv1.View = gv1;

【问题讨论】:

    标签: c# xml wpf gridview


    【解决方案1】:

    您的 foreach 循环显然是告诉循环遍历每个 &lt;ADRESSE&gt; 节点,您可以像以下之一那样修复它:

    //approach 1 :
    var chldNodes = rndfile.Descendants("ADRESSE").First().Elements();
    //or approach 2 :
    var chldNodes = rndfile.Root.Element("ADRESSE").Elements();
    //then loop through childNodes
    foreach (XElement xele in chldNodes)
    

    3 & 4 看起来完全错误。这样,即使它有效,您也会以多行结束,每一列对应一行,对应行的列填充来自 XML 的值,其余列为空。修复 1 和 2,然后你可以专注于 3 和 4,用你最接近的尝试编辑问题 - 或打开新问题 - 如果你不能让它在最后工作。

    编辑:

    在 google 上的快速搜索表明带有动态列的 ListView 似乎不是一项简单的任务(一些相关线程:12

    您可能想尝试这种方式(根据上面的链接 2 制作):

    ....
    var columnValues = new List<string>();
    foreach (XElement xele in rootele)
    {
        GridViewColumn gvc = new GridViewColumn();
        gvc.DisplayMemberBinding = new Binding(String.Format("[{0}]", counter)); 
        gvc.Header = xele.Name.LocalName; 
        gv1.Columns.Add(gvc); 
        columnValues.Add((string)xele);
        counter++;
    }
    lv1.Items.Add(columnValues);
    ....
    

    【讨论】:

    • 我应该给你一个“已解决的答案”点击还是我可以每个线程只给这个一次?因为你实际上解决了我循环的主要问题:)
    • 更新了我对其余问题的回答。不过,如果我的更新对您不起作用,我建议您提出新问题
    • 对于 XML 中只有一个条目的情况,这很有效,但如果您在外部 xml 中有多个 实例,则不能。我现在只是在玩这个,但我是想知道为什么 Binding 只适用于您在“String.Format("[{0}]", counter)" 上面写的那个。如果我尝试更改绑定名称,它根本不起作用?
    • 而且我以某种方式假设如果 XML 文件的条目稍微洗牌,它就不会按预期工作。我的意思是,上面的示例将值直接添加到创建的列中,因此它应该根据列的绑定添加值..但是你已经帮了我很多,我会尝试解决这个问题两个单独的 foreach 循环:一个根据 ADRESSE 的子项数量创建 Listview 列,另一个循环为整个 XML 文件中的每个 ADRESSE 条目添加值)或尝试以某种方式将变量名称放入 lv1.Add。物品命令
    • 1) 关于绑定,是的意思是“绑定到columnValues[counter]”,不能随意修改。 2)那是因为我们只得到了第一个&lt;ADRESSE&gt; - 我故意这样想的:rndfile.Root.Element("ADRESSE")....(注意Element而不是Elements)。如果您打算容纳多个&lt;ADRESSE&gt;,则需要彻底改变逻辑流程,因为此时代码最终会为每个&lt;ADRESSE&gt; 一次又一次地添加重复的列。我建议重新考虑逻辑,如果您需要进一步的建议,请提出新问题。
    【解决方案2】:

    您的 XML 文件不正确。

    <NAME2>Doe</NAME3> 
    

    应该是

    <NAME2>Doe</NAME2>
    

    【讨论】:

    • ahna 我只是编辑错误了一点,xml 很好 - 但是谢谢
    【解决方案3】:

    我现在只写部分解决方案,这将需要比我想要的更多的硬编码,但总比没有好 - 也许其他人需要它(再次感谢 har07

            GridView gv1 = new GridView();
            XDocument rndfile = XDocument.Load(@"C:\Users\...\rndfile.xml");
            var rootele = rndfile.Descendants("ADRESSE").First().Elements();
            int counter = 0;
            //Create empty Listview depending on Sub-entrys of ADRESSE
            foreach (XElement xele in rootele)
            {
    
                GridViewColumn gvc = new GridViewColumn();
                gvc.DisplayMemberBinding = new Binding("Feld"+counter);//gets a Binding name Feld# for each child
                gvc.Header = xele.Name.LocalName; //Name my Columns after the <tags> of the childs
                gv1.Columns.Add(gvc);  //add the current Column to my Gridview
                counter++;
    
            } //Listview created
    
            //Fill my list for every single Parent-element in my XML file
    
                foreach (XElement xe in rndfile.Descendants("ADRESSE"))
                {
    
                     lv1.Items.Add(new
                        {
                            Feld0 = xe.Element("NAME1").Value,
                            Feld1 = xe.Element("NAME2").Value,
                            Feld2 = xe.Element("STRASSE1").Value,
                            Feld3 = xe.Element("STRASSE2").Value,
                            Feld4 = xe.Element("LAND").Value,
                            Feld5 = xe.Element("PLZ").Value,
                            Feld6 = xe.Element("ORT").Value
                        });
    
                }//List filled 
    

    这样,在我的第一个之后,后续的 ADRESSE 标记中的 ChildElements 的顺序无关紧要(因为需要第一个 Parent 才能正确创建列)。所以下面的地址的第二个洗牌条目:

        <?xml version="1.0" encoding="UTF-8"?>
        <XML>
          <ADRESSE>
            <NAME1>John</NAME1>
            <NAME2>Doe</NAME2>
            <STRASSE1>Heystreet</STRASSE1>
            <STRASSE2>9</STRASSE2>
            <LAND>AUT</LAND>
            <PLZ>1050</PLZ>
            <ORT>Vienna</ORT>
          </ADRESSE>
          <ADRESSE>
            <LAND>AUT</LAND>
            <PLZ>1060</PLZ>
            <ORT>Vienna</ORT>
            <NAME1>Jane</NAME1>
            <STRASSE1>Wherestreet</STRASSE1>
            <STRASSE2>11</STRASSE2>
            <NAME2>Doe</NAME2>
          </ADRESSE>
        </XML>
    

    仍将填写在正确的列中。现在唯一剩下的问题是绑定(或列的命名)对第一个条目的依赖性,如果我使用另一种具有不同条目的 XML,我必须重命名所有 FeldX = xe.Element("XXX").Value 中的每个 X。

    仍然:如果有人知道解决方案接近(我知道那完全坏了但是)类似 ->

    lv1.Items.Add(new{ string.Format(@"Feld{0}", counter) = xe.Element(@"{0}", xele.Name.LocalName).Value} 
    

    放入一个循环我真的很感激!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多