Изменение шаблона TreeViewItem при его выборе

У меня возникли проблемы с изменением DataTemplate, который используется для TreeViewItem, когда он выбран. В идеале я хотел бы, чтобы каждый элемент содержал TextBlock, а затем, когда он выбран, он должен содержать вместо этого TextBox.

Вот что у меня есть до сих пор (я использовал этот вопрос в качестве отправной точки):

<Window>
    <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="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>

Что происходит, так это то, что в дереве есть только один узел, а текст узла - это имя типа объекта. Похоже, что тип, привязанный к узлу, не соответствует ожиданиям шаблона, поэтому он использует привязку по умолчанию ToString() вместо свойства Text, как я указал.

Я установил DataContext окна в коде файла. Я знаю, что мои привязки для данных верны, потому что, если я установил один HierarchicalDataTemplate для TreeView, данные будут отображаться правильно.

Я думаю, что моя проблема в том, что мне нужно установить свойство, отличное от ItemTemplate, в стилях TreeViewItem - я использую правильное свойство или мне нужно установить что-то другое?


person Andy    schedule 06.02.2009    source источник
comment
Опечатка в XAML: HierarchialDataTemplate должна быть HierarchicalDataTemplate.   -  person Mark Miller    schedule 26.02.2016
comment
@MarkMiller исправил - спасибо!   -  person Andy    schedule 26.02.2016


Ответы (1)


На самом деле вам нужен HeaderTemplate - это то, что определяет стиль самого узла. Вот что сработало для меня:

<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>

.. с некоторым тестовым кодом, например:

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
person fubaar    schedule 06.02.2009
comment
Это сработало - не знаю, как я пропустил свойство HeaderTemplate. Ах хорошо. Большое тебе спасибо! :) - person Andy; 07.02.2009