【问题标题】:How to highlight entire row in WPF TreeView如何在 WPF TreeView 中突出显示整行
【发布时间】:2014-12-10 10:34:34
【问题描述】:

我想适配默认的WPF TreeView/TreeViewItem模板,这样整行就可以高亮,如图:

但是,我尝试了几个谷歌搜索的模板,但没有一个能真正产生效果,一些错误的答案甚至被标记为正确......

在代码流中有一个答案似乎可以工作,但它添加了额外的 C# 代码,或者不需要额外的代码但不能完美地工作。

我不想添加额外的 C# 代码,而只想更改默认模板。 有人有什么好主意吗?

非常感谢!

----编辑----

@Nick,使用你的模板后,显示如下,

首先,它没有突出显示“整个”行,“整个”是指树的最宽宽度。

其次,它突出了包括孩子在内的额外区域。

【问题讨论】:

  • 1) 覆盖默认模板 2) 使用 Snoop 找到您需要突出显示的确切面板 3) 在 Trigger 的“OnSelected”属性中为该面板添加背景颜色。
  • @Kumar 这个问题其实比我们大家最初想象的要难,TreeViewItem 使用了递归结构,这让它和其他控件有很大的不同
  • 是的,你是对的;让我进一步检查并回复您。
  • 它突出显示了子项,因为触发器设置器的目标是包含项目及其子项的 。您将要使用 Grid.Column="0" Grid.ColumnSpan="3" 添加一个空矩形,然后使用这些 Setter 来更改其背景。这不会解决扩展器左侧空白的问题,但可以解决突出显示子项的问题。
  • 这是我找到的唯一解决方案,而且效果很好:stackoverflow.com/a/37784413

标签: wpf treeview controltemplate treeviewitem


【解决方案1】:

我最近不得不做一些类似的事情,虽然这个问题已经很老了,但我认为像我一样偶然发现这个页面的其他人可能能够从我的解决方案中得到一些东西。

我还编辑了 ControlTemplate,就像 Tim 在 cmets 中描述的那样。我将“扩展器”切换按钮和“Bd”边框控件分组到一个网格中,该网格横跨 TreeView 的整个宽度。然后在 IsSelected 触发器下,我将高亮设置为新创建的网格而不是边框​​。

这是 TreeView 的 ControlTemplate 以及我的编辑:

<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition MinWidth="19" Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <!-- created ItemRowGrid to contain both togglebutton and border -->
    <Grid x:Name="ItemRowGrid" Grid.ColumnSpan="3" Margin="1.5,0,0,0">
        <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}" HorizontalAlignment="Left" d:LayoutOverrides="Width, LeftMargin, RightMargin"/>
        <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true" Margin="17.5,0,-17.5,0">
            <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
        </Border>
    </Grid>
    <ItemsPresenter 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="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
        <!-- setting highlight target to created ItemRowGrid instead of border -->
        <Setter Property="Background" TargetName="ItemRowGrid" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
    </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>

这不完全是 OP 要求的方式,因为“子”行的突出显示以缩进开头。但它确实正确突出了每一行而不包括子项。

【讨论】:

    【解决方案2】:

    您需要修改 ItemContainerStyle 的模板。如果您在 Blend 中右键单击 TreeView 并选择“编辑其他模板”->“编辑生成的项目容器”->“编辑副本”。它将在您的 xaml 中创建默认模板的副本。 然后你需要在那里找到以下代码:

          <ControlTemplate TargetType="{x:Type TreeViewItem}">
            <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}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
              <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
              </Border>
              <ItemsPresenter 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.ControlBrushKey}}"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
              </MultiTrigger>
              <Trigger Property="IsEnabled" Value="false">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
              </Trigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
    

    查看由 IsSelected 属性激活的触发器。您可以看到它修改了名为“Bd”的元素的背景属性。那是文本周围的边框。如果您想将该选择扩展到整行,您需要:

    1. 为上述代码示例第二行的网格命名。

    2. 修改该 IsSelected 属性触发器的 Setter 以定位网格而不是边框​​控件。这将确保在您单击整行时突出显示它。

    3. 修改下面的 MultiTrigger 的 Setter,使其也以网格而不是边框​​控件为目标。这将确保整行在被选中时突出显示,但窗口不在焦点上。

    以下是将选择应用于整行的修改版本:

          <ControlTemplate TargetType="{x:Type TreeViewItem}">
            <Grid x:Name="itemGrid">
              <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}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
              <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
              </Border>
              <ItemsPresenter 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="itemGrid" 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="itemGrid" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
              </MultiTrigger>
              <Trigger Property="IsEnabled" Value="false">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
              </Trigger>
            </ControlTemplate.Triggers>
          </ControlTemplate>
    

    【讨论】:

    • 我试过了,没用,1.它不适用于整行2.它突出显示了额外的区域,请参阅我的帖子编辑。
    • BTW,这个问题其实比我们大家最初想象的要难,TreeViewItem采用了递归结构,这使得它和其他控件有很大的不同。
    【解决方案3】:

    您找到解决方案了吗? 如果不是,那么只需更改第 1 列和第 2 列的 ColumnDefination,如下所示

    <ControlTemplate TargetType="{x:Type TreeViewItem}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition MinWidth="19" Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
    

    完整代码:

    <ControlTemplate TargetType="{x:Type TreeViewItem}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition MinWidth="19" Width="Auto"/>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
                            <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                                <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </Border>
                            <ItemsPresenter 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>
    

    这对我有用

    【讨论】:

      【解决方案4】:

      不是最好的解决方案,但我想我还是提到了它。简单地覆盖一个白色网格就可以了。 用以下内容覆盖 ItemsPresenter:

      <Grid Grid.Row="1"                                  
            Grid.Column="0"                                  
            Grid.ColumnSpan="3"
            >
              <Grid.ColumnDefinitions>
              <ColumnDefinition MinWidth="19" Width="Auto"/>
              <ColumnDefinition Width="Auto"/>
              <ColumnDefinition Width="*"/>
          </Grid.ColumnDefinitions>
          <Grid.Style>
              <Style TargetType="Grid">
                  <Setter  Property="Background" Value="White"/>
              </Style>
          </Grid.Style>
          <ItemsPresenter x:Name="ItemsHost" Grid.Column="1" Grid.ColumnSpan="2"/>
      </Grid>
      

      【讨论】:

        猜你喜欢
        • 2012-05-13
        • 2010-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多