【问题标题】:WinForms, DataGridView: Filtering XML data using attributes from multiple nodesWinForms、DataGridView:使用来自多个节点的属性过滤 XML 数据
【发布时间】:2010-12-15 19:11:47
【问题描述】:

我有一个类似于以下格式的 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 行?谢谢!

更新:

感谢康拉德的帮助!但是,我仍在尝试弄清楚如何在这三个级别之间“导航”,因为添加 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 数据的方式吗?谢谢!

【问题讨论】:

    标签: c# xml winforms datagridview


    【解决方案1】:

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

    var data= (from d in XDocument.Load(_pathXML).Descendants("ThirdLevel") where d.Attribute("Id").Value == 1 select d;

    现在可以显示数据了

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

    【讨论】:

      【解决方案2】:

      更新 没有关系“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;
      

      【讨论】:

      • 仍然无法进行“导航”。 (见更新)。
      【解决方案3】:

      试试 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);
                  }
      

      【讨论】:

      • 谢谢!但是,Linq to XML 似乎很难进行双向数据绑定。我如何将 DataGridView 与此进行双向数据绑定,以便将编辑保存回 XML 文件?我在这里问了一个更一般的问题:stackoverflow.com/questions/4446296/…
      猜你喜欢
      • 2013-10-07
      • 1970-01-01
      • 2011-06-02
      • 1970-01-01
      • 2023-03-18
      • 2013-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多