locked
Vista style look for Treeview and Listview selected item RRS feed

  • Question

  • Hi all,

    I am trying in vain to get a Vista style look for Treeview and Listview selected item. You know, the selected item will have a gradient background (easy to do) and also a 1 pixel width rounded border (difficult part for me).

    I have pasted some XAML below, which doesn't quite work. I am not even sure that this approach is correct. I have highlighted some numbers in the sample code below, wondering whether they could be supplied dynamically via binding, in which case this may work. You can see the commented out binding code, which I tried and failed.

    I also tried using a DrawingBrush, but since it seems to kind of use relativetoboundingbox units (I think), I am not able to get the 1 pixel border around the selection (specifying Pen thickness for the GeometryDrawing as 0.1 or 0.01 is highly inaccurate to get a clean 1 pixel border around varied length treeview items).

    I request for help with this, including some sample code for both Listview and Treeview selection. Of course the next step for me would be to get the deselected look (grayish gradient background), and probably the mouse hover effect also:) Thanks in advance. Hafeez.



    VisualBrush sample:

    <Page
      xmlns="
    http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="
    http://schemas.microsoft.com/winfx/2006/xaml" SnapsToDevicePixels="True">

      <Page.Resources>
        <Style TargetType="{x:Type TreeViewItem}">
        <Style.Resources>
         
        <VisualBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Viewport="0,0,55,22" ViewportUnits="Absolute" Stretch="None">
          <VisualBrush.Visual>
    <!-- {Binding Path=ActualWidth, ElementName=TreeViewItem, Mode=Default} -->
            <Border BorderBrush="{x:Static SystemColors.HighlightBrush}" Background="Transparent" BorderThickness="1px" CornerRadius="3,3,3,3" Width="53" Height="22" Opacity=".5">
              <Border BorderBrush="White" BorderThickness="1px" CornerRadius="3,3,3,3" Width="51" Height="20">
                <Border.Background>
                  <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" Opacity=".5">
                    <GradientStop Color="{x:Static SystemColors.WindowColor}" Offset="0"/>
                    <GradientStop Color="{x:Static SystemColors.HighlightColor}" Offset="1"/>
                  </LinearGradientBrush>
                </Border.Background>
              </Border>
            </Border>
          </VisualBrush.Visual>
        </VisualBrush>
         
          <Brush x:Key="{x:Static SystemColors.ControlBrushKey}">LightGreen</Brush>
          <Brush x:Key="{x:Static SystemColors.HighlightTextBrushKey}">Black</Brush>
        </Style.Resources>

          <Setter Property="HeaderTemplate">
            <Setter.Value>
              <DataTemplate>
                <StackPanel Orientation="Horizontal" Height="22">
                  <Ellipse Width="11" Fill="Blue" Height="11" Margin="5,0,0,0" />
                  <TextBlock Text="{Binding}" Margin="5,0" VerticalAlignment="Center" Padding="5,0,15,0" />
                </StackPanel>
              </DataTemplate>
            </Setter.Value>
          </Setter>
        </Style>

      </Page.Resources>


    <Grid Margin="10,10,10,10">
      <Grid.RowDefinitions>
        <RowDefinition />
      </Grid.RowDefinitions>

      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
      </Grid.ColumnDefinitions>

      <TreeView Grid.Row="0" Grid.Column="0">
        <TreeViewItem Header="Foo">
          <TreeViewItem Header="Bar"/>
        </TreeViewItem>

        <TreeViewItem Header="This is a long text">
          <TreeViewItem Header="A"/>
        </TreeViewItem>
      </TreeView>
    </Grid>

    </Page>


    Tuesday, July 8, 2008 3:56 PM

