locked
Make TreeViewItem children nodes aligment like in Visual Studio property controls window. RRS feed

  • Question

  • Hello,

    I want to know how to make treeviewItem child node (without expander) to shift left towards its parent node like in Visual studio 2010/2012 WPF controls property window.

    Wednesday, October 9, 2013 2:19 PM

Answers

  • You also need to add the following resources. These are the default styles for a TreeViewItem that you can get from VS 2012 by right-click the TreeView in the designer and select "Edit additonal templates"->"Edit generated item container".

    You can modify any style and template as per your requirements.

    <Style x:Key="TreeViewItemFocusVisual">
          <Setter Property="Control.Template">
            <Setter.Value>
              <ControlTemplate>
                <Rectangle/>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Fill" Color="#FF595959"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Stroke" Color="#FF262626"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Stroke" Color="#FF1BBBFA"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Fill" Color="Transparent"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Stroke" Color="#FF262626"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Fill" Color="#FF595959"/>
        <PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Fill" Color="Transparent"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Stroke" Color="#FF989898"/>
        <Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
          <Setter Property="Focusable" Value="False"/>
          <Setter Property="Width" Value="16"/>
          <Setter Property="Height" Value="16"/>
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Border Background="Transparent" Height="16" Padding="5,5,5,5" Width="16">
                  <Path x:Name="ExpandPath" Data="{StaticResource TreeArrow}" Fill="{StaticResource TreeViewItem.TreeArrow.Static.Fill}" Stroke="{StaticResource TreeViewItem.TreeArrow.Static.Stroke}">
                    <Path.RenderTransform>
                      <RotateTransform Angle="135" CenterY="3" CenterX="3"/>
                    </Path.RenderTransform>
                  </Path>
                </Border>
                <ControlTemplate.Triggers>
                  <Trigger Property="IsChecked" Value="True">
                    <Setter Property="RenderTransform" TargetName="ExpandPath">
                      <Setter.Value>
                        <RotateTransform Angle="180" CenterY="3" CenterX="3"/>
                      </Setter.Value>
                    </Setter>
                    <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Fill}"/>
                    <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Stroke}"/>
                  </Trigger>
                  <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Stroke}"/>
                    <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Fill}"/>
                  </Trigger>
                  <MultiTrigger>
                    <MultiTrigger.Conditions>
                      <Condition Property="IsMouseOver" Value="True"/>
                      <Condition Property="IsChecked" Value="True"/>
                    </MultiTrigger.Conditions>
                    <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Stroke}"/>
                    <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Fill}"/>
                  </MultiTrigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>

    • Marked as answer by Black_Joker Monday, October 14, 2013 5:54 PM
    Thursday, October 10, 2013 10:04 AM

All replies

  • You could specify a custom style for the child nodes that removes the MinHeight of the leftmost column of the Grid in the ControlTemplate for a TreeViewItem:

    <TreeView>
          <TreeView.Resources>
            <Style x:Key="style" TargetType="{x:Type TreeViewItem}">
              <Setter Property="Background" Value="Transparent"/>
              <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
              <Setter Property="VerticalContentAlignment" Value="{Binding 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 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 BorderThickness}" 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="Collapsed"/>
                      </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>
                </Setter.Value>
              </Setter>
              <Style.Triggers>
                <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
                  <Setter Property="ItemsPanel">
                    <Setter.Value>
                      <ItemsPanelTemplate>
                        <VirtualizingStackPanel/>
                      </ItemsPanelTemplate>
                    </Setter.Value>
                  </Setter>
                </Trigger>
              </Style.Triggers>
            </Style>
          </TreeView.Resources>
          <TreeView.Items>
            <TreeViewItem Header="1">
              <TreeViewItem.Items>
                <TreeViewItem Header="11" Style="{StaticResource style}"/>
              </TreeViewItem.Items>
            </TreeViewItem>
            <TreeViewItem Header="2"/>
          </TreeView.Items>
        </TreeView>
    TreeView

     

    Wednesday, October 9, 2013 3:38 PM
  • Thanks for help, but I still have some questions regarding this style.

    Is it possible to make common style for all treeviewItems? Now it says that in this code block compiler does not see such static resource if I use this style separate from TreeViewItem.

    <Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/>

    And is it possible to make trigger on HasItems property to collapse expander when item has no subitems? Now it collapse expander even if it has subitems.

    Also compiler does not see resource  ExpandCollapseToggleStyle

    <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>

    • Edited by Black_Joker Thursday, October 10, 2013 9:18 AM
    Thursday, October 10, 2013 8:24 AM
  • You also need to add the following resources. These are the default styles for a TreeViewItem that you can get from VS 2012 by right-click the TreeView in the designer and select "Edit additonal templates"->"Edit generated item container".

    You can modify any style and template as per your requirements.

    <Style x:Key="TreeViewItemFocusVisual">
          <Setter Property="Control.Template">
            <Setter.Value>
              <ControlTemplate>
                <Rectangle/>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Fill" Color="#FF595959"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Stroke" Color="#FF262626"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Stroke" Color="#FF1BBBFA"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Fill" Color="Transparent"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Stroke" Color="#FF262626"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Fill" Color="#FF595959"/>
        <PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Fill" Color="Transparent"/>
        <SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Stroke" Color="#FF989898"/>
        <Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
          <Setter Property="Focusable" Value="False"/>
          <Setter Property="Width" Value="16"/>
          <Setter Property="Height" Value="16"/>
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Border Background="Transparent" Height="16" Padding="5,5,5,5" Width="16">
                  <Path x:Name="ExpandPath" Data="{StaticResource TreeArrow}" Fill="{StaticResource TreeViewItem.TreeArrow.Static.Fill}" Stroke="{StaticResource TreeViewItem.TreeArrow.Static.Stroke}">
                    <Path.RenderTransform>
                      <RotateTransform Angle="135" CenterY="3" CenterX="3"/>
                    </Path.RenderTransform>
                  </Path>
                </Border>
                <ControlTemplate.Triggers>
                  <Trigger Property="IsChecked" Value="True">
                    <Setter Property="RenderTransform" TargetName="ExpandPath">
                      <Setter.Value>
                        <RotateTransform Angle="180" CenterY="3" CenterX="3"/>
                      </Setter.Value>
                    </Setter>
                    <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Fill}"/>
                    <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Stroke}"/>
                  </Trigger>
                  <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Stroke}"/>
                    <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Fill}"/>
                  </Trigger>
                  <MultiTrigger>
                    <MultiTrigger.Conditions>
                      <Condition Property="IsMouseOver" Value="True"/>
                      <Condition Property="IsChecked" Value="True"/>
                    </MultiTrigger.Conditions>
                    <Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Stroke}"/>
                    <Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Fill}"/>
                  </MultiTrigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>

    • Marked as answer by Black_Joker Monday, October 14, 2013 5:54 PM
    Thursday, October 10, 2013 10:04 AM
  • Thanks for help. this style was exactly what I was looking.
    Monday, October 14, 2013 5:54 PM