Read xml file to treeview, selection to listview, modify and save

RoyLittle0

Active member
Joined
Nov 17, 2012
Messages
38
Location
Derby, Uk
Programming Experience
Beginner
OK, i'm sure you will all be horrified when you see my code, but i'm learning :)

This is as far as i have got, its not pretty but we all have to start somewhere and it is just a pet project, i can open up a file dialog box to select my xml and read it to the treeview, it then get the selections to the listview, when the listview selection is passed to a textbox for editing, i have a button ready for saving the file but just got to figure all that but out.

Be gentle with me i am trying to learn, all constructive comments welcome.

Modify xml.png
VB.NET:
Imports System.Linq
Imports System.Xml
Imports System.Xml.XPath


Public Class Form1
    Private document As XmlDocument = Nothing


    Private Sub LoadButton_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LoadButton.Click


        If OpenFileDialog.ShowDialog() = DialogResult.Cancel Then
            Return
        End If


        FileNameTextBox.Text = OpenFileDialog.FileName
        XmlTreeView.Nodes.Clear()


        document = New XmlDocument()
        document.Load(OpenFileDialog.FileName)
        'load the XMl file
        Dim nodeList As XmlNodeList = document.DocumentElement.ChildNodes


        'loop through the top nodes
        For Each node As XmlNode In document
            Dim treeNode As TreeNode = XmlNode2TreeNode(node)
            GetAttributes(node, treeNode)
            treeNode.Text = FormatName(node)
            XmlTreeView.Nodes.Add(treeNode)
        Next


    End Sub


    Private Function XmlNode2TreeNode(ByVal parentNode As XmlNode) As TreeNode
        Dim treeNode As New TreeNode()


        For Each childNode As XmlNode In parentNode.ChildNodes
            If childNode.NodeType = XmlNodeType.Element Then
                Dim childTreeNode As New TreeNode()


                If childNode.ChildNodes.Count > 0 Then
                    childTreeNode = XmlNode2TreeNode(childNode)
                End If


                childTreeNode.Text = FormatName(childNode)
                GetAttributes(childNode, childTreeNode)
                treeNode.Nodes.Add(childTreeNode)
            End If
        Next


        Return treeNode
    End Function


    Private Function FormatName(ByVal node As XmlNode) As String
        Dim fullName As String = "<" & node.Name


        If node.InnerText <> "" Then
            fullName += ">" & node.InnerText & "</" & node.Name & ">"
        Else
            fullName += ">"
        End If


        Return fullName
    End Function


    Private Sub GetAttributes(ByVal node As XmlNode, ByVal treeNode As TreeNode)
        If node.Attributes IsNot Nothing Then
            Dim attributes As ListViewItem() = New ListViewItem(node.Attributes.Count - 1) {}


            For i As Integer = 0 To node.Attributes.Count - 1
                attributes(i) = New ListViewItem(New String() {node.Attributes(i).Name, node.Attributes(i).Value})
            Next


            treeNode.Tag = attributes
        End If
    End Sub


    Private Sub xmlTreeView_NodeMouseClick(ByVal sender As Object, ByVal e As TreeNodeMouseClickEventArgs) Handles XmlTreeView.NodeMouseClick
        AttributesListView.Items.Clear()


        If e.Node.Tag IsNot Nothing Then
            AttributesListView.Items.AddRange(DirectCast(e.Node.Tag, ListViewItem()))
        End If
    End Sub


    Private Sub OpenFileDialog_FileOk(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialog.FileOk


    End Sub


    Private Sub AttributesListView_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AttributesListView.Click
        With Me.AttributesListView
            Dim i As Integer
            For Each item As ListViewItem In AttributesListView.SelectedItems
                i = item.Index
            Next


            Dim innercounter As Integer = 0
            For Each subItem As ListViewItem.ListViewSubItem In AttributesListView.Items(i).SubItems
                Dim myString As String = AttributesListView.Items(i).SubItems(innercounter).Text
                Select Case innercounter
                    Case 1
                        LabelTextBox.Text = myString
                End Select
                innercounter += 1
            Next
        End With
    End Sub


    Private Sub SaveXmlButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveXmlButton.Click


    End Sub
End Class
 
Hi Roy,

Overall there is nothing wrong with your code. There are loads of different ways, and more efficient ways, where things could have been written but this is down to knowledge and experience. On the basis it works then it is fine.

However, here are a couple of comments for you to start with:-

1) In your LoadButton click event you use the following code:-

