0

I'm doing my first bigger project with WPF and my first project with MVVM.

I want to fill a TreeView with values from a list of a self-defined class.

The part of my XAML looks similar to this:

<Window>
    <StackPanel>
    ...
        <TreeView>
            <TreeViewItem>
                <TreeViewItem />
                <TreeViewItem.ItemTemplate>
                    <HierarchicalDataTemplate 
                        ItemsSource="{Binding ListOfFoo}">
                        <StackPanel>
                            <CheckBox VerticalAlignment="Center" Width="50" 
                                      Content="{Binding Bar.Description}" IsChecked="{Binding IsChosen}"/>
                            <TextBox Width="38" VerticalAlignment="Center" 
                                     Text="{Binding SomeText}" IsEnabled="{Binding IsChosen}" />  
                        </StackPanel>
                    </HierarchicalDataTemplate>
                </TreeViewItem.ItemTemplate>
            </TreeViewItem>
        </TreeView>
    ...
    </StackPanel>
</Window>

The property at my ViewModel looks like this:

public List<Foo> ListOfFoo
{ 
    get { return listoffoo; }
    set 
    { 
        listoffoo = value; 
        OnPropertyChanged("ListOfFoo");
    }
}

Foo has the properties IsChosen, Bar (which is another type with a property Description) and SomeText.

When I execute my code, I can see the TreeView with the first item shown (which has some UI elements that I left out for better reading), but the items (in my test case should be 2) are not shown.

I used the following resources:

Fill wpf treeview with mvvm

(Can someone tell me where the x:Type comes from? I don't have that available in my x Namespace, which is defined as follows:

http://blogs.msdn.com/b/mikehillberg/archive/2009/10/30/treeview-and-hierarchicaldatatemplate-step-by-step.aspx

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

What am I doing wrong? Any help is appreciated.

Community
  • 1
  • 1
Marin Althuis
  • 168
  • 3
  • 14
  • This is a concise example of how it is done http://stackoverflow.com/a/28994128/1228 You can create a new project and paste that code in and it works. Do that, then compare it with your current project to find out what is different. –  Apr 28 '15 at 13:56
  • You didn't use ObservableCollection, maybe this is the issue? – Wojciech Kulik Apr 28 '15 at 13:58
  • Your x:Type question--that xmlns is defined in PresentationCore. Grab Telerik's JustDecompile, load the net 4.5 framework, and click on PresentationCore in the list. You can see the xmlnsdefinition for that namespace pointing to System.Windows.Markup. Here's how it's implemented https://msdn.microsoft.com/en-us/library/ms753322(v=vs.110).aspx –  Apr 28 '15 at 14:04
  • @Will thank you for your example, I'll have a look at it :-). The x:Type problem could be related to me using .NET 4.0. I'll change the project to 4.5m that could be the issue. – Marin Althuis Apr 28 '15 at 14:20
  • No, your x:Type issue (not clear what the issue is) isn't related to version. If anything, it should "just work". If it doesn't, you've screwed up something in your references, codebehind, or xaml. Create a fresh wpf project. Examine each of these three in the new project, and make sure you have equivalents in yours. –  Apr 28 '15 at 16:05
  • Hi Wojciech and Will, I have played around a bit with your ideas. First, I changed the List to an ObservableCollection. Then I removed the other Items (which are static, but I need them) from the TreeView and put them in another TreeView which only consists of those static items. These two steps solved my problem. Many thanks to both of you :-) – Marin Althuis Apr 30 '15 at 07:31
  • Kind of a meta question, but related to here: Wojciech's answer helped me, but the problem was solved by his comment. I can't upvote the comment though, because I don't have the reputation :/ I'll mark his answer as the correct answer for now. – Marin Althuis Apr 30 '15 at 08:13

1 Answers1

1

I think you wanted to achieve something like this:

<Window>
    <StackPanel>
        <TreeView ItemsSource="{Binding MainCollection}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding InnerCollection}">
                    <StackPanel>
                        <CheckBox VerticalAlignment="Center" Width="50" 
                                  Content="{Binding Bar.Description}" IsChecked="{Binding IsChosen}"/>
                        <TextBox Width="38" VerticalAlignment="Center" 
                                 Text="{Binding SomeText}" IsEnabled="{Binding IsChosen}" />  
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>

            <TreeViewItem />
        </TreeView>
    </StackPanel>
</Window>

Your mistakes:

  • you set ItemTemplate for TreeViewItem, but you should set ItemTemplate for TreeView
  • you added <TreeViewItem /> inside <TreeViewItem> instead of <TreeView>
  • you should bind to ItemsSource of TreeView with your main collection and to ItemsSource of HierarchicalDataTemplate with collection inside each element. For example if you have:

    • Players
      • Player 1
        • Teams
          • Team 1
          • Team 2
      • Player 2
        • Teams
          • Team 1
          • Team 2

then you should set binding in TreeView to players list and in HierarchicalDataTemplate to teams list.

Wojciech Kulik
  • 7,823
  • 6
  • 41
  • 67