c# - 在 TreeView 中禁用选择

标签 c# wpf xaml treeview

我看到有一些方法可以在 ListView 中禁用选择,但我还没有看到 TreeViewGrid 的任何内容。

我的表单很基本,如下所示:

View of form

问题是有人可以点击任何一个标签,然后突然看起来像这样:

View of form after selection

如何禁用此行为?

<TreeView Focusable="False">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="Focusable" Value="False"/>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeViewItem Focusable="False">
        <TreeViewItem.Header>Group Header</TreeViewItem.Header>
        <TreeViewItem.IsExpanded>true</TreeViewItem.IsExpanded>
        <Grid Focusable="False">
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <Label Content="Message ID">
                <Grid.Row>0</Grid.Row>
                <Grid.Column>0</Grid.Column>
            </Label>
            <TextBox Text="{Binding Path=GroupHeader.MessageId}" HorizontalAlignment="Stretch">
                <Grid.Column>1</Grid.Column>
                <Grid.Row>0</Grid.Row>
            </TextBox>
            <Label Content="Creation Date">
                <Grid.Row>1</Grid.Row>
                <Grid.Column>0</Grid.Column>
            </Label>
            <DatePicker SelectedDate="{Binding Path=GroupHeader.CreationDateTime}">
                <Grid.Row>1</Grid.Row>
                <Grid.Column>1</Grid.Column>
            </DatePicker>
            <Label Content="Instructing Agent">
                <Grid.Row>2</Grid.Row>
                <Grid.Column>0</Grid.Column>
            </Label>
            <TextBox Text="{Binding Path=GroupHeader.InstructingAgent}">
                <Grid.Row>2</Grid.Row>
                <Grid.Column>1</Grid.Column>
            </TextBox>
            <Label Content="Instructed Agent">
                <Grid.Row>3</Grid.Row>
                <Grid.Column>0</Grid.Column>
            </Label>
            <TextBox Text="{Binding Path=GroupHeader.InstructedAgent}">
                <Grid.Row>3</Grid.Row>
                <Grid.Column>1</Grid.Column>
            </TextBox>
        </Grid>
    </TreeViewItem>
   <TreeViewItem>
        ...
   </TreeViewItem>
</TreeView>

使用 TreeView.ItemContainerStyle 只是在实际项目标题上禁用它,而不是它看起来的内容。

更新:我已经尝试了 Chris W 的评论以及有关设置控制模板的建议,使用以下内容:

<Style x:Key="StretchingTreeViewItemStyle1" TargetType="{x:Type local:StretchingTreeViewItem}">
  <Setter Property="Background" Value="Transparent"/>
  <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
  <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
  <Setter Property="Padding" Value="1,0,0,0"/>
  <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
  <Setter Property="FocusVisualStyle">
    <Setter.Value>
      <Style>
        <Setter Property="Control.Template">
          <Setter.Value>
            <ControlTemplate>
              <Rectangle/>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </Setter.Value>
  </Setter>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type local:StretchingTreeViewItem}">
        <Grid>
          <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="19" Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
          </Grid.RowDefinitions>
          <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}">
            <ToggleButton.Style>
              <Style TargetType="{x:Type ToggleButton}">
                <Setter Property="Focusable" Value="False"/>
                <Setter Property="Width" Value="16"/>
                <Setter Property="Height" Value="16"/>
                <Setter Property="Template">
                  <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ToggleButton}">
                      <Border Background="Transparent" Height="16" Padding="5" Width="16">
                        <Path x:Name="ExpandPath" Data="M0,0 L0,6 L6,0 z" Fill="Transparent" Stroke="#FF989898">
                          <Path.RenderTransform>
                            <RotateTransform Angle="135" CenterY="3" CenterX="3"/>
                          </Path.RenderTransform>
                        </Path>
                      </Border>
                      <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="True">
                          <Setter Property="RenderTransform" TargetName="ExpandPath">
                            <Setter.Value>
                              <RotateTransform Angle="180" CenterY="3" CenterX="3"/>
                            </Setter.Value>
                          </Setter>
                          <Setter Property="Fill" TargetName="ExpandPath" Value="#FF595959"/>
                          <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF262626"/>
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="True">
                          <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF1BBBFA"/>
                          <Setter Property="Fill" TargetName="ExpandPath" Value="Transparent"/>
                        </Trigger>
                        <MultiTrigger>
                          <MultiTrigger.Conditions>
                            <Condition Property="IsMouseOver" Value="True"/>
                            <Condition Property="IsChecked" Value="True"/>
                          </MultiTrigger.Conditions>
                          <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF262626"/>
                          <Setter Property="Fill" TargetName="ExpandPath" Value="#FF595959"/>
                        </MultiTrigger>
                      </ControlTemplate.Triggers>
                    </ControlTemplate>
                  </Setter.Value>
                </Setter>
              </Style>
            </ToggleButton.Style>
          </ToggleButton>
          <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
            <ContentPresenter Focusable="False" x:Name="PART_Header" ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
          </Border>
          <ItemsPresenter Focusable="False" x:Name="ItemsHost" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1"/>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsExpanded" Value="False">
            <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
          </Trigger>
          <Trigger Property="HasItems" Value="False">
            <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
          </Trigger>
          <!--<Trigger Property="IsSelected" Value="True">
            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
          </Trigger>-->
          <!--<MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="IsSelected" Value="True"/>
              <Condition Property="IsSelectionActive" Value="False"/>
            </MultiTrigger.Conditions>
            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
          </MultiTrigger>-->
          <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Style.Triggers>
    <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="True">
      <Setter Property="ItemsPanel">
        <Setter.Value>
          <ItemsPanelTemplate>
            <VirtualizingStackPanel IsItemsHost="True"/>
          </ItemsPanelTemplate>
        </Setter.Value>
      </Setter>
    </Trigger>
  </Style.Triggers>
