3
votes

I am trying to bind a collection of objects held by a Model to a treeview in WPF. My XML to do this was based on WPF Treeview Databinding Hierarchal Data with mixed types but I am not having any luck.

My current XAML looks like this for the treeview.

    <TreeView Name="ConfigurationFilter">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type models:MyModel}"  ItemsSource="{Binding Path=Filters.FilterType1}">
                <StackPanel Orientation="Horizontal">
                    <CheckBox></CheckBox>
                    <Label Content="{Binding Path=Name}"></Label>
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>

I have a model that looks like this

public class MyModel
{
    public Observable<MyFilter> FilterType1 {get;set;}
    public Observable<MyFilter> FilterType2 {get;set;}
}

public class MyFilter
{
    public string Name {get;set;}
    public bool IsSelected {get;set;}
}

Within my MainWindow.Xaml.cs I have the following:

public partial class MainWindow : Window
{
    public MyModel Filters { get; set; }
}

The FilterType1 property has 331 items in it. Yet when I run the app, the binding never happens. I do not see any items in my Treeview. What am I doing wrong?

Update 1

I have added my main window as the data context for the treeview and the binding as suggested but i still do not have any items in the tree

<TreeView Name="ConfigurationFilter" ItemsSource="{Binding Filters}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type models:MyModel}"  ItemsSource="{Binding Path=Filters.FilterType1}">
                <StackPanel Orientation="Horizontal">
                    <CheckBox></CheckBox>
                    <Label Content="{Binding Path=Name}"></Label>
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>

and my MainWindow.cs

    public MainWindow()
    {
        InitializeComponent();
        ConfigurationFilter.DataContext = this;
    }
2

2 Answers

3
votes

I was able to get this working by modifying my treeview to bind to a composite view model as demonstrated on CodeProject.

    <TreeView Grid.ColumnSpan="2" Grid.RowSpan="2">
        <TreeViewItem Header="Routes" Name="RouteView" ItemsSource="{Binding Routes}">
            <TreeViewItem.ItemTemplate>
                <HierarchicalDataTemplate DataType="{x:Type viewModels:RouteViewModel}"  ItemsSource="{Binding}">
                    <StackPanel Orientation="Horizontal">
                        <Label Content="{Binding Path=Name}" VerticalAlignment="Center"></Label>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeViewItem.ItemTemplate>
        </TreeViewItem>
    </TreeView>

Since my treeview will have multiple root nodes that are pre-determined, I had to bind the datasource to each root TreeViewItem. Then I placed my objects into a composite viewmodel.

Composite View Model

public class DomainViewModel
{
    public ReadOnlyCollection<RouteViewModel> Routes { get; set; }
    public ReadOnlyCollection<SkyViewModel> SkyLines { get; set; }

    public DomainViewModel(List<Route> routes)
    {
        Routes = new ReadOnlyCollection<RouteViewModel>(
            (from route in routes
             select new RouteViewModel(route))
             .ToList<RouteViewModel>());
    }

        Skylines = new ReadOnlyCollection<SkyViewModel>(
            (from route in routes
             select new SkyViewModel(route))
             .ToList<SkyViewModel>());
    }
}

ViewModel - Only 1 shown to help readability.

public class RouteViewModel : INotifyPropertyChanged
{
    private Route _route; // My actual database model.

    public string Name
    {
        get { return _route.RouteName; }
    }

    public RouteViewModel(Route route)
    {
        _route = route;
    }
}

MainWindow

    public MainWindow()
    {
        InitializeComponent();

        this.DomainFilterTreeView.DataContext = new this.Domains;
    }
0
votes

TreeView doesn't have an ItemsSource bound to. Assuming the DataContext of the TreeView is your MainWindow, then you can add the ItemsSource binding.

<TreeView Name="ConfigurationFilter" ItemsSource={Binding Filters}>
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type models:MyModel}"  ItemsSource="{Binding Path=Filters.FilterType1}">
            <StackPanel Orientation="Horizontal">
                <CheckBox></CheckBox>
                <Label Content="{Binding Path=Name}"></Label>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
     ConfigurationFilter.DataContext = this;
    }

    public MyModel Filters { get; set; }
}