Install IsExpanded in WPF TreeViewItem from DataTrigger

I am trying to set the IsExpanded property for my TreeView elements using a conditional template in XAML :

 <DataTrigger Binding="{Binding MyStatus}" Value="Opened"> <Setter TargetName="MyTextBlock" Property="Foreground" Value="Green"/> <Setter Property="TreeViewItem.IsExpanded" Value="True" /> </DataTrigger> 

When I set the MyStatus property from C # code, the colors change (this is how DataTrigger works), but the nodes do not expand.

 _myItems[0].MyStatus = MyStatus.Opened; 

How to set TreeViewItem.IsExpanded property from DataTrigger ?

When I launch the application, the colors are set correctly, but the green node does not expand:

Screenshot just after starting the application

And after changing the value of _myItems[0].MyStatus and _myItems[1].MyStatus colors change accordingly, but the green node is still not expanding.

Screenshot after clicking the Button1

Full Code (XAML)

The full code is a bit long, but its 90% pattern.

 <Window x:Class="WpfApplication6.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="150" Width="250"> <DockPanel> <DockPanel.Resources> <HierarchicalDataTemplate ItemsSource="{Binding SubItems}" x:Key="MyTemplate"> <StackPanel Orientation="Horizontal"> <!-- ... --> <TextBlock x:Name="MyTextBlock" Foreground="Green" Text="{Binding Name}" /> </StackPanel> <HierarchicalDataTemplate.Triggers> <DataTrigger Binding="{Binding MyStatus}" Value="Closed"> <Setter TargetName="MyTextBlock" Property="Foreground" Value="Red"/> <Setter Property="TreeViewItem.IsExpanded" Value="False" /> </DataTrigger> <DataTrigger Binding="{Binding MyStatus}" Value="Opened"> <Setter TargetName="MyTextBlock" Property="Foreground" Value="Green"/> <Setter Property="TreeViewItem.IsExpanded" Value="True" /> </DataTrigger> </HierarchicalDataTemplate.Triggers> </HierarchicalDataTemplate> </DockPanel.Resources> <Button Name="button1" Click="button1_Click" DockPanel.Dock="Top" Content="Button1"/> <TreeView Name="treeView1" ItemsSource="{Binding MyItems}" ItemTemplate="{StaticResource MyTemplate}"/> </DockPanel> </Window> 

Full code (C #)

 using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows; namespace WpfApplication6 { public partial class MainWindow : Window { private ObservableCollection<MyItemCollection> _myItems; public MainWindow() { InitializeComponent(); _myItems = new ObservableCollection<MyItemCollection> { new MyItemCollection { Name = "Parent1", MyStatus = MyStatus.Closed, SubItems = { new MyItemCollection { Name = "Child1" } } }, new MyItemCollection { Name = "Parent2", MyStatus = MyStatus.Opened, SubItems = { new MyItemCollection { Name = "Child2" } } } }; DataContext = new { MyItems = _myItems }; } private void button1_Click(object sender, RoutedEventArgs e) { _myItems[0].MyStatus = MyStatus.Opened; _myItems[1].MyStatus = MyStatus.Closed; } } public enum MyStatus { Closed, Opened } public class MyItemCollection : INotifyPropertyChanged { public MyItemCollection() { SubItems = new ObservableCollection<MyItemCollection>(); _myStatus = MyStatus.Closed; } public string Name { get; set; } public ObservableCollection<MyItemCollection> SubItems { get; set; } private MyStatus _myStatus; public MyStatus MyStatus { get { return _myStatus; } set { _myStatus = value; NotifyPropertyChanged("MyStatus"); } } public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } } 
+7
c # wpf xaml treeview treeviewitem
source share
2 answers

There are a few things here. First, you set the TreeViewItem.IsSelected property to HierarchicalDataTemplate . This will not work. Instead, you need to set ItemContainerStyle in TreeView :

 <TreeView> <TreeView.ItemContainerStyle> <Style TargetType="{x:Type TreeViewItem}"> <!-- put logic for handling expansion here --> </Style> </TreeView.ItemContainerStyle> </TreeView> 

However, you cannot just put Trigger here. Due to DependencyProperty priority values , if your user clicks on nodes to expand or collapse them, triggers will not be # 1 on the priority list (i.e. local value). Therefore, it is best to create a new IValueConverter to convert from MyStatus to bool . And then set the TwoWay binding in Setter to Style :

 <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="IsExpanded" Value="{Binding MyStatus, Converter={StaticResource statusToBool}}" /> </Style> 

And your converter:

 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return ((MyStatus)value) == MyStatus.Opened; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return ((bool)value) ? MyStatus.Opened : MyStatus.Closed; } 
+9
source share

I needed to do something similar, and I solved it like this:

 <TreeView ItemsSource="{Binding source}" SnapsToDevicePixels="{Binding Path=myStatusToBool}" > <TreeView.ItemContainerStyle> <Style> <Setter Property="TreeViewItem.IsExpanded" Value="False" /> <Style.Triggers> <DataTrigger Binding="{Binding Path=SnapsToDevicePixels,RelativeSource={RelativeSource AncestorType=TreeView}}" Value="True"> <Setter Property="TreeViewItem.IsExpanded" Value="True" /> </DataTrigger> </Style.Triggers> </Style> </TreeView.ItemContainerStyle> <TreeView.Resources> ..... ..... </TreeView.Resources> </TreeView> 
+1
source share

All Articles