#wpf #xaml #treeview #datatemplate
#wpf #xaml #просмотр дерева #табличка данных
Вопрос:
Я пытаюсь настроить функциональность «развернуть при выборе» для TreeViewItem
определенного типа, как показано ниже:
<UserControl x:Class="ImprovedDirectory.Views.DirectoryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ImprovedDirectory.Views"
xmlns:vms="clr-namespace:ImprovedDirectory.ViewModels"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<DataTemplate x:Key="CollapsedItem" DataType="{x:Type vms:DirectoryItemViewModel}">
<TextBlock
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="5"/>
</DataTemplate>
<DataTemplate x:Key="ExpandedItem" DataType="{x:Type vms:DirectoryItemViewModel}">
<StackPanel DataContext="{Binding}">
<TextBlock
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="5"
Grid.Row="0"/>
<TextBlock
Text="{Binding Number, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="2.5"
Grid.Row="1"/>
<TextBlock
Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="2.5"
Grid.Row="2"/>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<TreeView x:Name="DirectoryTreeView" ItemsSource="{Binding Groups}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vms:DirectoryGroupViewModel}" ItemsSource="{Binding Items, UpdateSourceTrigger=PropertyChanged}">
<TextBlock
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center"
Margin="5"/>
</HierarchicalDataTemplate>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Setters>
<Setter Property="ItemTemplate" Value="{StaticResource CollapsedItem}"/>
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ItemTemplate" Value="{StaticResource ExpandedItem}"/>
</Trigger>
</Style.Triggers>
</Style>
</TreeView.Resources>
</TreeView>
Вывод выше выглядит следующим образом, и я понятия не имею, почему:
Вот как это должно выглядеть, когда ничего не выбрано:
Я знаю, что это что-то действительно простое, чего мне не хватает с привязками. Однако на данный момент я действительно не уверен, я протестировал каждый DataTemplate
элемент в UserControl.Resources
по отдельности, и они оба работают так, как задумано.
У меня также возникла проблема, которая, казалось бы, связана с Style
перезаписью форматирования для группы, а также только для элемента, поэтому я предполагаю, что второй вопрос будет касаться того, как я могу определить, какой конкретный DataType
вывод выполняется для элементов, а не для всех объектов.
Будем признательны за любую помощь.
Ответ №1:
Вывод, который вы видите, обусловлен тем фактом, что вы установили DataTemplate
as ItemTemplate
в своем TreeViewItem
стиле, который не имеет представления иерархии, например, ItemsSource
для дочерних элементов.
Если вы измените шаблоны, чтобы они были HierarchicalDataTemplate
такими же, как у вас TreeView
, вы получите иерархию, но я не думаю, что это работает так, как вы предполагали. Когда вы разворачиваете элемент и выбираете его или другой впоследствии, вы увидите, что шаблон меняется для всех дочерних элементов, и выделение прерывается.
Вместо замены шаблонов данных вы можете достичь желаемого результата более простым способом, просто объединив оба шаблона в один и отреагировав на IsSelected
свойство в триггере, которое изменяет видимость элементов управления, которые скрыты, когда они не выбраны.
<TreeView x:Name="DirectoryTreeView"
ItemsSource="{Binding Groups}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type vms:DirectoryGroupViewModel}"
ItemsSource="{Binding Items}">
<StackPanel>
<TextBlock Text="{Binding Name}"
VerticalAlignment="Center"
Margin="5"/>
<TextBlock x:Name="NumberTextBlock"
Text="{Binding Number}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="Collapsed"/>
<TextBlock x:Name="EmailTextBlock"
Text="{Binding Email}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="Collapsed"/>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=IsSelected}" Value="True">
<Setter TargetName="NumberTextBlock" Property="Visibility" Value="Visible"/>
<Setter TargetName="EmailTextBlock" Property="Visibility" Value="Visible"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Вместо триггеров вы также можете использовать a BooleanToVisibilityConverter
для привязки Visibility
напрямую.
<TreeView x:Name="DirectoryTreeView"
ItemsSource="{Binding Groups}">
<TreeView.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</TreeView.Resources>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type vms:DirectoryGroupViewModel}"
ItemsSource="{Binding Items}">
<StackPanel>
<TextBlock Text="{Binding Name}"
VerticalAlignment="Center"
Margin="5"/>
<TextBlock Text="{Binding Number}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="{Binding Email}"
VerticalAlignment="Center"
Margin="2.5"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>