Bind XML to ListView

Rubicon

New member
Joined
Nov 4, 2012
Messages
2
Programming Experience
Beginner
Hello,

I need some help with binding XML to ListView.

I have XML with defined test data:
VB.NET:
<?xml version="1.0" encoding="utf-8" ?>
<sets>
    <set sname="Testovací set 1">
        <servicename>Služba 1-1</servicename>
        <servicename>Služba 1-2</servicename>
        <servicename>Služba 1-3</servicename>
        <servicename>Služba 1-4</servicename>
    </set>
    <set sname="Testovací set 2">
        <servicename>Služba 2-1</servicename>
        <servicename>Služba 2-2</servicename>
        <servicename>Služba 2-3</servicename>
        <servicename>Služba 2-4</servicename>
    </set>
    <set sname="Testovací set 3">
        <servicename>Služba 3-1</servicename>
        <servicename>Služba 3-2</servicename>
        <servicename>Služba 3-3</servicename>
        <servicename>Služba 3-4</servicename>
    </set>
</sets>

I have ComboBox, where is loaded all values of sname from tags <set>.
After changing SelectedItem I wanna write all InnerText of tags <servicename> to ListView.

Please, have anyone solution for this case?

Thank you
 
Hi,

Try this example as a solution to your question. Create a new form, add a ComboBox and a ListView with it's view property set to details. Add the code below to the code behind and then change the file name in the StreamReader to the location of your file and Run.

VB.NET:
Imports System.Xml
Imports System.IO
 
Public Class Form1
 
  Private myReader As New StreamReader("d:\temp\XMLFile1.xml", System.Text.Encoding.UTF8)
  Private myXMlReader As XmlTextReader = New XmlTextReader(myReader)
  Private myXMLDoc As New XmlDocument()
 
  Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    myXMLDoc.Load(myXMlReader)
 
    RemoveHandler ComboBox1.SelectedIndexChanged, AddressOf ComboBox1_SelectedIndexChanged
    With ComboBox1
      .SelectedIndex = -1
      .Items.Clear()
    End With
    For Each mySet As XmlNode In myXMLDoc.GetElementsByTagName("set")
      ComboBox1.Items.Add(mySet.Attributes.ItemOf("sname").InnerText)
    Next
    AddHandler ComboBox1.SelectedIndexChanged, AddressOf ComboBox1_SelectedIndexChanged
    AddListViewHeader()
  End Sub
 
  Private Sub ComboBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
    Dim NodeCount As Integer
 
    For Each mySet As XmlNode In myXMLDoc.GetElementsByTagName("set")
      If mySet.Attributes.ItemOf("sname").InnerText = ComboBox1.SelectedItem.ToString Then
        ListView1.Items.Clear()
        For Each myServiceName As XmlNode In mySet.SelectNodes("servicename")
          NodeCount += 1
          Dim LVI As New ListViewItem
          With LVI
            .Text = NodeCount.ToString
            .SubItems.Add(myServiceName.InnerText)
          End With
          ListView1.Items.Add(LVI)
        Next
        AddListViewHeader()
      End If
    Next
  End Sub
 
  Private Sub AddListViewHeader()
    Dim LVHeader() As ColumnHeader = {New ColumnHeader With {.Text = "Service No", .Width = 150, .TextAlign = HorizontalAlignment.Left},
                                      New ColumnHeader With {.Text = "Service Name", .Width = -2, .TextAlign = HorizontalAlignment.Left}}
    ListView1.Columns.Clear()
    ListView1.Columns.AddRange(LVHeader)
  End Sub
End Class
Hope that helps.

Cheers,

Ian
 
You can also load the xml into a DataSet and set up bindings with that. You need to add two BindingSource components to your form.
here's the example of loading the data and configuring the bindings in the forms Load event handler:
        Dim ds As New DataSet
        ds.ReadXml("sets.xml")
        With Me.BindingSource1
            .DataMember = ds.Tables(0).TableName
            .DataSource = ds
        End With
        With Me.BindingSource2
            .DataMember = ds.Relations(0).RelationName
            .DataSource = Me.BindingSource1
        End With
        With Me.ComboBox1
            .DisplayMember = ds.Tables(0).Columns(1).ColumnName
            .DataSource = Me.BindingSource1
        End With

The ListView control is not a data binding control, if you used a DataGridView instead you could complete the bindings like this:
Me.DataGridView1.DataSource = Me.BindingSource2

For ListView control the items must be added manually each time the related item changes, this is best done using the CurrentChanged event of the related BindingSource:
    Private Sub BindingSource2_CurrentChanged(sender As Object, e As System.EventArgs) Handles BindingSource2.CurrentChanged
        With Me.ListView1.Items
            .Clear()         
            For Each row As DataRowView In Me.BindingSource2
                .Add(row(0).ToString)
            Next
        End With
    End Sub

Note also that it is a short way from this to using xsd.exe to generate a typed dataset from the xml file and then set up all the data binding configurations in designer.
 
Hi JohnH,

I had a funny feeling that there was going to be a more efficient way of dealing with XML files using DataSets and DataTables but up until now this had eluded me.

What's really interesting is how .NET automatically creates the relationships between the tables based on the structure of the XML file. Neat!

Thanks for the post and good to know.

Cheers,

Ian
 
Back
Top