1

I am developing a WPF application and I'm struggling with TreeView. I want to achieve look like in Windows Explorer. enter image description here

The default TreeView style stretches the TreeViewItem only for the required space.

enter image description here

I have overridden the default template to achieve this look, but I really cannot figure out how to add the space on left of child items. enter image description here

My code:

<ControlTemplate TargetType="{x:Type TreeViewItem}">
   <Grid>
      <Grid.ColumnDefinitions>
         <ColumnDefinition Width="*"/>
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
         <RowDefinition Height="Auto"/>
         <RowDefinition/>
      </Grid.RowDefinitions>
      <Border x:Name="Bd" Grid.Column="0" HorizontalAlignment="Stretch" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
         <Grid>
            <Grid.ColumnDefinitions>
               <ColumnDefinition MinWidth="19" Width="Auto"/>
               <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
               <RowDefinition Height="Auto"/>
               <RowDefinition/>
            </Grid.RowDefinitions>
            <ContentPresenter x:Name="PART_Header" Grid.Column="1" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
            <ToggleButton x:Name="Expander" Grid.Column="0" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
         </Grid>
      </Border>
      <ItemsPresenter x:Name="ItemsHost" Grid.Row="1" Grid.Column="1" />
   </Grid>
thatguy
  • 21,059
  • 6
  • 30
  • 40
Jakub
  • 95
  • 13
  • You forgot to add `` to the first grid so ItemsPresenter with Grid.Column="1" will be put in the first column – Bizhan Jul 17 '20 at 08:17

1 Answers1

0

Your Style got some flaws.
You are missing a column (that's why the items are positioned below the header). Your ItemsPresenter is visible all the time. It should be collapsed and become visible only when the expander is pressed. You are missing a corresponding trigger. Also you need to hide the expaner for items that don't have children.

This how the basic Style should look like.
To change the indetion, just add a Margin to the ItemPresenter.

<Style TargetType="TreeViewItem">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type TreeViewItem}">
        <Grid SnapsToDevicePixels="true">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
          </Grid.RowDefinitions>

          <ToggleButton x:Name="Expander" 
                        Grid.Column="0" Grid.Row="0"
                        ClickMode="Press"
                        IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}"
                        Style="{StaticResource ExpandCollapseToggleStyle}" />
          <Border x:Name="Bd" 
                  Grid.Column="1" Grid.Row="0"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}"
                  Background="{TemplateBinding Background}"
                  Padding="{TemplateBinding Padding}">

            <ContentPresenter x:Name="PART_Header"
                              ContentSource="Header"
                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
          </Border>

          <ItemsPresenter x:Name="ItemsHost" 
                          Grid.Row="1" Grid.Column="1"
                          Visibility="Collapsed" />
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="HasItems"
                   Value="false">
            <Setter TargetName="Expander"
                    Property="Visibility"
                    Value="Hidden" />
          </Trigger>
          <Trigger Property="IsExpanded"
                   Value="True">
            <Setter TargetName="ItemsHost"
                    Property="Visibility"
                    Value="Visible" />
          </Trigger>
          <Trigger Property="IsSelected"
                   Value="True">
            <Setter Property="Background"
                    Value="CornflowerBlue" />
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
BionicCode
  • 1
  • 4
  • 28
  • 44
  • But then the Item does not expand to full parent [length](https://imgur.com/a/Eq5p3pq) like in the windows explorer in question does – Jakub Jul 17 '20 at 19:13
  • What do you mean? The items will stretch to occupy available horizontal space. How do you set the selected item background? – BionicCode Jul 17 '20 at 19:38
  • I have added a corresponding `IsSelected` trigger to set the background of the selected item. Using the above code the item does stretch as expected. – BionicCode Jul 17 '20 at 19:41