</Style>

结果是 TreeViewItem 上的文本本身不再可选择/未突出显示,但其中的内容仍然可以。

我已经尝试将所有我能想到的都设置为 Focusable="False" 但这也不起作用,所以我开始认为它与专注于某个项目无关.特别是因为如果您嵌套了 TreeViews,您可以同时选择内部和外部项。

最佳答案

我相信您已经注意到了,禁用选择特定 TreeViewItem 的方法是将其 Focusable 属性设置为 false。您使用 TreeView.ItemContainerStyle 取得了部分成功 - 这导致禁用选择第一级项目,但不是嵌套项目。这是由 TreeView 的设计方式引起的。

TreeView 基本上是一个 ItemsControlTreeViewItem 容器包装它的项目。这里的关键是它只包含它的 child (第一级项目),所以 TreeView.ItemContainerStyle 只应用于它的 child - 因此你的结果。

TreeViewItem 也派生自 ItemsControl,并且它包含它自己的子项,因此所有二级项都是其一级父项的子项(和项)等. TreeViewItem 还用 TreeViewItem 容器包装它的所有子项-在您的情况下, TreeViewItem 内的 Grid 称为“Group Header"用 TreeViewItem 包裹,您可以使用 Snoop 等工具进行确认.因此,为了禁用对二级项目的选择,您应该设置所有相应一级父项目的 TreeViewItem.ItemContainerStyle,就像对 TreeView 所做的那样。

当然,在处理多级树时,为所有项目显式设置 TreeViewItem.ItemConainerStyle 可能会出现问题,因此您可以利用隐式样式:

<TreeView>
    <TreeView.Resources>
        <Style TargetType="TreeViewItem">
            <Setter Property="Focusable" Value="False" />
        </Style>
    </TreeView.Resources>
    ...
</TreeView>

现在这种样式将应用于 TreeView 中的所有 TreeViewItem 控件(w.r.t. 隐式样式规则) - 重要的是,不仅仅是第一级控件。这应该会给您带来预期的结果。

关于c# - 在 TreeView 中禁用选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35509054/

相关文章:

c# - Razor View 引擎何时将 IActionResult 转换为 HTML?

c# - 使用 Serilog for .NET 将日志写入 Excel 文件

wpf - 导入具有特定参数的类

c# - 使用 XAML 的 Setter 上的“#33333 3' is not a valid value for the ' System.Windows.Controls.Border.BorderBrush”属性

c# - SQLiteFunction简单不工作

c# - 在 WinRT 中暂停应用程序后恢复 CaptureElement

c# - 随机程序集引用失败 ("Are you missing a using directive or an assembly reference?")

wpf - 有两个控件设置另一个控件的可见性

c# - 禁止在 ListView 中选择项目

xaml - 如何将页面中的条目与 ViewModel 绑定(bind)