开发者

WinForms, DataGridView: Filtering XML data using attributes from multiple nodes

开发者 https://www.devze.com 2023-01-31 06:53 出处:网络
I have an XML data file of format similar to this: <?xml version=\"1.0\" standalone=\"yes\"?> <Root>

I have an XML data file of format similar to this:

<?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>

And I'm trying to create a WinForms application using DataGridView that binds to this XML file. And displays the following in the grid, depending on selected navigation parameters. For example, if user selects navigation of FirstLevel, SecondLevel, and ThirdLevel with Id of 1 for all, only the following 2 rows should be displayed, with ability to write back any changes to XML:

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

So far, I can only get all the rows (datatables) to display:

Id  Data
---------
1   hello
2   world
1   blablabla开发者_开发问答
2   blablabla
1   asdf
2   qwerty
... etc

Using the following code:

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;

How can I filter my data so that only 2 rows are displayed, as described above? Thanks!

UPDATE:

Thanks Conrad for your help! However, I'm still trying to figure out how to "navigate" between these three levels, as adding a DataMember doesn't quite add the filtering. So to be able to, say, display data for criteria of FirstLevel Id = 2, SecondLevel Id = 1, ThirdLevel Id = 5 (or something), would I have to add all three to:

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

And then add RowFilter with something like:

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

(but what about other levels here?)

And then modify DataMember as follows:

source.DataMember = "FirstLevel_SecondLevel_ThirdLevel_DataElement";

It doesn't quite work for me yet. Am I really just going against the flow here, and this is not how editing XML data should be approached in WinForms? Thanks!


You can filter the data in where clause passing the actual element name and fetching the exact data after filtering it.

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

Now you can display the data

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

          }


UPDATE There is no relation "FirstLevel_SecondLevel_ThirdLevel" which is why that doesn't work. You can find out which ones exist by inspecting the DataSet.Relations collection.

When you have multiple levels as you do you need to create a view for each level.

        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;


Try XPath and Linq to XML. Assuming the XML is in a string aclled 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);
            }
0

精彩评论

暂无评论...
验证码 换一张
取 消