How to Bind an XmlDataProvider Class Property to a XAML TreeView

sourcenouveau picture sourcenouveau · Jun 19, 2009 · Viewed 8.6k times · Source

I would like to bind a TreeView control I have defined in XAML to a property in its code-behind class. I already read through a WPF Basic Data Binding FAQ, but the example in the comments at the very bottom of the page didn't work when I tried to use an XmlDataProvider as the binding source.

How can I modify the following code so that the binding is defined in the XAML, rather than in the class's constructor? In other words, how can I modify the TreeView's ItemsSource attribute to reference a property in its code-behind class?

SomeClass.xaml - Works

<UserControl x:Class="SomeNamespace.SomeClass"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Resources>
        <XmlDataProvider x:Key="SomeTreeData" />
    </UserControl.Resources>
    <TreeView Name="SomeTree" ItemsSource="{Binding Source={StaticResource SomeTreeData}, XPath=*}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="items" ItemsSource="{Binding XPath=*}">
                <TextBlock Text="{Binding XPath=@Header}" />
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="item" ItemsSource="{Binding XPath=*}">
                <TextBlock Text="{Binding XPath=@Header}" />
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
</UserControl>

SomeClass.xaml.cs - Works

public partial class SomeClass : UserControl
{
    public SomeClass()
    {
        InitializeComponent();

        XmlDataProvider lSomeTreeData
            = this.FindResource("SomeTreeData") as XmlDataProvider;
        lSomeTreeData.Document = new XmlDocument();
        lSomeTreeData.Document.LoadXml("<items xmlns=\"\" Header=\"Some items\"><item Header=\"Some item\" /></items>");
    }
}

SomeClass.xaml - Desired

Note the {SOME MAGIC} in the TreeView's ItemsSource attribute.

<UserControl x:Class="SomeNamespace.SomeClass"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <TreeView Name="SomeTree" ItemsSource="{Binding Source={SOME MAGIC}, XPath=*}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="items" ItemsSource="{Binding XPath=*}">
                <TextBlock Text="{Binding XPath=@Header}" />
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="item" ItemsSource="{Binding XPath=*}">
                <TextBlock Text="{Binding XPath=@Header}" />
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
</UserControl>

SomeClass.xaml.cs - Desired

public partial class SomeClass : UserControl
{
    public XmlDataProvider SomeXmlDataProvider { get; set; }

    public SomeClass()
    {
        InitializeComponent();

        this.SomeXmlDataProvider = new XmlDataProvider();
        this.SomeXmlDataProvider.Document = new XmlDocument();
        this.SomeXmlDataProvider.Document.LoadXml("<items xmlns=\"\" Header=\"Some items\"><item Header=\"Some item\" /></items>");
    }
}

Answer

sourcenouveau picture sourcenouveau · Jun 30, 2009

I've discovered that one option is to set the control's DataContext:

<UserControl x:Class="SomeNamespace.SomeClass"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <TreeView ItemsSource="{Binding XPath=/items}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="items" ItemsSource="{Binding XPath=*}">
                <TextBlock Text="{Binding XPath=@Header}" />
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate DataType="item" ItemsSource="{Binding XPath=*}">
                <TextBlock Text="{Binding XPath=@Header}" />
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
</UserControl>

public partial class SomeClass : UserControl
{
    public XmlDataProvider SomeXmlDataProvider { get; set; }

    public SomeClass()
    {
        InitializeComponent();

        this.SomeXmlDataProvider = new XmlDataProvider();
        this.SomeXmlDataProvider.Document = new XmlDocument();
        this.SomeXmlDataProvider.Document.LoadXml("<items Header=\"Some items\"><item Header=\"Some item\" /></items>");

        this.DataContext = this.SomeXmlDataProvider.Document;
    }
}