WinForms,DataGridView:使用来自多个节点的属性过滤XML数据

时间:2010-12-15 19:11:47

标签: c# xml winforms datagridview

我有一个格式与此类似的XML数据文件:

<?xml version="1.0" standalone="yes"?>
<Root>
  <FirstLevel Id="1">
    <SecondLevel Id="1">
      <ThirdLevel Id="1">
        <DataElement Id="1" Data="hello" />
        <DataElement Id="2" Data="world" />
      </ThirdLevel>
      <ThirdLevel Id="2">
        <DataElement Id="1" Data="blablabla" />
        <DataElement Id="2" Data="blablabla" />
      </ThirdLevel>    
    </SecondLevel>
    <SecondLevel Id="2">
      <ThirdLevel Id="1">
        <DataElement Id="1" Data="asdf" />
        <DataElement Id="2" Data="qwerty" />
      </ThirdLevel>
      <ThirdLevel Id="2">
        <DataElement Id="1" Data="gggggg" />
        <DataElement Id="2" Data="dddddd" />
      </ThirdLevel>    
    </SecondLevel>
  </FirstLevel>
</Root>

我正在尝试使用绑定到此XML文件的DataGridView创建WinForms应用程序。并根据所选的导航参数在网格中显示以下内容。例如,如果用户为所有选择Id为1的FirstLevel,SecondLevel和ThirdLevel导航,则只显示以下2行,并且能够将任何更改写回XML:

Id   Data
----------
1    hello
2    world

到目前为止,我只能显示所有行(数据表):

Id  Data
---------
1   hello
2   world
1   blablabla
2   blablabla
1   asdf
2   qwerty
... etc

使用以下代码:

DataSet dataSet = new DataSet();
dataSet.ReadXML("Data.xml");
DataView dataView = new DataView(dataSet.Tables["DataElement"]);
BindingSource source = new BindingSource();
source.DataSource = dataView;
dataGridView1.DataSource = source;

如何过滤我的数据,以便只显示2行,如上所述?谢谢!

UPDATE:

感谢康拉德的帮助!但是,我仍然试图弄清楚如何在这三个级别之间“导航”,因为添加DataMember并不能完全添加过滤。因此,为了能够,比如显示FirstLevel Id = 2,SecondLevel Id = 1,ThirdLevel Id = 5(或其他)的标准数据,我是否必须将所有三个添加到:

DataView dataView = new DataView(dataSet.Tables["FirstLevel_SecondLevel_ThirdLevel"]);

然后添加类似于:

的RowFilter
dataView.RowFilter = "Id = '2'";

(但是这里的其他级别呢?)

然后按如下方式修改DataMember:

source.DataMember = "FirstLevel_SecondLevel_ThirdLevel_DataElement";

它对我来说还不太合适。我真的只是反对这里的流程,这不是如何在WinForms中编辑XML数据?谢谢!

3 个答案:

答案 0 :(得分:0)

尝试XPath和Linq to XML。 假设XML位于一个名为XML的字符串中:

           var doc = XDocument.Parse(xml);
            var firstLevel = "1";
            var secondLevel = "1";
            var thirdLevel = "1";
            var query = string.Format("/Root/FirstLevel[@Id={0}]/SecondLevel[@Id={1}]/ThirdLevel[@Id={2}]/DataElement", firstLevel, secondLevel, thirdLevel);
            var results = (from i in doc.XPathSelectElements(query)
                           select new { Id = i.Attribute("Id").Value, Data = i.Attribute("Data").Value }).ToList();
            foreach (var item in results)
            {
                Console.WriteLine("{0} - {1}", item.Id, item.Data);
            }

答案 1 :(得分:0)

<强>更新 没有关系“FirstLevel_SecondLevel_ThirdLevel”这就是为什么它不起作用。您可以通过检查DataSet.Relations集合找出存在的文件。

如果您有多个级别,则需要为每个级别创建一个视图。

        DataView firstDataView = new DataView(dataSet.Tables["FirstLevel"]);
        firstDataView.RowFilter = "Id = 1";


        DataView secondDataView  = firstDataView[0].CreateChildView("FirstLevel_SecondLevel");
        secondDataView.RowFilter = "Id = 2";

        DataView thirdDataView = secondDataView[0].CreateChildView("SecondLevel_ThirdLevel");
        DataView dataElement = thirdDataView[0].CreateChildView("ThirdLevel_DataElement");



        BindingSource source = new BindingSource();

        source.DataSource = dataElement;

        dataGridView1.DataSource = source;

答案 2 :(得分:0)

您可以过滤where子句中传递实际元素名称的数据,并在过滤后获取确切数据。

var data =(来自D在XDocument.Load(_pathXML).Descendants(&#34; ThirdLevel&#34;),其中d.Attribute(&#34; Id&#34;)。值== 1选择d;

现在您可以显示数据

          if (_appNme.Any())
          {
              foreach (var item in data)
              {
                  MessageBox.Show(_appNme.Elements("Id").Single().Value);
                  MessageBox.Show(_appNme.Elements("Data").Single().Value);
              }

          }