Answers

  • I get this working properly without using VisualBrush, VisualBrush could be trickier and will resort to some performance, I think if you want to change the visual look of TreeViewItem, you'd better completely redefine TreeViewItem's control template, I have a working example as follows:

    <Page
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Page.Resources>
            <Style x:Key="TreeViewItemFocusVisual">
                <Setter Property="Control.Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Rectangle/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
           
            <Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
                <Setter Property="Focusable" Value="False"/>
                <Setter Property="Width" Value="19"/>
                <Setter Property="Height" Value="13"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ToggleButton}">
                            <Border Width="19" Height="13" Background="Transparent">
                                <Border Width="9" Height="9" SnapsToDevicePixels="true" BorderBrush="#FF7898B5" BorderThickness="1" CornerRadius="1">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1,1" StartPoint="0,0">
                                            <GradientStop Color="White" Offset=".2"/>
                                            <GradientStop Color="#FFC0B7A6" Offset="1"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                    <Path Fill="Black" Margin="1,1,1,1" x:Name="ExpandPath" Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/>
                                </Border>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="True">
                                    <Setter Property="Data" TargetName="ExpandPath" Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
           
            <Style TargetType="{x:Type TreeViewItem}">
                <Style.Resources>
                    <Brush x:Key="{x:Static SystemColors.ControlBrushKey}">LightGreen</Brush>
                    <Brush x:Key="{x:Static SystemColors.HighlightTextBrushKey}">Black</Brush>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" Opacity=".5" x:Key="backBrush">
                        <GradientStop Color="{x:Static SystemColors.WindowColor}" Offset="0"/>
                        <GradientStop Color="{x:Static SystemColors.HighlightColor}" Offset="1"/>
                    </LinearGradientBrush>
                </Style.Resources>
                <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="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <ToggleButton
                                    x:Name="Expander"
                                    Style="{StaticResource ExpandCollapseToggleStyle}"
                                    ClickMode="Press"
                                    IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"/>
                                <Border
                                    x:Name="Bd"
                                    SnapsToDevicePixels="true"
                                    Grid.Column="1"
                                    CornerRadius="3"
                                    Background="{TemplateBinding Background}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}"
                                    Padding="{TemplateBinding Padding}">
                                    <Border
                                        BorderBrush="White"
                                        CornerRadius="3"
                                        x:Name="innerBorder">
                                        <ContentPresenter
                                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                            x:Name="PART_Header"
                                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                            ContentSource="Header"/>
                                    </Border>
                                </Border>
                                <ItemsPresenter x:Name="ItemsHost" Grid.Column="1" Grid.ColumnSpan="2" 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="Hidden"/>
                                </Trigger>
                                <Trigger Property="IsSelected" Value="true">
                                    <Setter Property="Background" TargetName="Bd" Value="{StaticResource backBrush}"/>
                                    <Setter Property="BorderThickness" TargetName="Bd" Value="1"/>
                                    <Setter Property="BorderThickness" TargetName="innerBorder" Value="1"/>
                                    <Setter Property="BorderBrush" 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.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>
                <Setter Property="HeaderTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" Height="22">
                                <Ellipse
                                    Width="11"
                                    Fill="Blue"
                                    Height="11"
                                    Margin="5,0,0,0" />
                                <TextBlock
                                    Text="{Binding}"
                                    Margin="5,0"
                                    VerticalAlignment="Center"/>
                            </StackPanel>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
       
        </Page.Resources>
        <Grid Margin="10,10,10,10">
            <Grid.RowDefinitions>
                <RowDefinition />
            </Grid.RowDefinitions>
           
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
           
            <TreeView Grid.Row="0" Grid.Column="0" SnapsToDevicePixels="True">
                <TreeViewItem Header="Foo">
                    <TreeViewItem Header="Bar"/>
                </TreeViewItem>
               
                <TreeViewItem Header="This is a long text">
                    <TreeViewItem Header="A"/>
                </TreeViewItem>
            </TreeView>
        </Grid>

    </Page>

    Hope the above sample should shed some light on how to restyle the TreeViewItem.

    Thanks
    • Marked as answer by Marco Zhou Monday, July 14, 2008 11:00 AM
    Friday, July 11, 2008 8:21 AM

