2

I've been doing some search on google and reading some similar questions here on SO but haven't found the answer to my question yet. I am binding an xml file to a treeview control in WPF. Using this article I am easily able to set up 2-way databinding with my xml file.

However, I would like to apply sorting to my xml document before I attach it. I am modelling a task organizer in which tasks contain start dates and due dates and I would like to order nodes by pending due date so the most urgent tasks appear first. I have some experience with Linq to XML but am not sure how to approach the binding issue. Any thoughts?

So after some more reading here is my pseudo code:

  • Create an XDocument from my local XML file
  • Sort the XDocument based on the tasks due date
  • Create a new XmlDataProvider from the newly sorted XDocument
  • Bind it to the TreeView

Can anyone help me flush this out?

2
  • Your question doesn't fit the question title. Is this about sorting an XML file or binding it to a TreeView? It seems your question is just about XML and not about WPF at all. Once it's sorted you want to bind it afterward and from what you've said your binding already works. Commented Jun 8, 2012 at 18:07
  • Sorry I guess it needs clarification. I can easily sort the xml document using linq to xml but once it is sorted and is stored in memory how do I bind it to the treeview? Commented Jun 8, 2012 at 18:09

1 Answer 1

3

Here's a basic example of how to implement XML to TreeView binding. XmlDataProvider allows you to load an XML document and bind to it. HierarchicalDataTemplate allows you to define TreeView templates with sub-items. XPath must be used to bind instead of Path, and the @ symbol prefix indicates binding to an attribute.

<Window x:Class="Testing.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <XmlDataProvider x:Key="people" XPath="People" />

        <HierarchicalDataTemplate x:Key="colorsTemplate">
            <TextBox Text="{Binding XPath=@Name, Mode=TwoWay}" />
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate x:Key="rootTemplate" ItemsSource="{Binding XPath=FavoriteColors/Color}" ItemTemplate="{StaticResource colorsTemplate}">
            <StackPanel Orientation="Horizontal">
                <TextBox Text="{Binding XPath=@FirstName, Mode=TwoWay}" />
                <TextBlock Text=" " />
                <TextBox Text="{Binding XPath=@LastName, Mode=TwoWay}" />
                <TextBlock Text=" (Age: " />
                <TextBox Text="{Binding XPath=@Age, Mode=TwoWay}" />
                <TextBlock Text=")" />
            </StackPanel>
        </HierarchicalDataTemplate>

    </Window.Resources>
    <Grid>
        <TreeView ItemsSource="{Binding Source={StaticResource people}, XPath=Person}" ItemTemplate="{StaticResource rootTemplate}" Grid.ColumnSpan="2" />
    </Grid>
</Window>

Using the following XML file:

<?xml version="1.0" encoding="utf-8" ?>
<People>
  <Person FirstName="Ringo" LastName="Starr" Age="72">
    <FavoriteColors />
  </Person>
  <Person FirstName="George" LastName="Harrison" Age="52">
    <FavoriteColors>
      <Color Name="Orange" />
      <Color Name="Green" />
      <Color Name="Purple" />
    </FavoriteColors>
  </Person>
  <Person FirstName="Paul" LastName="McCartney" Age="42">
    <FavoriteColors>
      <Color Name="White" />
    </FavoriteColors>
  </Person>
  <Person FirstName="John" LastName="Lennon" Age="33">
    <FavoriteColors>
      <Color Name="Red" />
      <Color Name="Green" />
    </FavoriteColors>
  </Person>
</People>

And the following code-behind:

XmlDataProvider people;

public MainWindow()
{
    InitializeComponent();

    people = FindResource("people") as XmlDataProvider;

    var xmlDocument = new XmlDocument();

    xmlDocument.Load("People.xml");

    people.Document = xmlDocument;
}

As you can see I am loading the XML document in code, so you can load it into an XDocument or XmlDocument class and sort it how you want. Then you should be able to save it back to file at some point.

EDIT:

Here's an example of loading and saving at runtime:

private void Load_Click(object sender, RoutedEventArgs e)
{
    var xmlDocument = new XmlDocument();

    xmlDocument.Load("People.xml");

    people.Document = xmlDocument;
}

private void Save_Click(object sender, RoutedEventArgs e)
{
    XmlDocument xml = people.Document;

    if (xml != null)
    {
        Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();

        if ((bool)sfd.ShowDialog(this))
        {
            xml.Save(sfd.FileName);
        }
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is very cool, but I wonder if it would be possible to make it more generic. In other words, how would you make this work for any xml file? How would you handle {Binding XPath=@FirstName, Mode=TwoWay} if the attributes (eg FirstName) are not known, and can be different each time? (I'll pose this as it's own question if you'd like)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.