Reputation: 2902
I have a TreeView that is filled with different types of items. The items can either be of type Node
(then they may have children) or of type Entry
(then they don't have children). For that, I bound my TreeView to my ViewModel property AllNodesAndEntries
which is an ObservableCollection<object>
. For different looks of Node
and Entry
I defined two DataTemplates. Here is the code:
<TreeView ItemsSource="{Binding AllNodesAndEntries}">
<TreeView.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding Children}"
DataType="{x:Type local:Node}">
<TextBlock Text="{Binding Name}"
Background="LightBlue"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:Entry}">
<TextBlock Text="{Binding Name}"
Background="LightSalmon"/>
</DataTemplate>
</TreeView.Resources>
</TreeView>
Now I want to make the Entry
elements unfocusable if a certain condition is met (that is, if my ViewModel property MyProp
is true
).
So I added a trigger into the DataTemplate for Entry
like this:
<DataTemplate DataType="{x:Type local:Entry}">
<TextBlock Text="{Binding Name}"
Background="LightSalmon"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding MyProp}" Value="True">
<Setter Property="Focusable" Value="False"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
But it does not work, I can still select entries after MyProp
was set to true
. What am I doing wrong? How do I make it work?
I did put a NotifyPropertyChanged(nameof(MyProp));
in the setter of MyProp
, so changes to MyProp
will be reported to the View.
Upvotes: 5
Views: 735
Reputation: 1649
It is no problem, you just need to set the Focusable
property at the TreeViewItem. Just add the following to your TreeView.Resources
:
<TreeView.Resources>
<DataTemplate DataType="{x:Type local:Entry}">
<TextBlock Text="{Binding Name}" Background="LightSalmon"/>
</DataTemplate>
<Style TargetType="TreeViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding MyProp}" Value="True">
<Setter Property="Focusable" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.Resources>
This style now occurs at all your TreeViewItems. If you like to prevent your Nodes
from this style you could do it in code behind or just bind your item object
and use a Converter
.
Upvotes: 0
Reputation: 11211
Using the IsNodeConverter
you've posted,
you can implement a MultiDataTrigger
that only fires when both conditions are fulfilled:
MyProp
= trueEntry
XAML
<Window.Resources>
<local:IsNodeConverter x:Key="IsNodeConverter"/>
</Window.Resources>
...
<TreeView ItemsSource="{Binding AllNodesAndEntries}">
<TreeView.Resources>
...
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding DataContext.MyProp, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
Value="True"/>
<Condition Binding="{Binding Converter={StaticResource IsNodeConverter}}"
Value="False"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Focusable" Value="False"></Setter>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
Upvotes: 5
Reputation: 1141
The problem is you set the Focusable Property to the DataTemplate which doesn't affect the selection of the TreeViewItem.
Instead you should set it on the TreeViewItem like this:
<TreeView ItemsSource="{Binding Items}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding MyProp}"
Value="True">
<Setter Property="Focusable"
Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
Upvotes: 2