Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Displaying XML in a WPF TreeView

0.00/5 (No votes)
23 Jan 2012 2  
In this article, I describe how to display data from a simple XML file in a WPF TreeView control.

Introduction

In this article, I will describe how to display data contained in a simple XML file using a TreeView control in a WPF application without writing any code. In this article, all of the magic is found in the XAML file that defines the window contents. Admittedly, you would not try to write a business application like this, but there may be something to learn here that will make that business application go together a little more easily.

Background

This article draws on information gleaned from two other articles about using XML with WPF that you may wish to read. The first is called Reaction to: A Simple WPF Explorer Tree by Josh Smith. In that article, Smith demonstrates how to use a DataTemplate to define the contents of TreeViewItems, and how the tree structure can be built using the window's "Loaded" event handler. The second article by Karl Shifflett took off from Smith's article. Shifflett's article is called Over Reaction To: A Simple WPF Explorer Tree. Shifflett's article described the HierarchicalDataTemplate demonstrating how it could be used to help recurse tree structure data to populate a TreeView control.

I found these two articles trying to find a solution to populate a TreeView with directory and file names similar to Window Explorer's directory tree, but including at least some filenames as well. While working that out, I had issues with strange behavior in the TreeView and decided to run some tests with XML data. That proved to be a bit of a challenge itself, but with information gleaned from Shifflett and Smith's articles, and a little use of the grey matter, I came up with the solution described below to populate a TreeView control with XML data.

Using the Code

It is actually fairly easy to display XML data using WPF. Other than the XML file itself, almost all of the work to enable this is done within XAML, and most of that is done by defining several resources. The source code available with this article is a complete working sample. The project is configured to use .NET 4.0, but you can move MainWindow.xaml and testdata.xml into a WPF 3.0 project, and it should work just as well.

In the text below, I will highlight just a sample of the XAML code that makes this work.

When you create a WPF project, a skeleton window is created in a file called MainWindow.xaml which opens in the Visual Studio editor. A little XAML is included to configure the default window with a Grid control to hold the rest of the visual elements of the window. In our code, we add a new child to the Window element right before the opening Grid tag, and below the opening Window tag, to create a section within Window to define some resources. To start out, the resources section looks like this:

<!-- This goes immediately after the opening Window tag -->
<Window.Resources>
</Window.Resources>

Then between those Window.Resources tags, we add several elements that will be used by the UI to display the XML data. The first resource we add is an XmlDataProvider. XmlDataProvider is a class that makes it possible to bind XML data to elements and work with the XML structure. An object is created by creating a resource from it like this:

<XmlDataProvider x:Key="xmldata"
                 Source="testdata.xml"
                 XPath="/root" />

The Source attribute is set to the name of the XML file we created for the test, but it does not actually reference a file during run time. By putting the file in the root directory of the project, and setting its build action to "Resource", the contents of the file are actually made a part of the assembly during compile time. So in this case, the filename becomes the key name for the resource, and WPF is smart enough to work out the details when the application runs. The XPath attribute is used to specify a node. The XML test file has a root node called "root", so we use that here to start the XML parsing with that node.

The really interesting work is done in data templates created with HierarchicalDataTemplate. Again, within the Window.Resources element, right below the XmlDataProvider, we create a data template for each type of tag used within the XML test file. In this case, three node items exist within testdata.xml, "root", "Node", and "leaf". So we create three data templates. The template for "Node" looks like this:

<HierarchicalDataTemplate DataType="Node"
                           ItemsSource="{Binding XPath=./*}">
    <StackPanel Orientation="Horizontal">
        <TextBlock Margin="0"
                   Text="Node:" />
        <TextBlock Margin="5,0,0,0"
                   Text="{Binding XPath=@name}" />
    </StackPanel>
</HierarchicalDataTemplate>

The other templates are similar. The main difference to note is that the ItemsSource attribute was not specified for "leaf" nodes, because I knew that I placed no items within "leaf" nodes. Such nodes are always at the end of the line, so there is no reason to check them for contents. The ItemsSource attribute is provided by HierarchicalDataTemplate specifically for this use. HierarchicalDataTemplate uses ItemsSource to determine if the current item contains other items. If not, the node will be rendered accordingly, and navigation further down into the node is impossible. But if other items are contained within the current item, it will be rendered so that the user can drill down into the node to see the other items.

The last thing to do is to bind the XML data to the UI controls. I do that by setting the DataContext of the Grid, and the ItemsSource attribute of the TreeView control. The complete UI is defined within just a few lines.

<Grid DataContext="{StaticResource xmldata}">
    <TreeView Name="dirTree"
          HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch"
          ItemsSource="{Binding}"
          VirtualizingStackPanel.IsVirtualizing="False"
          VirtualizingStackPanel.VirtualizationMode="Standard" />
</Grid>

That's it!

Points of Interest

The HierarchicalDataTemplate class made it very easy to populate the TreeView with XML data. There is no reason it could not be used in other scenarios to help in more complicated situations. The main things to remember are to create a template for each type expected by the TreeView (or else a parent type to catch several descending types) and to set the ItemsSource on types that may contain more data that needs to go into the TreeView.

History

  • January 20, 2012 - Original article.
  • January 21, 2012 - Cosmetic changes to correct code alignment.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here