Changing TreeViewItem Template When IsSelected and Two Types Selected in TreeView

In my TreeView, I use two differnt classes for binding. For example, I have a group that can have a child group and can contain elements. Sample code for this class:

using System.Collections.Generic; using System.Collections.ObjectModel; namespace WpfApplication1 { public class Group { public Group(string name) { Name = name; items = new ObservableCollection<Item>(); groups = new ObservableCollection<Group>(); } public string Name { get; set; } private ObservableCollection<Item> items; private ObservableCollection<Group> groups; public ObservableCollection<Item> Items { get { return items; } } public ObservableCollection<Group> Groups { get { return groups; } } public IEnumerable<object> AllItems { get { foreach (var group in groups) { yield return group; } foreach (var item in items) { yield return item; } } } } public class Item { public Item(string name) { ItemName = name; } public string ItemName { get; set; } } } 

To associate it with a TreeView, I use the following template

 <Grid> <TreeView Name="treeView"> <TreeView.Resources> <HierarchicalDataTemplate DataType="{x:Type WpfApplication1:Group}" ItemsSource="{Binding AllItems}"> <TextBlock Text="{Binding Name}"/> </HierarchicalDataTemplate> <DataTemplate DataType="{x:Type WpfApplication1:Item}"> <TextBlock Text="{Binding ItemName}" FontStyle="Italic"/> </DataTemplate> </TreeView.Resources> </TreeView> </Grid> 

It is easy.

The problem is that I need to change the ItemTemplate when selecting. And I need to change only when the Item class is selected.

I can do this if only one class is used for binding. It is also easy to use style and trigger, for example:

 <TreeView Name="treeView1" Grid.Column="1"> <TreeView.Resources> <HierarchicalDataTemplate DataType="{x:Type WpfApplication1:Group}" ItemsSource="{Binding AllItems}" x:Key="groupTemplate"> <TextBlock Text="{Binding Name}"/> </HierarchicalDataTemplate> <HierarchicalDataTemplate DataType="{x:Type WpfApplication1:Group}" ItemsSource="{Binding AllItems}" x:Key="selectedGroupTemplate"> <TextBlock Text="{Binding Name}" FontStyle="Italic" FontWeight="Bold" FontSize="14"/> </HierarchicalDataTemplate> </TreeView.Resources> <TreeView.ItemContainerStyle> <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="HeaderTemplate" Value="{StaticResource groupTemplate}"/> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="HeaderTemplate" Value="{StaticResource selectedGroupTemplate}"/> </Trigger> </Style.Triggers> </Style> </TreeView.ItemContainerStyle> </TreeView> 

But I have a problem with multiclass binding.

How can I change the SelectedItem template and then use multiclass binding? Any ideas?

My code is for the sample:

 using System.Collections.ObjectModel; using System.Windows; namespace WpfApplication1 { /// <summary> /// Interaction logic for Window2.xaml /// </summary> public partial class Window2 : Window { private ObservableCollection<Group> _groups; public ObservableCollection<Group> Groups { get { return _groups; } } public Window2() { InitializeComponent(); InitGroups(); treeView.ItemsSource = _groups; treeView1.ItemsSource = _groups; } private void InitGroups() { _groups = new ObservableCollection<Group>(); Group group1 = new Group("Group1"); group1.Groups.Add(new Group("Group1.1")); group1.Groups.Add(new Group("Group1.2")); group1.Groups.Add(new Group("Group1.3")); group1.Items.Add(new Item("Item1.1")); group1.Items.Add(new Item("Item1.2")); group1.Groups[1].Items.Add(new Item("Item1.2.1")); group1.Groups[1].Items.Add(new Item("Item1.2.2")); _groups.Add(group1); Group group2 = new Group("Group2"); group2.Groups.Add(new Group("Group2.1")); group2.Groups.Add(new Group("Group2.2")); group2.Items.Add(new Item("Item2.1")); group2.Groups[0].Items.Add(new Item("Item2.1.1")); group2.Groups[0].Items.Add(new Item("Item2.1.1")); _groups.Add(group2); } } } 

Result Result

Now I am thinking of using TreeView.HeaderTemplateSelector, but there may be a way to use only xaml.

Thanks.

+4
source share
1 answer

There are several ways to achieve the desired result. If you are sure that your DataTemplate will be used only in TreeViewItem objects, then the easiest way is to simply bind it to the TreeViewItem.IsSelected property, and then respond to the change in the DataTemplate :

  <DataTemplate DataType="{x:Type WpfApplication1:Item}"> <TextBlock Text="{Binding ItemName}"> <TextBlock.Style> <Style> <Style.Triggers> <DataTrigger Binding="{Binding IsSelected, RelativeSource= {RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, FallbackValue=False}" Value="True"> <Setter Property="TextBlock.FontStyle" Value="Italic" /> </DataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock> </DataTemplate> 
+4
source

Source: https://habr.com/ru/post/1394537/


All Articles