在 WPF 中突出显示整个 TreeViewItem 行 [英] Highlight whole TreeViewItem line in WPF

查看:53
本文介绍了在 WPF 中突出显示整个 TreeViewItem 行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我设置 TreeViewItem Background,它只会突出显示标题.如何突出显示整条线?

我发现了一篇几乎解决问题的帖子

这个需要更多的工作.我确信有很多方法可以做到这一点,但这种方法使用长度转换器和 TreeViewItem 扩展方法来获取深度.这两者都与 TreeViewItem 可视化树紧密耦合,因此如果您开始弄乱模板,那么您可能会遇到麻烦.同样,这里是重要的部分,下面是完整的代码.

<ControlTemplate.Resources><local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter"/></ControlTemplate.Resources><堆栈面板><边框名称="Bd"背景="{模板绑定背景}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"Padding="{TemplateBinding Padding}"><Grid Margin="{Binding Converter={StaticResource lengthConverter},RelativeSource={RelativeSource TemplatedParent}}"><Grid.ColumnDefinitions><ColumnDefinition Width="19"/><列定义/></Grid.ColumnDefinitions><ToggleButton x:Name="Expander"Style="{StaticResource ExpandCollapseToggleStyle}"IsChecked="{绑定路径=IsExpanded,RelativeSource={RelativeSource TemplatedParent}}"ClickMode="按下"/><ContentPresenter x:Name="PART_Header"Grid.Column="1"内容来源 =标题"Horizo​​ntalAlignment="{TemplateBinding Horizo​​ntalContentAlignment}"/></网格></边框><ItemsPresenter x:Name="ItemsHost"/></StackPanel><!-- 触发器--></控制模板>

TreeViewDepth 扩展

公共静态类 TreeViewItemExtensions{public static int GetDepth(此 TreeViewItem 项){TreeViewItem 父项;while ((parent = GetParent(item)) != null){返回 GetDepth(parent) + 1;}返回0;}私有静态 TreeViewItem GetParent(TreeViewItem item){var parent = VisualTreeHelper.GetParent(item);while (!(parent is TreeViewItem || parent is TreeView)){parent = VisualTreeHelper.GetParent(parent);}将父项作为 TreeViewItem 返回;}}

LeftMarginMultiplierConverter

public class LeftMarginMultiplierConverter : IValueConverter{公共双长度{得到;放;}公共对象转换(对象值,类型目标类型,对象参数,文化信息文化){var item = value as TreeViewItem;如果(项目==空)返回新的厚度(0);返回新厚度(长度 * item.GetDepth(), 0, 0, 0);}公共对象 ConvertBack(对象值,类型目标类型,对象参数,CultureInfo 文化){抛出新的 System.NotImplementedException();}}

控制

<TreeViewItem Header="test2"/><TreeViewItem Header="test2"><TreeViewItem Header="子测试"><TreeViewItem Header="sub test1-1"/><TreeViewItem Header="sub test1-2"/></TreeViewItem><TreeViewItem Header="sub test2"/></TreeViewItem><TreeViewItem Header="test3"/></树视图>

完整的 TreeViewItem 样式

