突出显示WPF中的整个TreeViewItem行

时间:2009-03-20 01:08:07

标签: wpf templates treeviewitem

如果我设置TreeViewItem背景,它只突出显示标题。我怎样才能突出整条线?

我发现了一篇几乎解决问题的帖子http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b04f73e2-0b10-4d97-a6da-64df2e30c21d/

但是有一些问题: 它没有强调整条线 这棵树在Vista上有XP风格。我希望它在Vista上的外观和原来一样,但如果用户将主题更改为XP - 它应该是XP方式。 那么多XAML ......

任何想法,我应该寻找什么?

9 个答案:

答案 0 :(得分:102)

我们走了,第三次魅力。如果你想要这样的东西。

Full Width TreeView

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

<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();
    }
}

<强>控制

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

完整TreeViewItem样式

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

答案 1 :(得分:17)

TreeViewItem标题不会拉伸?

出现此问题的原因是,TreeViewItem的WPF默认模板设置为3列乘2行Grid。第一行用于“标题”(实际上是Border),第二行用于ItemsPresenter。根据需要使两行可见或隐藏,以便在单击小三角形时完成树展开 - 它占据Grid的第0列。

这两行实际上只需要一个额外的列。例如,在第二行中,我们必须在col-0,row-1处没有任何内容,因为当IsExpanded为真时,该空白部分应缩进。但是,当我们注意到基于第1行第1行的ItemsPresenter指定 Grid.ColumnSpan=2 时,这个谜就开始了。

不幸的是,在第一行中,包含标题的Border设置为Grid.Column=1 ...但没有ColumnSpan。由于Grid的col-2有Width=*,这意味着标题/边框不会水平拉伸。

换句话说,我认为3列网格设计没有任何意义,只是为了防止标题拉伸。据我所知,一个简单的2x2安排会更灵活[编辑:见脚注#2],并支持全拉伸'锯齿'标头非拉伸,通过常规WPF对齐机制。

理想情况下,我们会将Grid更改为只有2列而不是3列。由于这不是那么容易,而是 使标题跨度为2列 ,就像ItemsPresenter一样。

好的,这是一个小型,完整,自包含(仅限XAML)的工作程序,它演示并修复了问题:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:r="clr-namespace:System.Reflection;assembly=mscorlib"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Width="800" SizeToContent="Manual">

  <TreeView ItemsSource="{Binding Source={StaticResource data}}"
            VirtualizingStackPanel.VirtualizationMode="Recycling"
            VirtualizingStackPanel.IsVirtualizing="True"
            VirtualizingPanel.ScrollUnit="Item">

    <TreeView.Resources>
        <ObjectDataProvider x:Key="data" ObjectInstance="{x:Static sys:AppDomain.CurrentDomain}" MethodName="GetAssemblies" />

        <HierarchicalDataTemplate DataType="{x:Type r:Assembly}" ItemsSource="{Binding Path=DefinedTypes}" >
            <TextBlock Text="{Binding Path=Location}" />
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type sys:Type}" ItemsSource="{Binding Path=CustomAttributes}">
            <TextBlock Text="{Binding Path=Name}" />
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="{x:Type r:CustomAttributeData}" ItemsSource="{Binding Path=ConstructorArguments}">
            <TextBlock Text="{Binding Path=AttributeType.Name}" />
        </HierarchicalDataTemplate>
    </TreeView.Resources>

    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">

            <!-- == == BEGIN HERE == == -->
            <Style.Resources>
                <Style TargetType="{x:Type Border}">
                    <Setter Property="Grid.ColumnSpan" Value="2" />
                </Style>
            </Style.Resources>
            <!-- == == == END == == == -->

            <Setter Property="Background" Value="LightBlue" />

        </Style>
    </TreeView.ItemContainerStyle>
  </TreeView>
</Window>

如果您运行此程序如图所示,您将看到类似这样的内容。这是固定行为,它允许您重新获得对TreeViewItem标题的拉伸行为的完全控制:

enter image description here

