Use XML Files with WPF

XML files are very handy for storing and display data that you might not want to keep in a database. It is wonderful choice for prototyping since you do not need to setup any database tables, connection strings and data objects. Instead you can send a complete project to a user that they can try out immediately without any setup at all. There are actually several methods you can use to display XML within a WPF application, let’s look at a few.

The XML Data
For the samples in this article, the XML data is a simple set of Product data. The XML file, called Product.xml, looks like the following:

<Products>
  <Product>
    <ProductId>1</ProductId>
    <ProductName>Architecting ASP.NET Applications
                 eBook</ProductName>
    <Price>19.95</Price>
  </Product>
  <Product>
    <ProductId>2</ProductId>
    <ProductName>Fundamentals of N-Tier eBook</ProductName>
    <Price>19.95</Price>
  </Product>
     ...
     ...
  <Product>
    <ProductId>3</ProductId>
    <ProductName>Security for ASP.NET Developers
                 eBook</ProductName>
    <Price>19.95</Price>
  </Product>
</Products>

Using the XML Data Provider
The simplest method of display XML data is to use the XmlDataProvider object in XAML. You create an XmLDataProvider and set its Source property to the location of where the XML file is located. Consider the following XmlDataProvider created in a Window.Resources area.

<Window.Resources>
  <XmlDataProvider x:Key="ProductData"
                   Source="/Product.xml"
                   XPath="Products/Product" />
</Window.Resources>

Notice that the Key is set to a unique identifier for this resource. You then specify the Source with where the XML file is located. Finally you specify the top level XPath query that will be used to get to the node level where you will be displaying data. If you use a ListBox on this Window you would specify the ItemsSource to be data bound to this StaticResource “ProductData”. You then reference the element name within the XML that you want to use to display in the ListBox. Since you have already specified “Products/Product” in the XPath attribute of the XmlDataProvider, the DisplayMemberPath can be just set to the element to display; in this case “ProductName”.

<ListBox
   ItemsSource="{Binding
                 Source={StaticResource ProductData}}"
   DisplayMemberPath="ProductName" />

Sorting using a CollectionViewSource
One additional nice feature you might want to add is the ability to sort the XML data. You can accomplish this complete in XAML by using a CollectionViewSource object. The CollectionViewSource object will take a source set of data from an XmlDataProvider (or any data provider for that matter) and you can then apply some additional elements to do things like sorting or grouping. For sorting data you will add SortDescriptions to the collection. Look at the XAML below.

<Window.Resources>
  <XmlDataProvider x:Key="ProductData"
                   Source="/Product.xml"
                   XPath="Products/Product" />
  <CollectionViewSource x:Key="collProducts"
                        Source="{StaticResource ProductData}">
    <CollectionViewSource.SortDescriptions>
      <scm:SortDescription PropertyName="ProductName"
                           Direction="Ascending" />
    </CollectionViewSource.SortDescriptions>
  </CollectionViewSource>
</Window.Resources>

You can see that you added a CollectionViewSource.SortDescriptions element within the <CollectionViewSource> element. This element allows you to add one or many sort description objects. The SortDescription object you add comes from the System.ComponentModel namespace within the WindowsBase assembly. So, you will need to add a XAML namespace at the top of your window that looks like the following:

xmlns:scm=
 "clr-namespace:System.ComponentModel;assembly=WindowsBase"

You can give it any “name” you want, I chose “scm”, so that is what I used when adding the SortDescription element with the PropertyName set to “ProductName” and the Direction set to “Ascending”. Setting these two properties is what will then sort the data in the CollectionViewSource by the ProductName element in the XML file. Notice that the Source property of the CollectionViewSource is set to the XmlDataProvider object. So the CollectionViewSource creates a collection of the XML data and applies to the sort description to create a new “view” of the original data. You now use the CollectionViewSource as the ItemsSource property of the List Box as shown below.

<ListBox
  ItemsSource="{Binding Source={StaticResource collProducts}}"
  DisplayMemberPath="ProductName" />

Using LINQ to XML
Another method you can use to display XML data in a WPF application is to use LINQ to XML. Sometimes LINQ to XML might be necessary if you have a more complicated XML file, or if you wish to filter the data in a special way, or just want to read a few elements instead of every element.
To use LINQ to XML you must set the Build Action property of the Product.xml file to “Content” and the Copy to Output Directory to “Copy if newer”. Instead of using an XmlDataProvider this time load the data writing some C# or VB code. In the ListBox you set the ItemsSource to “{Binding}”. This tells the list box that the data will be supplied at runtime.

<ListBox Margin="10"
         ItemsSource="{Binding}"
         Name="lstProducts" />

In the Windows Loaded event you will call the ProductsLoad procedure which uses LINQ to XML to create a collection of XElement objects.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
  ProductsLoad();
}

To use LINQ to XML you will need to import a couple of namespaces.

using System.Linq;
using System.Xml.Linq;

Now, in the ProductsLoad procedure you use the Load method of the XElement class to load the XML file. Then you write a normal LINQ query to iterate over the “Product” Descendants in the XML file. In this query you will also use an order by clause to order each element by ProductName, then select the ProductName. You could select more elements if you want, but since all you are doing is displaying ProductName in the ListBox, let’s just grab this one piece of data from the XML file.

private void ProductsLoad()
{
  var xElem = XElement.Load(@"Product.xml");

  var products = from prod in xElem.Descendants("Product")
           orderby prod.Element("ProductName").Value
           select prod.Element("ProductName").Value;

  lstProducts.DataContext = products;
}

Summary
XML files are a great way to display data in WPF applications. I find XML files to be especially useful for prototyping as I find creating XML files much quicker than creating database tables and hooking up to those database tables from WPF. You have a lot of different methods to retrieve the XML data. In this article I showed you how to display the data using the XmlDataProvider, a CollectionViewSource and LINQ to XML.

NOTE: You can download the complete sample code at my website. http://www.pdsa.com/downloads. Choose Tips & Tricks, then "Use XML Files in WPF" from the drop-down.

Good Luck with your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

Past Blog Content

Blog Archive

1 Comment

  • Can an XML file be included as a resource in the project? In that case, My.Resources.ResourceName would contain the XML text of the file. I can't see how to use that in the XmlDataProvider syntax. Any ideas how to do this?
    Thanks...

Comments have been disabled for this content.