我有一个填充了不同类型项目的TreeView。这些项目可以是Node
类型(然后他们可能有孩子)或类型Entry
(然后他们没有孩子)。为此,我将TreeView绑定到我的ViewModel属性AllNodesAndEntries
,这是一个ObservableCollection<object>
。对于Node
和Entry
的不同外观,我定义了两个DataTemplates。这是代码:
<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>
现在,如果满足某个条件(即,如果我的ViewModel属性Entry
为MyProp
),我想让true
元素无法调整。
所以我在Entry
的DataTemplate中添加了一个触发器,如下所示:
<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>
但它不起作用,我仍然可以在MyProp
设置为true
后选择条目。 我做错了什么?我该如何使其发挥作用?
我确实在NotifyPropertyChanged(nameof(MyProp));
的设置器中添加了MyProp
,因此对MyProp
的更改将报告给视图。
答案 0 :(得分:5)
使用IsNodeConverter
你posted,
您可以实现只在满足两个条件时才会触发的MultiDataTrigger
:
MyProp
= true Entry
<强> 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>
答案 1 :(得分:2)
问题是您将Focusable属性设置为DataTemplate,它不会影响TreeViewItem的选择。
相反,你应该在TreeViewItem上设置它:
<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>
答案 2 :(得分:0)
没问题,你只需要在TreeViewItem上设置Focusable
属性。只需将以下内容添加到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>
此样式现在出现在所有TreeViewItems上。如果您希望阻止Nodes
使用此样式,则可以在后面的代码中执行此操作,或者仅绑定项object
并使用Converter
。