禁用TreeView

时间:2016-10-07 14:36:34

标签: c# wpf triggers treeview

我有一个填充了不同类型项目的TreeView。这些项目可以是Node类型(然后他们可能有孩子)或类型Entry(然后他们没有孩子)。为此,我将TreeView绑定到我的ViewModel属性AllNodesAndEntries,这是一个ObservableCollection<object>。对于NodeEntry的不同外观,我定义了两个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属性EntryMyProp),我想让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的更改将报告给视图。

3 个答案:

答案 0 :(得分:5)

使用IsNodeConverterposted, 您可以实现只在满足两个条件时才会触发的MultiDataTrigger

  • ViewModel MyProp = true
  • 类型Entry
  • 的TreeViewItem

<强> 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