tags:

views:

1751

answers:

1

I'm having some problems changing the DataTemplate that is used for a TreeViewItem when it is selected. Ideally, I would like each item to contain a TextBlock, and then when selected it should contain a TextBox instead.

Here is what I have so far (I used this question as a starting point):

<Window>
    <Window.Resources>
        <HierarchialDataTemplate x:Key="normal"
            ItemsSource="{Binding Path=Children}">
            <TextBlock Text="{Binding Path=Text}" />
        </HierarchialDataTemplate>
        <HierarchialDataTemplate x:Key="selected"
            ItemsSource="{Binding Path=Children}">
            <TextBox Text="{Binding Path=Text}" />
        </HierarchialDataTemplate>
        <Style TargetType="{x:Type TreeViewItem}" x:Key="ContainerStyle">
            <Setter Property="ItemTemplate" Value="{StaticResource normal}" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="ItemTemplate" Value="{StaticResource selected}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resource>
    <Grid>
        <TreeView ItemSource="{Binding Body}" ItemContainerStyle="{StaticResource ContainerStyle}" />
    </Grid>
</Window>

What happens is that there is only one node in the tree, and the text of the node is the type name of the object. It sounds like the type bound to the node isn't what the template is expecting, so it's using the default ToString() binding instead of the Text property as I specified.

I have set the DataContext of the Window in the code behind file. I know that my Bindings for the data are correct, because if I set one HierarchialDataTemplate for the TreeView the data is displayed correctly.

I think that my problem is that I need to set a property other than ItemTemplate in the TreeViewItem styles - am I using the right property, or should I set something else?

+1  A: 

It's actually the HeaderTemplate you need - that's what governs the style of the node itself. Just so there is a complete sample, this is what worked for me:

<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
    <HierarchicalDataTemplate x:Key="normal"
                             ItemsSource="{Binding Path=Children}">
        <TextBlock Text="{Binding Path=Text}" />
    </HierarchicalDataTemplate>
    <HierarchicalDataTemplate x:Key="selected"
                             ItemsSource="{Binding Path=Children}">
        <TextBox Text="{Binding Path=Text}" />
    </HierarchicalDataTemplate>
    <Style TargetType="{x:Type TreeViewItem}"
           x:Key="ContainerStyle">
        <Setter Property="HeaderTemplate"
                Value="{StaticResource normal}" />
        <Style.Triggers>
            <Trigger Property="IsSelected"
                     Value="True">
                <Setter Property="HeaderTemplate"
                        Value="{StaticResource selected}" />
            </Trigger>
        </Style.Triggers>
    </Style>
    </Window.Resources>
    <Grid>
        <TreeView x:Name="_Tree" ItemContainerStyle="{StaticResource ContainerStyle}"/>
    </Grid>
</Window>

.. with some test code behind like this:

Imports System.Collections.ObjectModel

Class Window1

    Private Sub Window1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim Root As New Node
        Root.Text = "Root"

        Dim Child As New Node
        Child.Text = "Child"
        Root.Children.Add(Child)

        Dim Nodes As New Collection(Of Node)
        Nodes.Add(Root)
        _tree.itemssource = Nodes

    End Sub

End Class

Public Class Node

    Private _Text As String
    Public Property Text() As String
        Get
            Return _Text
        End Get
        Set(ByVal Value As String)
            _Text = Value
        End Set
    End Property

    Private _Children As New Collection(Of Node)
    Public Property Children() As Collection(of node)
        Get
            Return _Children
        End Get
        Set(ByVal Value As Collection(of node))
            _Children = Value
        End Set
    End Property

End Class
fubaar
That worked - not sure how I missed the HeaderTemplate property. Ah well. Thank you very much! :)
Andy