All replies

  • I get this working properly without using VisualBrush, VisualBrush could be trickier and will resort to some performance, I think if you want to change the visual look of TreeViewItem, you'd better completely redefine TreeViewItem's control template, I have a working example as follows:

    <Page
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Page.Resources>
            <Style x:Key="TreeViewItemFocusVisual">
                <Setter Property="Control.Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Rectangle/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
           
            <Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
                <Setter Property="Focusable" Value="False"/>
                <Setter Property="Width" Value="19"/>
                <Setter Property="Height" Value="13"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ToggleButton}">
                            <Border Width="19" Height="13" Background="Transparent">
                                <Border Width="9" Height="9" SnapsToDevicePixels="true" BorderBrush="#FF7898B5" BorderThickness="1" CornerRadius="1">
                                    <Border.Background>
                                        <LinearGradientBrush EndPoint="1,1" StartPoint="0,0">
                                            <GradientStop Color="White" Offset=".2"/>
                                            <GradientStop Color="#FFC0B7A6" Offset="1"/>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                    <Path Fill="Black" Margin="1,1,1,1" x:Name="ExpandPath" Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/>
                                </Border>
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="True">
                                    <Setter Property="Data" TargetName="ExpandPath" Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
           
            <Style TargetType="{x:Type TreeViewItem}">
                <Style.Resources>
                    <Brush x:Key="{x:Static SystemColors.ControlBrushKey}">LightGreen</Brush>
                    <Brush x:Key="{x:Static SystemColors.HighlightTextBrushKey}">Black</Brush>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" Opacity=".5" x:Key="backBrush">
                        <GradientStop Color="{x:Static SystemColors.WindowColor}" Offset="0"/>
                        <GradientStop Color="{x:Static SystemColors.HighlightColor}" Offset="1"/>
                    </LinearGradientBrush>
                </Style.Resources>
                <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="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <ToggleButton
                                    x:Name="Expander"
                                    Style="{StaticResource ExpandCollapseToggleStyle}"
                                    ClickMode="Press"
                                    IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"/>
                                <Border
                                    x:Name="Bd"
                                    SnapsToDevicePixels="true"
                                    Grid.Column="1"
                                    CornerRadius="3"
                                    Background="{TemplateBinding Background}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}"
                                    Padding="{TemplateBinding Padding}">
                                    <Border
                                        BorderBrush="White"
                                        CornerRadius="3"
                                        x:Name="innerBorder">
                                        <ContentPresenter
                                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                            x:Name="PART_Header"
                                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                            ContentSource="Header"/>
                                    </Border>
                                </Border>
                                <ItemsPresenter x:Name="ItemsHost" Grid.Column="1" Grid.ColumnSpan="2" 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="Hidden"/>
                                </Trigger>
                                <Trigger Property="IsSelected" Value="true">
                                    <Setter Property="Background" TargetName="Bd" Value="{StaticResource backBrush}"/>
                                    <Setter Property="BorderThickness" TargetName="Bd" Value="1"/>
                                    <Setter Property="BorderThickness" TargetName="innerBorder" Value="1"/>
                                    <Setter Property="BorderBrush" 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.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>
                <Setter Property="HeaderTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" Height="22">
                                <Ellipse
                                    Width="11"
                                    Fill="Blue"
                                    Height="11"
                                    Margin="5,0,0,0" />
                                <TextBlock
                                    Text="{Binding}"
                                    Margin="5,0"
                                    VerticalAlignment="Center"/>
                            </StackPanel>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
       
        </Page.Resources>
        <Grid Margin="10,10,10,10">
            <Grid.RowDefinitions>
                <RowDefinition />
            </Grid.RowDefinitions>
           
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
           
            <TreeView Grid.Row="0" Grid.Column="0" SnapsToDevicePixels="True">
                <TreeViewItem Header="Foo">
                    <TreeViewItem Header="Bar"/>
                </TreeViewItem>
               
                <TreeViewItem Header="This is a long text">
                    <TreeViewItem Header="A"/>
                </TreeViewItem>
            </TreeView>
        </Grid>

    </Page>

    Hope the above sample should shed some light on how to restyle the TreeViewItem.

    Thanks
    • Marked as answer by Marco Zhou Monday, July 14, 2008 11:00 AM
    Friday, July 11, 2008 8:21 AM
  • Wow! Thanks, really:)

    Regards,
    Hafeez
    Sunday, July 13, 2008 8:59 PM