VB.NET:
If OpenFileDialog1.ShowDialog() = DialogResult.Cancel Then
  Return
End If
This is incorrect in this context since Return has no real meaning here. The way this should have been structured is:-

VB.NET:
If Not OpenFileDialog1.ShowDialog() = DialogResult.Cancel Then
  'Process your Load code
End If
or

VB.NET:
If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
  'Process your Load code
End If
2) In the same LoadButton event you have:-

VB.NET:
Dim nodeList As XmlNodeList = document.DocumentElement.ChildNodes
You then do not use this so it can be removed.

There are a few things in your code like this but as you gain experience you can use that knowledge to make your code more efficient as you need to.

The only things that you are actually missing is the routine to update the XML node at the correct location with your new strings and the saving of the updated XML file.

Hope that helps.

Cheers,

Ian
 
I now have my code to lets me show the treeview and select items to view in a listview, on clicking the listview they are displayed in 3 text boxes, pressing the Update Button a new Form opens where i can see what was original and make my changes, i then have a button that will update the xml, this is where i am struggling a little, any suggestions

SaveTo DB.png

SaveFunction.png

Any other comments about what i have done or not done is always welcome too

VB.NET:
Public Class Form7


    Private Sub Form7_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        idTextBox.Text = Form6.TextBox3.Text
        OldNameTextBox.Text = Form6.TextBox1.Text
        OldLabelTextBox.Text = Form6.TextBox2.Text


        Dim document As XDocument = XDocument.Load("C:\VisionProject\IBS2000.xml")
        For Each curElement As XElement In document...<IBS2000>
            If curElement = idTextBox.Text Then
                NewLabelTextBox.Text = curElement.Attribute("Label")
                NewNameTextBox.Text = curElement.Attribute("Name")
            End If


        Next


    End Sub


    Private Sub DoneButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim document As XDocument = XDocument.Load("C:\VisionProject\IBS2000.xml")
        Dim NewName As String = NewNameTextBox.Text
        Dim NewLabel As String = NewLabelTextBox.Text


        For Each curElement As XElement In document...<IBS2000>


            If curElement = idTextBox.Text Then


                curElement.SetValue(NewName)
                curElement.SetAttributeValue("Name", NewName)
                curElement.SetValue(NewLabel)
                curElement.SetAttributeValue("Label", NewLabel)


                document.Save("C:\VisionProject\IBS2000.xml")


                Me.Close()
            End If
        Next


    End Sub


    Private Sub DoneButton_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DoneButton.Click


    End Sub


    Private Sub CancelButton1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CancelButton1.Click
        Me.Close()
    End Sub
End Class
 
Last edited:
Hi Roy,

For this one to work you need to step back to the drawing board a little bit. This is one of those cases where you cannot code something if you cannot actually visualise how you would go about doing it.

What you need to think about is what have you learned from doing this project so far? One thing that you do know is how to select nodes using the form xmlDoc.SelectNodes(<NodePosition>) so that has to be the basis on which you can structure a solution.

What I mean by this is that each node is located within it own node position i.e:-

Root/Root1/Section1/Root2/Section2 etc....

If you could find a way (and there is a way, believe me) to save the node position for each node that is added to the TreeView then you can use a simple LINQ query to get the actual node to be updated as we have done previously. i.e:-

VB.NET:
Dim xmlNode = (From Node In xmlDoc.SelectNodes(<NodePos>) Select Node, NodeID = DirectCast(Node, XmlNode).Attributes("id").InnerText Where NodeID = txtIDNo.Text).SingleOrDefault
 
With myNode
  .Attributes("Name").InnerText = txtName.Text
  .Attributes("Label").InnerText = txtLabel.Text
End With

Hope that helps and good luck.

Cheers,

Ian
 
Hi Ian,

I was thinking about this last night whilst watching TV and have realised that i cant do this from getting data from the text boxes i need to reference the node, the easiest way would be from teh selection made from teh treeview , so the below code sends the nede data to the Listview so thehis holds the answers to updating it as well, if i can get the data from "ListviewItems" to my text boxes i can update back to "ListViewItems"