注意BEGIN / END部分在XAML源中带有虚线。基本上,我只是在有问题的Grid.ColumnSpan=2上设置Border,以便填充Grid的拉伸宽度。该元素由TreeViewItem模板发出,因此我发现改变其属性的有效方法是通过{{1>}的资源字典中的定位Style } TreeViewItem。是的,令人困惑。通过Style访问Style

要查看(现有的)破坏行为,您可以在虚线之间注释掉部分:

enter image description here

您也可以在某些资源字典中设置这些样式,而不是像我在这里那样使用TreeViewItem.ItemContainerStyle属性。我这样做是因为它最小化了修复的范围,因此不会影响不相关的ItemContainerStyle控件。如果您确实需要一种更具辨别力的方法来定位此控件,您可以利用它具有Border的事实。

[edit:] 此解决方案使用反射!不要被无意义的演示数据吓到 - 它与此问题无关;这只是获取一些分层数据用于演示目的的最简单方法,同时保持整个程序的微小。

[编辑#2:]我刚刚意识到设计师试图通过3x2网格布置避免的是以下难看的效果(通过缩小的屏幕截图在这里夸大)。因此,如果您采用本页面中的一个解决方案,请预先警告您可能不希望这样:

enter image description here

答案 2 :(得分:6)

如果你的意思是这样的截图

Full Width TreeViewItem
(来源:bendewey.com

<强>更新 如上所述,这个例子的缩写是在子项目上缩进

Full Width TreeViewItem
(来源:bendewey.com

那么这应该对你有所帮助。它也基于http://msdn.microsoft.com/en-us/library/ms788727.aspx你可以将TreeViewItem的模板更改为StackPanel并将ItemsPanel左边距设置为19.然后在TreeView中设置Horizo​​ntalContentAlignment =“Stretch”。我在下面附上了整个资源,但这里是重要的部分。

<ControlTemplate TargetType="{x:Type TreeViewItem}">
<StackPanel>
    <Border Name="Bd"
      Background="{TemplateBinding Background}"
      BorderBrush="{TemplateBinding BorderBrush}"
      BorderThickness="{TemplateBinding BorderThickness}"
      Padding="{TemplateBinding Padding}">
        <Grid>
        <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" Margin="19,0,0,0" />
</StackPanel>
<!-- Triggers -->
</ControlTemplate>

<强>控制

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

<强>资源

<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}">
        <StackPanel>
            <Border Name="Bd"
              Background="{TemplateBinding Background}"
              BorderBrush="{TemplateBinding BorderBrush}"
              BorderThickness="{TemplateBinding BorderThickness}"
              Padding="{TemplateBinding Padding}">
            <Grid>
                <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" Margin="19,0,0,0" />
        </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>

答案 3 :(得分:4)

如果你的意思是这样的截图

LineItem Hightlighting in a TreeView
(来源:bendewey.com

那么这应该对你有所帮助。它基于http://msdn.microsoft.com/en-us/library/ms788727.aspx,您可以对TreeViewItem的Grid布局进行一些更改。基本上你删除第三列。然后在TreeView中设置Horizo​​ntalContentAlignment =“Stretch”。我在下面附上了整个资源,但这里是重要的部分。

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

<强>控制

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

<强>资源

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

答案 4 :(得分:4)

这是迄今为止最简单的解决方案。只需创建一个矩形,将其称为Hb,并将其边距设置为-100px并且不可见。只有在选中或鼠标悬停时才将其设置为Visible。这是一个黑客,但你最好有5个级别的嵌套TreeViewItems(100> 19 * 5)

     <ControlTemplate TargetType="{x:Type TreeViewItem}">
  <Grid>
   <Grid.ColumnDefinitions>
    <ColumnDefinition MinWidth="19" Width="Auto"/>
    <ColumnDefinition Width="*"/>
   </Grid.ColumnDefinitions>
   <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition/>
   </Grid.RowDefinitions>
                        <ToggleButton x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press" VerticalAlignment="Top" Panel.ZIndex="1"/>
   <Rectangle x:Name="Hb" Width="Auto" Height="Auto" Grid.ColumnSpan="2" Margin="-100,0,0,0" Panel.ZIndex="-1" Visibility="Hidden" />
                        <Border x:Name="Bd" SnapsToDevicePixels="true" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" Grid.Column="1" Panel.ZIndex="0">
    <ContentPresenter x:Name="PART_Header" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ContentSource="Header" HorizontalAlignment="Stretch"/>
   </Border>
   <ItemsPresenter x:Name="ItemsHost" Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Margin="19,0,0,0"/>
  </Grid>

答案 5 :(得分:1)

使用带有ItemsSource的TreeView的问题来源是link text引用的,如果是TreeViewItem Extensions类,我已经更改了一些代码:

public static class TreeViewItemExtensions
{
    public static int GetDepth(this TreeViewItem item)
    {
        while (GetSelectedTreeViewItemParent(item) != null)
        {
            var parent = GetSelectedTreeViewItemParent(item);
            if (parent != null)
                return parent.GetDepth() + 1;

            item = parent;
        }
        return 0;
 }

 public static TreeViewItem GetSelectedTreeViewItemParent(this TreeViewItem item)
 {
        DependencyObject parent = VisualTreeHelper.GetParent(item);
        while (!(parent is TreeViewItem || parent is TreeView))
        {
            parent = VisualTreeHelper.GetParent(parent);
        }

        return parent as TreeViewItem;
  }
}

答案 6 :(得分:1)

使用像theseven7这样的东西来促进bendewey代码与模板化TreeViewItems的使用......

    public static int GetDepth(this TreeViewItem item)
    {
        FrameworkElement elem = item;
        var parent = VisualTreeHelper.GetParent(item);
        var count = 0;
        while (parent != null && !(parent is TreeView))
        {
            var tvi = parent as TreeViewItem;
            if (parent is TreeViewItem)
                count++;
            parent = VisualTreeHelper.GetParent(parent);
        }
        return count;
    }

答案 7 :(得分:0)

对于XAML唯一的方法,我采用了Bendewey的一个解决方案,并将其分解为一个更基本的解决方案:

下面的样式应该允许Treeview项目跨越:

<Style TargetType="{x:Type TreeViewItem}">           
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TreeViewItem}">                    
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition MinWidth="19"
                  Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <ToggleButton x:Name="Expander"
              Content="..." 
              IsChecked="{Binding Path=IsExpanded,
                          RelativeSource={RelativeSource TemplatedParent}}"
              ClickMode="Press"/>
                    <Border Name="Bd" Grid.Column="1" Background="Red" Padding="3">
                        <ContentPresenter x:Name="PART_Header"   ContentSource="Header"
                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                    </Border>
                    <ItemsPresenter x:Name="ItemsHost"  Grid.Row="1"   Grid.Column="1"/>
                </Grid>  
      <!-- ADD TRIGGERS HERE -->                                  
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

为了让它像正确的Treeview一样运行和崩溃,下面的触发器应允许这样:

<ControlTemplate.Triggers>                                          
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="HasHeader" Value="false"/>
                            <Condition Property="Width" Value="Auto"/>
                        </MultiTrigger.Conditions>                            
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="HasHeader" Value="false"/>
                            <Condition Property="Height" Value="Auto"/>
                        </MultiTrigger.Conditions>                          
                    </MultiTrigger>                        
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true"/>
                            <Condition Property="IsSelectionActive" Value="false"/>
                        </MultiTrigger.Conditions>                                             
                    </MultiTrigger>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter TargetName="Bd" Property="Background" Value="Blue"/>                           
                    </Trigger>
                    <Trigger Property="HasItems" Value="false">
                        <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
                    </Trigger>
                    <Trigger Property="IsExpanded"   Value="false">
                        <Setter TargetName="ItemsHost"
                                Property="Visibility"
                                Value="Collapsed"/>
                    </Trigger>
</ControlTemplate.Triggers> 

将触发器嵌套在控件模板中。颜色/填充/设计需要调整以满足您自己的需要,但上述应该是仅在XAML基础上的一个非常基本的想法。

答案 8 :(得分:-1)

我通过使用blend复制ItemContainerStyle来管理它,为项目放置的网格命名,然后设置网格的背景。