Reputation: 82
I'm attempting to setup "expand on select" functionality on a TreeViewItem
of a specific type as below:
<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>
The output from above is as follows and I have no idea why:
This is what it should look like when nothing is selected:
I know it's something really simple I'm missing with the bindings. However, I'm really not sure at this point, I've tested each DataTemplate
element in the UserControl.Resources
individually and they both work as intended.
I also am having an issue it would seem with the Style
overwriting the formatting for the Group as well as just the item, so I guess the second question would be around how I can define which specific DataType
is being made primary output for the items, rather than all objects.
Any help would be greatly appreciated.
Upvotes: 0
Views: 535
Reputation: 22089
The output that you see comes from the fact that you set a DataTemplate
as ItemTemplate
in your TreeViewItem
style, which has no representation of hierarchy, e.g. an ItemsSource
for children.
If you change the templates to be HierarchicalDataTemplate
s like in your TreeView
, you get the hierarchy, but I do not think that this behaves as you intended. As you expand an item and select it or another subsequently, you will see the template changing for all children and selection is broken.
Instead of swapping data templates, you can achieve the desired result in a simpler way by just combining both templates into one and reacting on the IsSelected
property in a trigger, that changes the visibility of controls that are hidden when unselected.
<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>
Instead of triggers, you could also use a BooleanToVisibilityConverter
to bind Visibility
directly.
<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>
Upvotes: 1