VB.NET:
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]    
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] TreeView1_NodeMouseClick([/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] sender [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]Object[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2], [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] e [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]TreeNodeMouseClickEventArgs[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]) [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] TreeView1.NodeMouseClick[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
        AttributeListView.Items.Clear()


        
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] e.Node.Tag [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]IsNot[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]Nothing[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]Then[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]
[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]            AttributeListView.Items.AddRange(
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]DirectCast[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2](e.Node.Tag, [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af][FONT=Consolas][SIZE=2][COLOR=#2b91af]ListViewItem[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]()))[/SIZE][/FONT][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]
        
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]
[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2]    
[/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][FONT=Consolas][SIZE=2][FONT=Consolas][SIZE=2] [/SIZE][/FONT][/SIZE][/FONT][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT]
[FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][FONT=Consolas][SIZE=2][COLOR=#0000ff][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT][/COLOR][/SIZE][/FONT]
 
Hi Roy,

Yes you can do what you have said but that does not solve your problem. The issue here is how to identify and store the location of the node to be updated within the XML file. You already have a working structure in place, you just need to expand upon it.

Cheers,

Ian
 
Hmm, I understand what you are saying but cant think how to get there, the only part of the code from form 6 where i am getting my information is the code below, i cant see how i can use the code from Form 1 as it is not linked to the information i am sending to form 6.

Form 6
VB.NET:
    Public Sub GetAttributes(ByVal node As XmlNode, ByVal treeNode As TreeNode)
        If node.Attributes IsNot Nothing Then
            Dim attributes As ListViewItem() = New ListViewItem(node.Attributes.Count - 1) {}


            For i As Integer = 0 To node.Attributes.Count - 1
                attributes(i) = New ListViewItem(New String() {node.Attributes(i).Name, node.Attributes(i).Value})
            Next


            treeNode.Tag = attributes
        End If
    End Sub

Form 1
VB.NET:
 If NodeLocation < MaxListViews Then
                'set an object to the next control to be updated
                Dim myNextControl As ListView = DirectCast(Me.Controls(ControlSelector & NodeLocation + 1), ListView)
                Dim strXMLPos As String = "//Root"
                'identify the selected ID of the element that has been clicked
                Dim SelectedID As Integer = CInt(myListView.SelectedItems(0).SubItems(1).Text)


                'create the string to read nodes from the file
                For Counter As Integer = 1 To NodeLocation + 1
                    strXMLPos += "/Root" & Counter & "/Section" & Counter
                Next


                'get the node list at the specified location
                Dim nodesToDisplay = (From MyNode In xmlDoc.SelectNodes(strXMLPos) Select MyNode, NodeID = CInt(DirectCast(MyNode, XmlNode).ParentNode.ParentNode.Attributes.ItemOf("id").InnerText) Where NodeID = SelectedID)
                For Each curNode In nodesToDisplay
                    Dim myNode As XmlNode = DirectCast(curNode.MyNode, XmlNode)
                    Dim LVI As New ListViewItem
                    With LVI
                        .Text = myNode.Attributes.ItemOf("Name").InnerText
                        .SubItems.Add(myNode.Attributes.ItemOf("id").InnerText)
                        .SubItems.Add(myNode.Attributes.ItemOf("Label").InnerText)
                    End With
                    myNextControl.Items.Add(LVI)
 
Hi Roy,

In your GetAttributes routine have a look at the different properties exposed by the Node parameter. You have got yourself blinded by the Attribute properties of the Node and you have missed what else is available to you within the properties of the Node itself.

Once you find the right property to use you can build your NodePosition string from there and save it with the TreeView Node.

Cheers,

Ian
 
Hi Ian,

The attribute that binds everything together is my "id" which is unique to the whole xlm, so my understanding is that i need to relate everything back to the "id".

(curNode.Attributes.ItemOf("id").InnerText)

The only other thing is the location of the node itself by means of Root/Root1/Section1/Root2/Section2/Root3/Section3.

Dim SelectedID As Integer = CInt(myListView.SelectedItems(0).SubItems(1).Text)

 
Last edited:
Hi Ian,

Just to change tactics a little here, on the bigger picture i think i have may have created a form that really serves no purpose, i am already using my form 1 to get the nodes displayed so i should be able to use this to modify my selection.

From my main form 1 i navigate my xml through the various ListViews, what is stopping me having a Modify button on this form that directly sends the data and node location to a save form, via the SelectedIndexChanged, there must be a Dim that handles this already, so if i do a step-into then it will be just before the nodeToDisplay Dim, if i understand things correctly, this will simplify the whole process (what i mean is i want this to be user friendly) not form after form.

Roy
 
Hi Roy,

Regarding your first point, you are correct. When you have these two snippets of information you can then use the LINQ query posted earlier to interrogate and update the XML document.

With regards to your second point, its up to you how you want to deign your editor but user friendliness is always the ultimate goal when creating a UI for your project.

Hope that helps.

Cheers,

Ian
 
Hi Roy,

This is my last post before I jet off on holiday for a couple of weeks and since I have seen that you have given your solution some good rational thought it is only right of me to post where I got to so as not to leave you in the lurch.

You will need to add the following to a form:- a TreeView, 3 Buttons (btnLoad, btnUpdate, btnSave), 4 TextBoxes (txtIDNo, txtName, txtLabel, txtNodePos) and then replace the form code with the code below.

What you might like about the way I coded the solution is that I ignored all the root nodes and comments when adding to the TreeView and I also ensured that the TreeView text property displayed the Name attribute of the Node. This way when a user navigates the structure of the TreeView they can see where they need to navigate to rather than having to figure out what the nodes RootX/SectionX mean.

There are plenty of comments in the code to help you understand what I have written and I hope that helps you to ultimately get to where you need to be.

Good luck and cheers,

Ian

VB.NET:
Imports System.Xml
Imports System.IO
 
Public Class Form1
  Private Const xmlFileName As String = "d:\temp\IBS2000.xml"
  'Here I declare the private XMLDocument variable which has scope anywhere within this form
  'You could declare this Publically so this is accessible outside of the form
  Private xmlDoc As New XmlDocument()
  Private XMLFileChanged As Boolean
 
  Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles btnLoad.Click
    'Here we load the file into the TreeView - you could put this in the
    'form load event for simplicity if you like
    Me.Cursor = Cursors.WaitCursor
 
    Dim strmReader As New StreamReader(xmlFileName, System.Text.Encoding.UTF8)
    Dim xmlReader As XmlTextReader = New XmlTextReader(strmReader)
 
    xmlReader.WhitespaceHandling = WhitespaceHandling.None
    xmlDoc.Load(xmlReader)
    'the XMLDocument variable now has the contents of the XML file
    'so we can close the reader therefore closing the file on the disk
    xmlReader.Close()
 
    'add the root node to the TreeView
    Dim StartTreeNode As TreeNode = TreeView1.Nodes.Add("Root")
    Const strXMLPos As String = "//Root"
 
    For Each myNode As XmlNode In xmlDoc.SelectNodes(strXMLPos)
      'loop through all the top level nodes using a for loop and add the node
      'to the parent node using the subroutine:-
      'AddTreeNode(ParentNode, NodeToAdd, XMLFilePosition
      AddTreeNode(StartTreeNode, myNode, "/")
    Next
 
    Me.Cursor = Cursors.Default
  End Sub
 
  Private Sub AddTreeNode(ByVal CurrentNode As TreeNode, ByVal xmlNodeToAdd As XmlNode, ByVal strXMLPos As String)
    'first we deal with any comments in the XML file and ignore them
    Const IgnoreString As String = "#comment"
 
    If Not xmlNodeToAdd.Name = IgnoreString Then
      'build the current position of the node within the XML file
      strXMLPos += "/" & xmlNodeToAdd.Name
      'check for Root elements (do not have id attribute)
      'do not need to add the node but do need to continue looping
      'through available child nodes
      If Not IsNothing(xmlNodeToAdd.Attributes("id")) Then
        'add the new node to the TreeView using the parent node
        Dim NewNode As TreeNode = CurrentNode.Nodes.Add(xmlNodeToAdd.Attributes("Name").InnerText)
        'create a Custom Type to hold the elements of the XML node
        'see the definition of the custom class below
        Dim MyNodeInfo As New NodeInfo
        With MyNodeInfo
          .NodePos = strXMLPos
          .Name = xmlNodeToAdd.Attributes("Name").InnerText
          .Label = xmlNodeToAdd.Attributes("Label").InnerText
          .IDNo = xmlNodeToAdd.Attributes("id").InnerText
        End With
        'add the custom type to the tag property of the tree node for access later
        NewNode.Tag = MyNodeInfo
        'this is the bit that makes the whole thing work
        'we now check for child nodes within the current node that
        'has just been added to the tree view
        'we then call AddTreeNode again to add the child nodes to this node
        'This is called recursive programming
        If xmlNodeToAdd.HasChildNodes Then
          For Each ChildNode As XmlNode In xmlNodeToAdd.ChildNodes
            AddTreeNode(NewNode, ChildNode, strXMLPos)
          Next
        End If
      Else
        'just recurse child nodes if they exist within a root node
        If xmlNodeToAdd.HasChildNodes Then
          For Each ChildNode As XmlNode In xmlNodeToAdd.ChildNodes
            AddTreeNode(CurrentNode, ChildNode, strXMLPos)
          Next
        End If
      End If
    End If
  End Sub
 
  Private Sub TreeView1_AfterSelect(sender As System.Object, e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
    'once you click on a tree node it takes the information stored in the tag property
    'and displays the information in the Text Boxes
    Const RootNode As String = "Root"
    Dim TN As TreeNode = TreeView1.SelectedNode
    If Not TN.Name = RootNode Then
      Dim MyNodeInfo As NodeInfo = DirectCast(TN.Tag, NodeInfo)
      With MyNodeInfo
        txtIDNo.Text = .IDNo
        txtLabel.Text = .Label
        txtName.Text = .Name
        txtNodePos.Text = .NodePos
      End With
    Else
      txtIDNo.Clear()
      txtLabel.Clear()
      txtName.Clear()
      txtNodePos.Clear()
    End If
  End Sub
 
  Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles btnUpdate.Click
    'Here we update the tree node and the details held within the tag property
    If Not IsNothing(TreeView1.SelectedNode) Then
      Dim TN As TreeNode
      Dim myNodeInfo As NodeInfo
      TN = TreeView1.SelectedNode
      myNodeInfo = DirectCast(TN.Tag, NodeInfo)
      With myNodeInfo
        .IDNo = txtIDNo.Text
        .Name = txtName.Text
        .Label = txtLabel.Text
        .NodePos = txtNodePos.Text
      End With
      With TN
        .Text = txtName.Text
        .Tag = myNodeInfo
      End With
 
      'Here we update the XMLDocument variable with the new details from 
      'the text boxes
      Dim xmlNode = (From Node In xmlDoc.SelectNodes(txtNodePos.Text) Select Node, NodeID = DirectCast(Node, XmlNode).Attributes("id").InnerText Where NodeID = txtIDNo.Text).SingleOrDefault
      Dim myNode As XmlNode = DirectCast(xmlNode.Node, XmlNode)
      With myNode
        .Attributes("Name").InnerText = txtName.Text
        .Attributes("Label").InnerText = txtLabel.Text
      End With
 
      If Not XMLFileChanged Then
        XMLFileChanged = True
      End If
    End If
  End Sub
 
  Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles btnSave.Click
    'here we save the XMLDocument back to a file on the disk
    If XMLFileChanged Then
      xmlDoc.Save(xmlFileName)
      MsgBox("XML File Saved")
    Else
      MsgBox("XML File Has Not Changed. Save Not Needed!")
    End If
  End Sub
 
  'this is the custom class which has been created 
  'to hold the information on the XML node
  Private Class NodeInfo
    Public Property NodePos As String
    Public Property Name As String
    Public Property Label As String
    Public Property IDNo As String
  End Class
End Class
 
Hi Ian,

Thanks so much for your help, i wouldn't have gotten anywhere with out it, i will take a good look at the code when i get back home next week. this has all given me some good understanding but most of all and probably more importantly it has taught me that i need to sit down and learn from the beginning, i have ordered some good books and have some good videos to look at over the next few weeks.

Have a great holiday and once again thanks for your help

Roy
 

Latest posts

Back
Top