WPF TreeView: how to style selected elements with rounded corners, as in Explorer

The selected item in WPF TreeView has a dark blue background with β€œsharp” corners. Today it looks a bit dated:

WPF selected TreeViewItem with or without focus

I would like to change the background so that it looks like in Windows 7 Explorer (with / without focus):

Explorer TreeViewItem selectedExplorer TreeViewItem selected without focus

What I have tried so far does not remove the original dark blue background, but draws a rounded frame on top, so that you see a dark blue color at the edges and on the left is ugly.

enter image description here

Interestingly, when my version has no focus, it looks pretty good:

enter image description here

I would like to refrain from revising the management template as here or here . I want to set the minimum required properties so that the selected item looks like in Explorer.

Alternative: I would also be glad if the focused selected element looked as if mine is doing now when it has no focus. When focus is lost, the color should change from blue to gray.

Here is my code:

<TreeView x:Name="TreeView" ItemsSource="{Binding TopLevelNodes}" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling"> <TreeView.ItemContainerStyle> <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="BorderBrush" Value="#FF7DA2CE" /> <Setter Property="Background" Value="#FFCCE2FC" /> </Trigger> </Style.Triggers> </Style> </TreeView.ItemContainerStyle> <TreeView.Resources> <HierarchicalDataTemplate DataType="{x:Type viewmodels:ObjectBaseViewModel}" ItemsSource="{Binding Children}"> <Border Name="ItemBorder" CornerRadius="2" Background="{Binding Background, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" BorderBrush="{Binding BorderBrush, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" BorderThickness="1"> <StackPanel Orientation="Horizontal" Margin="2"> <Image Name="icon" Source="/ExplorerTreeView/Images/folder.png"/> <TextBlock Text="{Binding Name}"/> </StackPanel> </Border> </HierarchicalDataTemplate> </TreeView.Resources> </TreeView> 



Decision

With the excellent Sheridan and Meleak answers, my TreeView now looks like this in code (as a result, I am very satisfied and pretty close to the Explorer style):

 <TreeView ... <TreeView.ItemContainerStyle> <Style TargetType="{x:Type TreeViewItem}"> <!-- Style for the selected item --> <Setter Property="BorderThickness" Value="1"/> <Style.Triggers> <!-- Selected and has focus --> <Trigger Property="IsSelected" Value="True"> <Setter Property="BorderBrush" Value="#7DA2CE"/> </Trigger> <!-- Mouse over --> <Trigger Property="helpers:TreeView_IsMouseDirectlyOverItem.IsMouseDirectlyOverItem" Value="True"> <Setter Property="Background"> <Setter.Value> <LinearGradientBrush EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="#FFFAFBFD" Offset="0"/> <GradientStop Color="#FFEBF3FD" Offset="1"/> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="BorderBrush" Value="#B8D6FB"/> </Trigger> <!-- Selected but does not have the focus --> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="True"/> <Condition Property="IsSelectionActive" Value="False"/> </MultiTrigger.Conditions> <Setter Property="BorderBrush" Value="#D9D9D9"/> </MultiTrigger> </Style.Triggers> <Style.Resources> <Style TargetType="Border"> <Setter Property="CornerRadius" Value="2"/> </Style> </Style.Resources> </Style> </TreeView.ItemContainerStyle> <TreeView.Resources> <HierarchicalDataTemplate DataType="{x:Type viewmodels:ObjectBaseViewModel}" ItemsSource="{Binding Children}"> <StackPanel Orientation="Horizontal" Margin="2,1,5,2"> <Grid Margin="0,0,3,0"> <Image Name="icon" Source="/ExplorerTreeView/Images/folder.png"/> </Grid> <TextBlock Text="{Binding Name}" /> </StackPanel> </HierarchicalDataTemplate> <!-- Brushes for the selected item --> <LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="#FFDCEBFC" Offset="0"/> <GradientStop Color="#FFC1DBFC" Offset="1"/> </LinearGradientBrush> <LinearGradientBrush x:Key="{x:Static SystemColors.ControlBrushKey}" EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="#FFF8F8F8" Offset="0"/> <GradientStop Color="#FFE5E5E5" Offset="1"/> </LinearGradientBrush> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" /> <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" /> </TreeView.Resources> </TreeView> 