<!--================================================================树视图项====================================================================--><Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton"><Setter Property="Focusable" Value="False"/><Setter 属性="模板"><Setter.Value><ControlTemplate TargetType="ToggleButton"><网格宽度=15"高度=13"背景=透明"><Path x:Name="ExpandPath"水平对齐=左"垂直对齐=中心"边距="1,1,1,1"Fill="{StaticResource GlyphBrush}"数据=M 4 0 L 8 4 L 4 8 Z"/></网格><ControlTemplate.Triggers><触发器属性="IsChecked"值="真"><Setter 属性="数据"目标名称=扩展路径"值="M 0 4 L 8 4 L 4 8 Z"/></触发器></ControlTemplate.Triggers></控制模板></Setter.Value></Setter></风格><Style x:Key="TreeViewItemFocusVisual"><Setter Property="Control.Template"><Setter.Value><控制模板><边框><矩形边距="0,0,0,0"StrokeThickness="5"中风=黑色"StrokeDashArray="1 2"不透明度=0"/></边框></控制模板></Setter.Value></Setter></风格><Style x:Key="{x:Type TreeViewItem}"TargetType="{x:Type TreeViewItem}"><Setter 属性="背景"值="透明"/><Setter 属性="Horizo​​ntalContentAlignment"值="{绑定路径=水平内容对齐,RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/><Setter Property="VerticalContentAlignment"值="{绑定路径=垂直内容对齐,RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/><Setter 属性="填充"值="1,0,0,0"/><Setter 属性="前景"Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/><Setter 属性="FocusVisualStyle"Value="{StaticResource TreeViewItemFocusVisual}"/><Setter 属性="模板"><Setter.Value><ControlTemplate TargetType="{x:Type TreeViewItem}"><ControlTemplate.Resources><local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter"/></ControlTemplate.Resources><堆栈面板><边框名称="Bd"背景="{模板绑定背景}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"Padding="{TemplateBinding Padding}"><Grid Margin="{Binding Converter={StaticResource lengthConverter},RelativeSource={RelativeSource TemplatedParent}}"><Grid.ColumnDefinitions><ColumnDefinition Width="19"/><列定义/></Grid.ColumnDefinitions><ToggleButton x:Name="Expander"Style="{StaticResource ExpandCollapseToggleStyle}"IsChecked="{绑定路径=IsExpanded,RelativeSource={RelativeSource TemplatedParent}}"ClickMode="按下"/><ContentPresenter x:Name="PART_Header"Grid.Column="1"内容来源 =标题"Horizo​​ntalAlignment="{TemplateBinding Horizo​​ntalContentAlignment}"/></网格></边框><ItemsPresenter x:Name="ItemsHost"/></StackPanel><ControlTemplate.Triggers><触发属性="IsExpanded"值="假"><Setter TargetName="ItemsHost"属性="可见性"值=折叠"/></触发器><触发器属性="HasItems"值="假"><Setter TargetName="扩展器"属性="可见性"值="隐藏"/></触发器><多重触发><MultiTrigger.Conditions><条件属性="HasHeader"值="假"/><条件属性="宽度"值="自动"/></MultiTrigger.Conditions><Setter TargetName="PART_Header"属性=最小宽度"值="75"/></多触发器><多重触发><MultiTrigger.Conditions><条件属性="HasHeader"值="假"/><条件属性="高度"值="自动"/></MultiTrigger.Conditions><Setter TargetName="PART_Header"属性=最小高度"值="19"/></多触发器><触发器属性="IsSelected"值=真"><Setter TargetName="Bd"属性=背景"Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/><Setter 属性="前景"Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/></触发器><多重触发><MultiTrigger.Conditions><条件属性="IsSelected"值=真"/><条件属性="IsSelectionActive"值="假"/></MultiTrigger.Conditions><Setter TargetName="Bd"属性=背景"Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/><Setter 属性="前景"Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/></多触发器><触发器属性="IsEnabled"值="假"><Setter 属性="前景"Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/></触发器></ControlTemplate.Triggers></控制模板></Setter.Value></Setter></风格>

If I set TreeViewItem Background it highlights the header only. How can I highlight the whole line?

I have found a post almost solving a problem http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b04f73e2-0b10-4d97-a6da-64df2e30c21d/

But there are some problems: 1. It does not highlight the whole line 2. The tree has XP style on Vista. I whould like it to looks the same way on Vista as it was, but if user changed the theme to XP - it should be XP way. 3. So many XAML...

Any ideas, what I should look for?

解决方案

Here we go, third times a charm. If you want something that look like this.

This one takes a bit more work. I'm sure there are many ways of doing this, but this method uses a Length Converter and a TreeViewItem extension method to get the Depth. Both of these are tightly coupled to the TreeViewItem visual tree, so if you start messing with the Templates then you may have troubles. Again, here is the important part, and below is the full code.

<ControlTemplate TargetType="{x:Type TreeViewItem}">
  <ControlTemplate.Resources>
      <local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" />
  </ControlTemplate.Resources>
  <StackPanel>
        <Border Name="Bd"
          Background="{TemplateBinding Background}"
          BorderBrush="{TemplateBinding BorderBrush}"
          BorderThickness="{TemplateBinding BorderThickness}"
          Padding="{TemplateBinding Padding}">
            <Grid Margin="{Binding Converter={StaticResource lengthConverter},
                    RelativeSource={RelativeSource TemplatedParent}}">

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="19" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <ToggleButton x:Name="Expander"
                    Style="{StaticResource ExpandCollapseToggleStyle}"
                    IsChecked="{Binding Path=IsExpanded,
                    RelativeSource={RelativeSource TemplatedParent}}"
                    ClickMode="Press"/>

                <ContentPresenter x:Name="PART_Header"
                    Grid.Column="1"
                    ContentSource="Header"
                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
            </Grid>
      </Border>
      <ItemsPresenter x:Name="ItemsHost" />
    </StackPanel>
    <!-- Triggers -->
</ControlTemplate>

TreeViewDepth Extension

public static class TreeViewItemExtensions
{
    public static int GetDepth(this TreeViewItem item)
    {
        TreeViewItem parent;
        while ((parent = GetParent(item)) != null)
        {
            return GetDepth(parent) + 1;
        }
        return 0;
    }

    private static TreeViewItem GetParent(TreeViewItem item)
    {
        var parent = VisualTreeHelper.GetParent(item);
        while (!(parent is TreeViewItem || parent is TreeView))
        {
            parent = VisualTreeHelper.GetParent(parent);
        }
        return parent as TreeViewItem;
    }
}

LeftMarginMultiplierConverter

