【问题标题】:Disable focusability of certain entries in TreeView禁用 TreeView 中某些条目的可聚焦性
【发布时间】:2016-10-11 16:51:36
【问题描述】:

我有一个充满不同类型项目的 TreeView。这些项目可以是Node 类型(那么他们可能有孩子)或Entry 类型(那么他们没有孩子)。为此,我将我的 TreeView 绑定到我的 ViewModel 属性AllNodesAndEntries,这是一个ObservableCollection<object>。对于NodeEntry 的不同外观,我定义了两个DataTemplate。代码如下:

<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 属性 MyProptrue),我想让 Entry 元素无法聚焦。

所以我在 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 后选择条目。 我做错了什么?如何让它发挥作用?

我确实在MyProp 的setter 中放置了NotifyPropertyChanged(nameof(MyProp));,因此对MyProp 的更改将报告给视图。

【问题讨论】:

    标签: c# wpf triggers treeview


    【解决方案1】:

    使用IsNodeConverter 你已经posted, 你可以实现一个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>
    

    【讨论】:

      【解决方案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>
      

      【讨论】:

      • 正确答案。 TextBlock 无法正常选中。当你正常点击 TextBlock 时,什么也没有发生。
      • 对我来说它也不起作用:(我仍然可以选择所有内容。而且我认为即使它确实有效,它也会使所有 TreeViewItems 都无法选择,对吧?我只想要 @ 类型的 TreeViewItems 987654322@ 不可选择。
      • 我认为它不起作用,因为触发器的DataContext是TreeViewItem中的Entry/Node,而不是ViewModel。但是MyProp是在ViewModel中定义的,所以绑定是无效的。但是如何更改触发器/样式的 DataContext?看来他们没有 DataContext 属性...
      • @Kjara 看看 ItemContainerStyleSelector 并根据项目类型使用不同的样式。
      【解决方案3】:

      没问题,只需要在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

      【讨论】:

        猜你喜欢
        • 2016-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多