+55
styles wpf xaml treeview selecteditem
Feb 18 '11 at 23:16
source share
3 answers

Adding to @Sheridan's answer
This is not 100% accurate, but should be pretty close (it uses colors from the GridView , which are pretty close to Windows Explorer)

enter image description here

 <TreeView ...> <TreeView.Resources> <LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="#FFD9F4FF" Offset="0"/> <GradientStop Color="#FF9BDDFB" Offset="1"/> </LinearGradientBrush> <LinearGradientBrush x:Key="{x:Static SystemColors.ControlBrushKey}" EndPoint="0,1" StartPoint="0,0"> <GradientStop Color="#FFEEEDED" Offset="0"/> <GradientStop Color="#FFDDDDDD" Offset="1"/> </LinearGradientBrush> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" /> <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" /> </TreeView.Resources> <TreeView.ItemContainerStyle> <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="BorderThickness" Value="1.5"/> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="BorderBrush" Value="#adc6e5"/> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="True"/> <Condition Property="IsSelectionActive" Value="False"/> </MultiTrigger.Conditions> <Setter Property="BorderBrush" Value="LightGray"/> </MultiTrigger> </Style.Triggers> <Style.Resources> <Style TargetType="Border"> <Setter Property="CornerRadius" Value="2"/> </Style> </Style.Resources> </Style> </TreeView.ItemContainerStyle> </TreeView> 
+39
Feb 19 2018-11-11T00:
source share

Add this to your TreeView.ContainerStyle to remove the default blue background.

 <Style.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" /> <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" /> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" /> <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" /> </Style.Resources> 

You can replace Black with any color that you want the text of your item and the text of the selected item to be.

To have a gray background if it is not focused, you can set up an β€œunfocused” Style with a gray backgorund and use EventTrigger for TreeViewItem.GotFocus and LostFocus to switch between Style c.

EDIT β†’>

If you want to be blinking, you can use the animation to change the background color by adding triggers to your ItemBorder Border directly to your HierarchicalDataTemplate , for example:

 <Border.Triggers> <EventTrigger RoutedEvent="Border.GotFocus"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <ColorAnimation Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="YourColour" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> <EventTrigger RoutedEvent="Border.LostFocus"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <ColorAnimation Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="LightGray" Duration="0:0:0.2" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Border.Triggers> 

Please note that this will only work if ColorAnimation is From . Since this code is worth it, the runtime will look for the SolidColorBrush set in the Border.Background property, so you must install it. You can directly set the ColorAnimation.From property.

+25
Feb 18 '11 at 23:22
source share

WindowsView Style TreeView (and ListView)

I originally looked for a way to apply a Windows 10 color scheme to a TreeViewItem, including

  • IsMouseOver for current item only
  • Windows 10 colors that WPF already applies to ListBox (not Windows Explorer)



If any of you are looking for exactly this, feel free to take the code below. I used the Helge Klein solution for the IsMouseOver problem and applied the colors of Windows 10 to XAML. Therefore, I propose this as a complement to the accepted answer.

Also see below the word on ListView and ComboBox .




Screenshot

example

App.xaml

 <Style TargetType="{x:Type TreeView}"> <Style.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#CBE8F6" /> <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="#F6F6F6" /> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" /> <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" /> </Style.Resources> </Style> <Style TargetType="{x:Type TreeViewItem}"> <Setter Property="BorderThickness" Value="1" /> <Style.Triggers> <Trigger Property="IsSelected" Value="True"> <Setter Property="BorderBrush" Value="#26A0DA" /> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="local:TreeViewItemHelper.IsMouseDirectlyOverItem" Value="True" /> <Condition Property="IsSelected" Value="False" /> </MultiTrigger.Conditions> <Setter Property="Background" Value="#E5F3FB" /> <Setter Property="BorderBrush" Value="#70C0E7" /> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="True" /> <Condition Property="IsSelectionActive" Value="False" /> </MultiTrigger.Conditions> <Setter Property="BorderBrush" Value="#DADADA" /> </MultiTrigger> </Style.Triggers> </Style> 

