Themes/MaterialDesignTheme.TreeView.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:converters="clr-namespace:MaterialDesignThemes.Wpf.Converters"
                    xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf">
  <Style x:Key="MaterialDesignTreeView" TargetType="{x:Type TreeView}">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="BorderBrush" Value="{x:Null}" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Foreground" Value="{DynamicResource MaterialDesign.Brush.Foreground}" />
    <Setter Property="Padding" Value="1" />
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
    <Setter Property="ScrollViewer.PanningMode" Value="Both" />
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
    <Setter Property="Stylus.IsFlicksEnabled" Value="False" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type TreeView}">
          <Border BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}"
                  SnapsToDevicePixels="true">
            <ScrollViewer x:Name="_tv_scrollviewer_"
                          Padding="{TemplateBinding Padding}"
                          Background="{TemplateBinding Background}"
                          wpf:ScrollViewerAssist.IgnorePadding="{Binding Path=(wpf:ScrollViewerAssist.IgnorePadding), RelativeSource={RelativeSource TemplatedParent}}"
                          wpf:ScrollViewerAssist.PaddingMode="{Binding Path=(wpf:ScrollViewerAssist.PaddingMode), RelativeSource={RelativeSource TemplatedParent}}"
                          CanContentScroll="false"
                          Focusable="false"
                          HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                          VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
              <ItemsPresenter />
            </ScrollViewer>
          </Border>
          <ControlTemplate.Triggers>
            <Trigger Property="IsEnabled" Value="false">
              <Setter Property="Opacity" Value=".56" />
            </Trigger>
            <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
              <Setter TargetName="_tv_scrollviewer_" Property="CanContentScroll" Value="true" />
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="wpf:TreeViewAssist.HasNoItemsExpanderVisibility" Value="Hidden" />
    <Style.Triggers>
      <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
        <Setter Property="ItemsPanel">
          <Setter.Value>
            <ItemsPanelTemplate>
              <VirtualizingStackPanel />
            </ItemsPanelTemplate>
          </Setter.Value>
        </Setter>
      </Trigger>
    </Style.Triggers>
  </Style>
 
  <Style x:Key="MaterialDesignTreeViewItemFocusVisual">
    <Setter Property="Control.Template">
      <Setter.Value>
        <ControlTemplate>
          <Rectangle />
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
 
  <Style x:Key="MaterialDesignExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="Focusable" Value="False" />
    <Setter Property="Height" Value="16" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type ToggleButton}">
          <Border Width="{TemplateBinding Width}"
                  Height="{TemplateBinding Height}"
                  Background="{TemplateBinding Background}">
            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="CheckStates">
                <VisualStateGroup.Transitions>
                  <VisualTransition From="Unchecked" To="Checked">
                    <VisualTransition.GeneratedEasingFunction>
                      <QuarticEase EasingMode="EaseOut" />
                    </VisualTransition.GeneratedEasingFunction>
                    <Storyboard>
                      <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpandPath" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
                        <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                        <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="45" />
                      </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualTransition>
                  <VisualTransition GeneratedDuration="0" To="Unchecked">
                    <Storyboard>
                      <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpandPath" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
                        <EasingDoubleKeyFrame KeyTime="0" Value="45" />
                      </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualTransition>
                  <VisualTransition GeneratedDuration="0" To="Checked">
                    <Storyboard>
                      <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpandPath" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
                        <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                      </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualTransition>
                  <VisualTransition GeneratedDuration="0"
                                    From="Checked"
                                    To="Unchecked">
                    <VisualTransition.GeneratedEasingFunction>
                      <QuarticEase EasingMode="EaseOut" />
                    </VisualTransition.GeneratedEasingFunction>
                    <Storyboard>
                      <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpandPath" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
                        <EasingDoubleKeyFrame KeyTime="0" Value="45" />
                        <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0" />
                      </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualTransition>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Checked">
                  <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpandPath" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
                      <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="45" />
                    </DoubleAnimationUsingKeyFrames>
                  </Storyboard>
                </VisualState>
                <VisualState x:Name="Unchecked">
                  <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpandPath" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
                      <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0" />
                    </DoubleAnimationUsingKeyFrames>
                  </Storyboard>
                </VisualState>
              </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Viewbox>
              <Canvas Width="24" Height="24">
                <Path x:Name="ExpandPath"
                      Data="M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z"
                      Fill="{TemplateBinding Foreground}"
                      RenderTransformOrigin=".5,.5"
                      SnapsToDevicePixels="True"
                      Stroke="{TemplateBinding Foreground}">
                  <Path.RenderTransform>
                    <TransformGroup>
                      <ScaleTransform />
                      <SkewTransform />
                      <RotateTransform Angle="0" CenterX="4" CenterY="4" />
                      <TranslateTransform />
                    </TransformGroup>
                  </Path.RenderTransform>
                </Path>
              </Canvas>
            </Viewbox>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
    <Setter Property="Width" Value="16" />
  </Style>
 
  <Style x:Key="MaterialDesignTreeViewItem" TargetType="{x:Type TreeViewItem}">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="FocusVisualStyle" Value="{StaticResource MaterialDesignTreeViewItemFocusVisual}" />
    <Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}" />
    <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
    <Setter Property="Padding" Value="8" />
    <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 Height="Auto" />
              <RowDefinition />
            </Grid.RowDefinitions>
            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup Name="CommonStates">
                <VisualStateGroup.Transitions>
                  <VisualTransition GeneratedDuration="0:0:0.3" To="Normal">
                    <VisualTransition.GeneratedEasingFunction>
                      <CubicEase EasingMode="EaseOut" />
                    </VisualTransition.GeneratedEasingFunction>
                  </VisualTransition>
                </VisualStateGroup.Transitions>
                <VisualState Name="Normal" />
                <VisualState Name="MouseOver">
                  <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="MouseOverBorder"
                                     Storyboard.TargetProperty="Opacity"
                                     To="0.1"
                                     Duration="0" />
                    <DoubleAnimation Storyboard.TargetName="MouseOverBorder"
                                     Storyboard.TargetProperty="Opacity"
                                     To="0.1"
                                     Duration="0" />
                  </Storyboard>
                </VisualState>
                <VisualState Name="Disabled" />
              </VisualStateGroup>
              <VisualStateGroup x:Name="SelectionStates">
                <VisualStateGroup.Transitions>
                  <VisualTransition GeneratedDuration="0:0:0.6" />
                </VisualStateGroup.Transitions>
                <VisualState Name="Selected">
                  <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="SelectedBorder"
                                     Storyboard.TargetProperty="Opacity"
                                     To="0.18"
                                     Duration="0" />
                  </Storyboard>
                </VisualState>
                <VisualState Name="Unselected" />
              </VisualStateGroup>
              <VisualStateGroup x:Name="ExpansionStates">
                <VisualStateGroup.Transitions>
                  <VisualTransition GeneratedDuration="0" To="Expanded">
                    <VisualTransition.GeneratedEasingFunction>
                      <CubicEase EasingMode="EaseOut" />
                    </VisualTransition.GeneratedEasingFunction>
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsHost" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
                      </ObjectAnimationUsingKeyFrames>
                      <DoubleAnimation Storyboard.TargetName="ItemsHost"
                                       Storyboard.TargetProperty="Opacity"
                                       To="1"
                                       Duration="0:0:0.3" />
                      <DoubleAnimation Storyboard.TargetName="ScaleHost"
                                       Storyboard.TargetProperty="Scale"
                                       To="1"
                                       Duration="0:0:0.3" />
                    </Storyboard>
                  </VisualTransition>
                  <VisualTransition GeneratedDuration="0" To="Collapsed">
                    <VisualTransition.GeneratedEasingFunction>
                      <CubicEase EasingMode="EaseOut" />
                    </VisualTransition.GeneratedEasingFunction>
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsHost" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0:0:0.3" Value="{x:Static Visibility.Collapsed}" />
                      </ObjectAnimationUsingKeyFrames>
                      <DoubleAnimation Storyboard.TargetName="ItemsHost"
                                       Storyboard.TargetProperty="Opacity"
                                       To="0"
                                       Duration="0:0:0.3" />
                      <DoubleAnimation Storyboard.TargetName="ScaleHost"
                                       Storyboard.TargetProperty="Scale"
                                       To="0"
                                       Duration="0:0:0.3" />
                    </Storyboard>
                  </VisualTransition>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Expanded">
                  <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="ItemsHost"
                                     Storyboard.TargetProperty="Opacity"
                                     To="1"
                                     Duration="0" />
                    <DoubleAnimation Storyboard.TargetName="ScaleHost"
                                     Storyboard.TargetProperty="Scale"
                                     To="1"
                                     Duration="0:0:0.3" />
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsHost" Storyboard.TargetProperty="Visibility">
                      <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
                    </ObjectAnimationUsingKeyFrames>
                  </Storyboard>
                </VisualState>
                <VisualState x:Name="Collapsed">
                  <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="ItemsHost"
                                     Storyboard.TargetProperty="Opacity"
                                     To="0"
                                     Duration="0" />
                    <DoubleAnimation Storyboard.TargetName="ScaleHost"
                                     Storyboard.TargetProperty="Scale"
                                     To="0"
                                     Duration="0:0:0.3" />
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsHost" Storyboard.TargetProperty="Visibility">
                      <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                    </ObjectAnimationUsingKeyFrames>
                  </Storyboard>
                </VisualState>
              </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <wpf:ScaleHost x:Name="ScaleHost" />
            <ToggleButton x:Name="Expander"
                          Width="{TemplateBinding wpf:TreeViewAssist.ExpanderSize}"
                          Height="{TemplateBinding wpf:TreeViewAssist.ExpanderSize}"
                          Margin="8,0,8,0"
                          VerticalAlignment="Center"
                          ClickMode="Press"
                          Foreground="{TemplateBinding Foreground}"
                          IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
                          Style="{StaticResource MaterialDesignExpandCollapseToggleStyle}" />
 
            <Border x:Name="MouseOverBorder"
                    Grid.Column="1"
                    Grid.ColumnSpan="2"
                    Background="{TemplateBinding Foreground, Converter={x:Static converters:BrushRoundConverter.Instance}}"
                    IsHitTestVisible="False"
                    Opacity="0" />
 
            <Border x:Name="SelectedBorder"
                    Grid.Column="1"
                    Grid.ColumnSpan="2"
                    Background="{TemplateBinding Foreground, Converter={x:Static converters:BrushRoundConverter.Instance}}"
                    IsHitTestVisible="False"
                    Opacity="0" />
 
            <Grid x:Name="ContentGrid"
                  Grid.Column="1"
                  Grid.ColumnSpan="2"
                  Background="{TemplateBinding Background}">
              <wpf:Ripple x:Name="Ripple"
                          Padding="{TemplateBinding Padding}"
                          HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                          VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                          Feedback="{TemplateBinding Foreground, Converter={x:Static converters:BrushRoundConverter.Instance}}"
                          Focusable="False"
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
                <ContentPresenter x:Name="PART_Header" ContentSource="Header" />
              </wpf:Ripple>
            </Grid>
 
            <ContentControl x:Name="AdditionalContentControl"
                            Grid.Row="1"
                            Grid.Column="1"
                            Grid.ColumnSpan="2"
                            Content="{TemplateBinding Header}"
                            ContentTemplate="{Binding RelativeSource={RelativeSource Self}, Path=(wpf:TreeViewAssist.AdditionalTemplate)}"
                            ContentTemplateSelector="{Binding RelativeSource={RelativeSource Self}, Path=(wpf:TreeViewAssist.AdditionalTemplateSelector)}"
                            Visibility="Collapsed" />
 
            <StackPanel x:Name="ItemsPanel"
                        Grid.Row="2"
                        Grid.Column="1"
                        Grid.ColumnSpan="2"
                        Margin="-16,0,0,0">
              <StackPanel.Height>
                <MultiBinding Converter="{x:Static converters:MathMultipleConverter.MultiplyInstance}">
                  <Binding ElementName="ItemsHost" Path="ActualHeight" />
                  <Binding ElementName="ScaleHost" Path="Scale" />
                </MultiBinding>
              </StackPanel.Height>
              <ItemsPresenter x:Name="ItemsHost"
                              VerticalAlignment="Top"
                              Opacity="0"
                              Visibility="Collapsed" />
            </StackPanel>
          </Grid>
          <ControlTemplate.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=(wpf:TreeViewAssist.AdditionalTemplate), Converter={x:Static converters:NullableToVisibilityConverter.CollapsedInstance}, Mode=OneWay}" Value="Visible">
              <Setter TargetName="AdditionalContentControl" Property="Visibility" Value="Visible" />
            </DataTrigger>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=(wpf:TreeViewAssist.AdditionalTemplateSelector), Converter={x:Static converters:NullableToVisibilityConverter.CollapsedInstance}, Mode=OneWay}" Value="Visible">
              <Setter TargetName="AdditionalContentControl" Property="Visibility" Value="Visible" />
            </DataTrigger>
            <Trigger Property="HasItems" Value="false">
              <Setter TargetName="Expander" Property="Visibility" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:TreeViewAssist.HasNoItemsExpanderVisibility)}" />
            </Trigger>
            <Trigger Property="IsEnabled" Value="false">
              <Setter Property="Opacity" Value=".56" />
            </Trigger>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=(wpf:TreeViewAssist.ShowSelection)}" Value="False">
              <Setter TargetName="MouseOverBorder" Property="Visibility" Value="Collapsed" />
              <Setter TargetName="Ripple" Property="Feedback" Value="Transparent" />
              <Setter TargetName="SelectedBorder" Property="Visibility" Value="Collapsed" />
            </DataTrigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
    <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
    <Setter Property="wpf:TreeViewAssist.ExpanderSize" Value="16" />
    <Setter Property="wpf:TreeViewAssist.HasNoItemsExpanderVisibility" Value="{Binding RelativeSource={RelativeSource AncestorType=TreeView}, Path=(wpf:TreeViewAssist.HasNoItemsExpanderVisibility)}" />
    <Setter Property="wpf:TreeViewAssist.ShowSelection" Value="True" />
    <Style.Triggers>
      <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
        <Setter Property="ItemsPanel">
          <Setter.Value>
            <ItemsPanelTemplate>
              <VirtualizingStackPanel />
            </ItemsPanelTemplate>
          </Setter.Value>
        </Setter>
      </Trigger>
    </Style.Triggers>
  </Style>
</ResourceDictionary>