3
votes

I'm pretty new to Xaml and need some advise.

A TreeView should be bound to a hierarchical object structure. The TreeView should have a context menu, which is specific for each object type.

I've tried the following:

<TreeView>
  <TreeView.Resources>
    <DataTemplate x:Key="RoomTemplate">
      <TreeViewItem Header="{Binding Name}">
        <TreeViewItem.ContextMenu>
          <ContextMenu>
            <MenuItem Header="Open" />
            <MenuItem Header="Remove" />
          </ContextMenu>
        </TreeViewItem.ContextMenu>
      </TreeViewItem>
    </DataTemplate>
  </TreeView.Resources>

  <TreeViewItem Header="{Binding Name}" Name="tviRoot" IsExpanded="True" >

  <TreeViewItem Header="Rooms"  
                ItemsSource="{Binding Rooms}"
                ItemTemplate="{StaticResource RoomTemplate}">
    <TreeViewItem.ContextMenu>
      <ContextMenu>
        <MenuItem Header="Add room"></MenuItem>
      </ContextMenu>
    </TreeViewItem.ContextMenu>
  </TreeViewItem>
</TreeViewItem>

But with this markup the behavior is as intended, but the child items (the rooms) are indented too much.

Anyway all the bining samples I could find use TextBlock instead of TreeViewItem in the DataTemplate, but wonder how to integrate the ContextMenu there.

1

1 Answers

8
votes

You would not normally create a DataTemplate containing a TreeViewItem, because the binding infrastructure will be creating the TreeViewItem for you -- all your DataTemplate needs to do is specify what should be displayed as the content of the TreeViewItem. That's why the samples you've found use TextBlocks instead of TreeViewItems in the DataTemplate.

I suspect the use of TreeViewItem rather than TextBlock causes the excessive indenting because you have a (manually created) TreeViewItem in your DataTemplate (which incurs one level of indent) inside another (automatic) TreeViewItem (which incurs another level of indent). Therefore, using a TextBlock instead of a TreeViewItem should cure this. Integrating the ContextMenu shouldn't be an issue because TextBlock has a ContextMenu property too.

So you should be able to just change your DataTemplate as follows:

<DataTemplate x:Key="RoomTemplate">
  <TextBlock Text="{Binding Name}">
    <TextBlock.ContextMenu>
      <ContextMenu>
        <MenuItem Header="Open" />
        <MenuItem Header="Remove" />
      </ContextMenu>
    </TextBlock.ContextMenu>
  </TextBlock>
</DataTemplate>

Incidentally for TreeViews it is common to use a HierarchicalDataTemplate rather than a plain DataTemplate because this allows for multiple levels of items via the HierarchicalDataTemplate.ItemsSource property. This may not be required in your scenario though.