Выделить всю строку TreeViewItem в WPF - PullRequest
61 голосов
/ 20 марта 2009

Если я установлю TreeViewItem Background, он будет выделять только заголовок. Как я могу выделить всю строку?

Я нашел сообщение, почти решающее проблему http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b04f73e2-0b10-4d97-a6da-64df2e30c21d/

Но есть некоторые проблемы: 1. Не выделяет всю строку 2. Дерево имеет стиль XP на Vista. Мне бы хотелось, чтобы на Vista она выглядела так же, как и раньше, но если пользователь сменил тему на XP - это должен быть XP путь. 3. Так много XAML ...

Есть идеи, что мне искать?

Ответы [ 9 ]

103 голосов
/ 23 марта 2009

Вот и мы, третий раз очарование. Если вы хотите что-то похожее на это.

Full Width TreeView

Этот требует немного больше работы. Я уверен, что есть много способов сделать это, но этот метод использует конвертер длины и метод расширения 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

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>
17 голосов
/ 14 июня 2015

Заголовок TreeViewItem не растягивается?

Эта проблема возникает из-за того, что шаблон WPF по умолчанию для TreeViewItem настроен как 3-столбец для 2-строки Grid. Первая строка для «заголовка» (на самом деле Border), а вторая строка для ItemsPresenter. Две строки становятся видимыми или скрытыми по мере необходимости, чтобы выполнить расширение дерева, когда вы щелкаете по маленькому треугольнику - который занимает нулевой столбец Grid.

Обе строки действительно нуждаются только в одном дополнительном столбце. Например, во второй строке у нас ничего не должно быть в col-0, row-1, потому что эта пустая часть должна иметь отступ, если IsExpanded имеет значение true. Но загадка начинается, когда мы отмечаем, что ItemsPresenter, основанный на столбце col-1, row-1, указывает Grid.ColumnSpan=2.

К сожалению, в верхнем ряду Border, который содержит заголовок, установлен на Grid.Column=1 ... но без ColumnSpan. Поскольку у col-2 Grid есть Width=*, это означает, что заголовок / рамка не будут растягиваться горизонтально.

Другими словами, мне кажется, что у сетки с тремя столбцами нет никакой цели, кроме как специально предотвратить растяжение заголовка. Насколько я могу судить, простое расположение 2x2 было бы более гибким [править: см. Сноску # 2] и поддерживало бы либо полное растяжение , либо не растягивающийся заголовок с "зубчатыми" заголовками через обычный 1027 * выравнивающие механизмы.

В идеале, мы бы изменили 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, поэтому я обнаружил, что эффективный способ изменить его свойства - это настроить таргетинг Style в словаре ресурсов из TreeViewItem Style. Да, сбивает с толку. Доступ к Style осуществляется через TreeViewItem.ItemContainerStyle.

Чтобы увидеть (существующее) прерывистое поведение, вы можете закомментировать часть между пунктирными линиями:

enter image description here

Вы также можете установить эти стили в некотором словаре ресурсов вместо использования свойства ItemContainerStyle, как я это сделал здесь. Я сделал это так, потому что это сводит к минимуму объем исправления, так что не связанные элементы управления Border не будут затронуты. Если вам нужен более дискриминационный способ нацеливания именно на этот элемент управления, вы можете воспользоваться тем, что он имеет Name='Bd'.


[edit:] Это решение не использует отражение! Не пугайтесь бессмысленных демонстрационных данных - оно не имеет никакого отношения к этой проблеме; это был просто самый простой способ получить некоторые иерархические данные для демонстрационных целей, сохранив при этом всю программу крошечной.


[edit # 2:] Я только что понял, что дизайнеры пытались избежать с помощью сетки 3х2, это был следующий неприглядный эффект (преувеличенный здесь уменьшенным скриншотом). Поэтому, если вы воспользуетесь одним из решений на этой странице, имейте в виду, что вы можете не захотеть этого:

enter image description here

6 голосов
/ 21 марта 2009

Если вы имеете в виду что-то вроде этого скриншота

Full Width TreeViewItem
(источник: bendewey.com )

Обновление Как уже отмечалось, этот пример имеет отступ от подпунктов

Full Width TreeViewItem
(источник: bendewey.com )

Тогда это должно вам помочь. Он также основан на http://msdn.microsoft.com/en-us/library/ms788727.aspx. Вы можете изменить шаблон TreeViewItem на StackPanel и установить для левой позиции ItemsPanel значение 19. Затем в TreeView вы установите HorizontalContentAlignment = "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>
4 голосов
/ 27 октября 2009

Это, безусловно, самое простое решение. Просто создайте прямоугольник, назовите его 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>
4 голосов
/ 20 марта 2009

Если вы имеете в виду что-то вроде этого скриншота

LineItem Hightlighting in a TreeView
(источник: bendewey.com )

Тогда это должно вам помочь. На основе http://msdn.microsoft.com/en-us/library/ms788727.aspx вы можете внести некоторые изменения в компоновку Grid TreeViewItem. В основном вы удаляете третий столбец. Затем в TreeView вы устанавливаете HorizontalContentAlignment = "Растянуть". Я прилагаю весь ресурс ниже, но вот важная часть.

<!-- ... -->
<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>
1 голос
/ 07 августа 2010

Использовал что-то вроде thisven7 для облегчения использования кода Бендевея с шаблонными 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;
    }
1 голос
/ 24 сентября 2009

Источник проблемы при использовании TreeView с ItemsSource, по ссылке текст ссылки , я изменил некоторый код класса TreeViewItemExtensions:

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;
  }
}
0 голосов
/ 19 сентября 2017

Для подхода только на XAML я взял одно из решений Бендевея и разбил его на более простое решение:

Приведенный ниже стиль должен позволять элементам 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>

Чтобы заставить его работать и рушиться, как правильное древовидное представление, следующие триггеры должны разрешить это:

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

0 голосов
/ 10 апреля 2013

Я справился с этим, скопировав ItemContainerStyle с помощью blend, присвоив имя сетке, в которую помещен элемент, и затем установив фон сетки.

...