如何在WPF TreeView中突出显示整行

时间:2014-12-10 10:34:35

标签: wpf treeview controltemplate treeviewitem

我想调整默认的WPF TreeView / TreeViewItem模板,以便整个行可以突出显示,如图所示:

enter image description here

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

代码流中有一个答案似乎有用,但是它添加了额外的C#代码,或者不需要额外的代码但不能完美运行。

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

非常感谢!

---- ---- EDIT

@Nick,在使用您的模板后,它显示如下,

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

第二,它强调了包括孩子在内的额外区域。

enter image description here

4 个答案:

答案 0 :(得分:2)

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

我还编辑了ControlTemplate,就像Tim在评论中描述的那样。我将“Expander”切换按钮和“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要求的方式,因为“children”行的突出显示以缩进开头。但它确实正确地突出显示每一行而不包括子项。

答案 1 :(得分:1)

您需要修改ItemContainerStyle的模板。如果右键单击Blend中的TreeView并选择&#34;编辑其他模板&#34; - &GT; &#34;编辑生成的项目容器&#34; - &GT; &#34;编辑副本&#34;。它将在您的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属性激活的触发器。您可以看到它修改名为&#34; Bd&#34;的元素的Background属性。这是文本的边界。如果要将该选择扩展到整行,则需要:

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

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

  3. 修改下面的MultiTrigger的Setter也可以定位网格而不是边框​​控件。这将确保选中整行时突出显示,但窗口未对焦。

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

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

答案 2 :(得分:1)

您找到解决方案了吗? 如果没有,那么只需更改第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>

这对我有用

答案 3 :(得分:0)

不是最好的解决方案,但我想我还是提到了它。只需覆盖一个白色网格即可完成工作。 使用以下内容覆盖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>