TreeViewItemHelper ( Source as published by Helge Klein, minor changes / simplification)

 public static class TreeViewItemHelper { private static TreeViewItem CurrentItem; private static readonly RoutedEvent UpdateOverItemEvent = EventManager.RegisterRoutedEvent("UpdateOverItem", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TreeViewItemHelper)); private static readonly DependencyPropertyKey IsMouseDirectlyOverItemKey = DependencyProperty.RegisterAttachedReadOnly("IsMouseDirectlyOverItem", typeof(bool), typeof(TreeViewItemHelper), new FrameworkPropertyMetadata(null, new CoerceValueCallback(CalculateIsMouseDirectlyOverItem))); public static readonly DependencyProperty IsMouseDirectlyOverItemProperty = IsMouseDirectlyOverItemKey.DependencyProperty; static TreeViewItemHelper() { EventManager.RegisterClassHandler(typeof(TreeViewItem), UIElement.MouseEnterEvent, new MouseEventHandler(OnMouseTransition), true); EventManager.RegisterClassHandler(typeof(TreeViewItem), UIElement.MouseLeaveEvent, new MouseEventHandler(OnMouseTransition), true); EventManager.RegisterClassHandler(typeof(TreeViewItem), UpdateOverItemEvent, new RoutedEventHandler(OnUpdateOverItem)); } public static bool GetIsMouseDirectlyOverItem(DependencyObject obj) { return (bool)obj.GetValue(IsMouseDirectlyOverItemProperty); } private static object CalculateIsMouseDirectlyOverItem(DependencyObject item, object value) { return item == CurrentItem; } private static void OnUpdateOverItem(object sender, RoutedEventArgs e) { CurrentItem = sender as TreeViewItem; CurrentItem.InvalidateProperty(IsMouseDirectlyOverItemProperty); e.Handled = true; } private static void OnMouseTransition(object sender, MouseEventArgs e) { lock (IsMouseDirectlyOverItemProperty) { if (CurrentItem != null) { DependencyObject oldItem = CurrentItem; CurrentItem = null; oldItem.InvalidateProperty(IsMouseDirectlyOverItemProperty); } Mouse.DirectlyOver?.RaiseEvent(new RoutedEventArgs(UpdateOverItemEvent)); } } } 

ListBox / ListView and ComboBox: On Windows 7 (and 8?), This will cause the design from TreeView to ListBox / ListView and ComboBox to be different. Therefore, if you want to apply this color scheme to these types of controls, also use this:

 <Style TargetType="{x:Type ListBoxItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Border Name="Border" BorderThickness="1" Background="Transparent"> <ContentPresenter /> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="Border" Property="Background" Value="#E5F3FB" /> <Setter TargetName="Border" Property="BorderBrush" Value="#70C0E7" /> </Trigger> <Trigger Property="IsSelected" Value="True"> <Setter TargetName="Border" Property="Background" Value="#CBE8F6" /> <Setter TargetName="Border" Property="BorderBrush" Value="#26A0DA" /> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsSelected" Value="True" /> <Condition Property="Selector.IsSelectionActive" Value="False" /> </MultiTrigger.Conditions> <Setter TargetName="Border" Property="Background" Value="#F6F6F6" /> <Setter TargetName="Border" Property="BorderBrush" Value="#DADADA" /> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}" /> <Style TargetType="{x:Type ComboBoxItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ComboBoxItem}"> <Border Name="Border" BorderThickness="1" Padding="1" Background="Transparent"> <ContentPresenter /> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="Border" Property="Background" Value="#E5F3FB" /> <Setter TargetName="Border" Property="BorderBrush" Value="#70C0E7" /> </Trigger> <Trigger Property="IsSelected" Value="True"> <Setter TargetName="Border" Property="Background" Value="#CBE8F6" /> <Setter TargetName="Border" Property="BorderBrush" Value="#26A0DA" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> 
0
Dec 27 '16 at 2:55
source share



All Articles