1. Select an XML file
2. Select an Element from the XML
3. Display the child elements and the associated values
4. Select a specific value of a child element and display all occurrences of that value
All of this will displayed in a Windows Forms DataGridView Control.
So I have wanted to learn some more Linq for a while so I decided to do use Linq for querying the XML data instead of using XPath.
This post is the first post of what will likely be a few posts in this series as there are some other items I will cover. I will want to have two panels in this application, one that contain the XML structure(so the user can select which Elements they want to view) and the other panel will show the results. I might also have a 3rd panel that shows the source xml. I am going to try and do some drag and drop to allow the user drag values, we'll see how I get on with that (easy in the web world so am hoping it's not too clunky in the winforms world).
Part 1: Display Linq to XML Query Results in Windows Forms DataGridView
NOTE: All of this is using VS2010 and .Net Framwork version 4.
So the first order of business is allowing the user to select an xml file to open. So to do this I did:
1. Created a new Windows Form project inVisual Studio 2010
2. Add a Picture Box to the form and set the picture to a nice open file icon
3. Add a Open File Dialog control to the form
4. Put the following code in the button on click event
1: namespace XMLFileTool
2: {
3: public partial class Form1 : Form
4: {
5: public Form1()
6: {
7: InitializeComponent();
8: }
9:
10: private void pictureBox1_Click(object sender, EventArgs e)
11: {
12: DialogResult result = openFileDialog1.ShowDialog();
13: if (result == DialogResult.OK)
14: {
15: string fileName = openFileDialog1.FileName;
16: }
17: else
18: {
19: MessageBox.Show("It's gonna be kind of hard to read an xml file if you don't select one.");
20: }
21: }
22: }
23: }
So the next activity is to read in the file you have selected so that you can run your Linq query on the XML.
I am using the XElement Class to read in the elements from a specific node in the XML. Using this class means that I don't have to start from the Root node and work my way from there. It's a bit less code to do it this way.
I am going to go ahead and past the whole class below and then explain what it going on. You can ignore Lines 24 to 30 for now. This will be covered off in a later post.
1: using System;
2: using System.Collections.Generic;
3: using System.ComponentModel;
4: using System.Data;
5: using System.Drawing;
6: using System.Linq;
7: using System.Text;
8: using System.Windows.Forms;
9: using System.IO;
10: using System.Xml;
11: using System.Xml.Linq;
12:
13: namespace XMLFileTool
14: {
15: public partial class Form1 : Form
16: {
17: public Form1()
18: {
19: InitializeComponent();
20: }
21:
22: private void pictureBox1_Click(object sender, EventArgs e)
23: {
24: List<string> xmlTagList = new List<string>();
25: xmlTagList.Add("OUTDOORS");
26: xmlTagList.Add("ACTIVITIES");
27: xmlTagList.Add("WALKING");
28: xmlTagList.Add("TOWNNAME");
29:
30: var dataTableName = xmlTagList.Last();
31:
32: DialogResult result = openFileDialog1.ShowDialog();
33: if (result == DialogResult.OK)
34: {
35: string fileName = openFileDialog1.FileName;
36:
37: tbSelectedFile.Text = openFileDialog1.FileName;
38: XElement xmlDocument = XElement.Load(fileName);
39: try
40: {
41: var xmlNodes = from nodeList in xmlDocument.Descendants(dataTableName)
42: select new
43: {
44: TownName = nodeList.Attribute("name").Value,
45: WalkName = nodeList.Element("WALKNAME").Value
46: };
47:
48: dgSearchResults.AutoGenerateColumns = true;
49: dgSearchResults.DataSource = xmlNodes.ToList();
50: }
51: catch (IOException ex)
52: {
53: MessageBox.Show(ex.Message);
54: }
55: }
56: else
57: {
58: MessageBox.Show("It's gonna be kind of hard to read an xml file if you don't select one.");
59: }
60: }
61: }
62: }
You will notice on line 37 the code to write out the file name to a text box. What I did here was added a Text Box control to the form and I use this code to display the file name and file path to the user so that they can see on screen which file they selected.
On Line 38 we use the XElement Class which has a Load() method and we pass the string fileName which is the path to the file the user has selected.
Line 41 starts the Linq query. Basically what this is saying is:
Get me a list of all of the Elements that are Children of the TOWNNAME element and set the variable xmlNodes equal to what ever is returned by the Linq query.
On Line 49 I set the DataGridView DataSource using the ToList() method of the Enumerable Class.
That's all you need to do! I have listed the XML that I used below. When you run this, select the XML file, this is what you will see on screen:
<?xml version="1.0"?>
<OUTDOORS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ACTIVITIES>
<WALKING>
<TOWNNAME name="Drumshanbo">
<WALKNAME>Historical Town Walk</WALKNAME>
<WALKLOCATION>Begins in Market Yard</WALKLOCATION>
<DIFFICULTY>Easy</DIFFICULTY>
<DURATION>1 hour</DURATION>
</TOWNNAME>
<TOWNNAME name="Ballinaglera">
<WALKNAME>St. Hugh's Holy Well</WALKNAME>
<WALKLOCATION>St. Hugh's Holy Well</WALKLOCATION>
<DIFFICULTY>Medium</DIFFICULTY>
<DURATION>2 hours</DURATION>
</TOWNNAME>
<TOWNNAME name="Arigna">
<WALKNAME>Miner's Way</WALKNAME>
<WALKLOCATION>Own train tracks</WALKLOCATION>
<DIFFICULTY>Medium</DIFFICULTY>
<DURATION>4 hours</DURATION>
</TOWNNAME>
<TOWNNAME name="Drumkeeran">
<WALKNAME>Miner's Way</WALKNAME>
<WALKLOCATION>Drumkeeran</WALKLOCATION>
<DIFFICULTY>Easy</DIFFICULTY>
<DURATION>6 hours</DURATION>
</TOWNNAME>
</WALKING>
<FISHING>
<LOUGHALLEN>
<FISHINGTYPE>Coarse</FISHINGTYPE>
<TYPESOFFISH>Pike</TYPESOFFISH>
</LOUGHALLEN>
<RIVERSHANNON>
<FISHINGTYPE>Fly Fishing</FISHINGTYPE>
<TYPESOFFISH>Trout</TYPESOFFISH>
</RIVERSHANNON>
</FISHING>
</ACTIVITIES>
</OUTDOORS>
No comments:
Post a Comment