public class LeftMarginMultiplierConverter : IValueConverter
{
    public double Length { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var item = value as TreeViewItem;
        if (item == null)
            return new Thickness(0);

        return new Thickness(Length * item.GetDepth(), 0, 0, 0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new System.NotImplementedException();
    }
}

Control

<TreeView Margin="50" HorizontalContentAlignment="Stretch">
    <TreeViewItem Header="test2"/>
    <TreeViewItem Header="test2">
        <TreeViewItem Header="sub test">
            <TreeViewItem Header="sub test1-1"/>
            <TreeViewItem Header="sub test1-2"/>
        </TreeViewItem>
        <TreeViewItem Header="sub test2"/>
    </TreeViewItem>
    <TreeViewItem Header="test3"/>
</TreeView>

Full TreeViewItem Style

<SolidColorBrush x:Key="GlyphBrush" Color="#444" />

<!--=================================================================
     TreeViewItem
  ==================================================================-->
<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
  <Setter Property="Focusable" Value="False"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ToggleButton">
        <Grid
          Width="15"
          Height="13"
          Background="Transparent">
          <Path x:Name="ExpandPath"
            HorizontalAlignment="Left" 
            VerticalAlignment="Center" 
            Margin="1,1,1,1"
            Fill="{StaticResource GlyphBrush}"
            Data="M 4 0 L 8 4 L 4 8 Z"/>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsChecked"
               Value="True">
            <Setter Property="Data"
                TargetName="ExpandPath"
                Value="M 0 4 L 8 4 L 4 8 Z"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
<Style x:Key="TreeViewItemFocusVisual">
  <Setter Property="Control.Template">
    <Setter.Value>
      <ControlTemplate>
        <Border>
          <Rectangle Margin="0,0,0,0"
                 StrokeThickness="5"
                 Stroke="Black"
                 StrokeDashArray="1 2"
                 Opacity="0"/>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>


<Style x:Key="{x:Type TreeViewItem}"
     TargetType="{x:Type TreeViewItem}">
  <Setter Property="Background"
      Value="Transparent"/>
  <Setter Property="HorizontalContentAlignment"
      Value="{Binding Path=HorizontalContentAlignment,
              RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
  <Setter Property="VerticalContentAlignment"
      Value="{Binding Path=VerticalContentAlignment,
              RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
  <Setter Property="Padding"
      Value="1,0,0,0"/>
  <Setter Property="Foreground"
      Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
  <Setter Property="FocusVisualStyle"
      Value="{StaticResource TreeViewItemFocusVisual}"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type TreeViewItem}">
        <ControlTemplate.Resources>
            <local:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" />
        </ControlTemplate.Resources>
        <StackPanel>
        <Border Name="Bd"
              Background="{TemplateBinding Background}"
              BorderBrush="{TemplateBinding BorderBrush}"
              BorderThickness="{TemplateBinding BorderThickness}"
              Padding="{TemplateBinding Padding}">
            <Grid Margin="{Binding Converter={StaticResource lengthConverter},
                              RelativeSource={RelativeSource TemplatedParent}}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="19" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
          <ToggleButton x:Name="Expander"
                  Style="{StaticResource ExpandCollapseToggleStyle}"
                  IsChecked="{Binding Path=IsExpanded,
                              RelativeSource={RelativeSource TemplatedParent}}"
                  ClickMode="Press"/>

            <ContentPresenter x:Name="PART_Header"
            Grid.Column="1"
                      ContentSource="Header"
                      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
            </Grid>
          </Border>
          <ItemsPresenter x:Name="ItemsHost" />
        </StackPanel>
        <ControlTemplate.Triggers>
          <Trigger Property="IsExpanded"
               Value="false">
            <Setter TargetName="ItemsHost"
                Property="Visibility"
                Value="Collapsed"/>
          </Trigger>
          <Trigger Property="HasItems"
               Value="false">
            <Setter TargetName="Expander"
                Property="Visibility"
                Value="Hidden"/>
          </Trigger>
          <MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="HasHeader"
                     Value="false"/>
              <Condition Property="Width"
                     Value="Auto"/>
            </MultiTrigger.Conditions>
            <Setter TargetName="PART_Header"
                Property="MinWidth"
                Value="75"/>
          </MultiTrigger>
          <MultiTrigger>
            <MultiTrigger.Conditions>
              <Condition Property="HasHeader"
                     Value="false"/>
              <Condition Property="Height"
                     Value="Auto"/>
            </MultiTrigger.Conditions>
            <Setter TargetName="PART_Header"
                Property="MinHeight"
                Value="19"/>
          </MultiTrigger>
          <Trigger Property="IsSelected"
               Value="true">
            <Setter TargetName="Bd"
                Property="Background"
                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 TargetName="Bd"
                Property="Background"
                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>
    </Setter.Value>
  </Setter>
</Style>

这篇关于在 WPF 中突出显示整个 TreeViewItem 行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