Click here to Skip to main content
15,897,291 members
Articles / Desktop Programming / WPF

A Versatile TreeView for WPF

Rate me:
Please Sign up or sign in to vote.
4.95/5 (107 votes)
7 Feb 2008CPOL15 min read 642.7K   18.6K   303  
A strongly typed enhancement of the regular WPF TreeView control.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:Hardcodet.Wpf.Samples;assembly="
                    xmlns:vm="clr-namespace:Hardcodet.Wpf.Samples.ViewModel;assembly="
                    xmlns:shop="clr-namespace:SampleShop.Products;assembly="
                    xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase">
 
  
  <!-- a data template for bound ShopCategory instances -->
  <DataTemplate x:Key="CategoryTemplate"
                DataType="{x:Type shop:ShopCategory}">
    <StackPanel x:Name="GroupPanel"
                Orientation="Horizontal"
                Margin="0,2,0,2">
      <Image x:Name="Folder"
             Source="/Images/FolderClosed.png" />
      <TextBlock x:Name="CategoryName"
                 Margin="2,0,0,0"
                 Text="{Binding Path=CategoryName}" /> 
    </StackPanel>

    <DataTemplate.Triggers>
      <DataTrigger Binding="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
                   Value="True">
        <Setter Property="Source"
                TargetName="Folder"
                Value="/Images/FolderOpen.png" />
      </DataTrigger>

      <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource TemplatedParent}}"
                   Value="True">
        <Setter Property="Foreground"
                TargetName="CategoryName"
                Value="White" />
        <Setter Property="Source"
                TargetName="Folder"
                Value="/Images/FolderSelected.png" />
        <Setter Property="BitmapEffect">
          <Setter.Value>
            <OuterGlowBitmapEffect GlowColor="Black" />
          </Setter.Value>
        </Setter>
      </DataTrigger>
      
      <!-- custom icons for the root nodes -->
      <DataTrigger Binding="{Binding Path=Header.CategoryName, RelativeSource={RelativeSource TemplatedParent}}"
                   Value="Music">
        <Setter Property="Source"
                TargetName="Folder"
                Value="/Images/Music.png" />
      </DataTrigger>
      <DataTrigger Binding="{Binding Path=Header.CategoryName, RelativeSource={RelativeSource TemplatedParent}}"
                   Value="Movies">
        <Setter Property="Source"
                TargetName="Folder"
                Value="/Images/Movie.png" />
      </DataTrigger>
      <DataTrigger Binding="{Binding Path=Header.CategoryName, RelativeSource={RelativeSource TemplatedParent}}"
                   Value="Books">
        <Setter Property="Source"
                TargetName="Folder"
                Value="/Images/Book.png" />
      </DataTrigger>

    </DataTemplate.Triggers>
  </DataTemplate>


  <!-- this is the style that is applied to the tree -->
  <Style x:Key="SimpleFolders"
         TargetType="{x:Type TreeViewItem}">
    <Style.Resources>
      <!-- override default brushes that show bad background colors -->
      <Brush x:Key="{x:Static SystemColors.HighlightBrushKey}">Transparent</Brush>
      <Brush x:Key="{x:Static SystemColors.ControlBrushKey}">Transparent</Brush>
    </Style.Resources>
    <Setter Property="HeaderTemplate"
            Value="{StaticResource CategoryTemplate}" />
    <Style.Triggers>
    </Style.Triggers>
  </Style>
  
  <!-- 
    A default style for treeview controls. This one will automatically
    be applied as the custom tree's 'TreeStyle' property is not set.
  -->
  <Style x:Key="SimpleTreeStyle" TargetType="{x:Type TreeView}">
    <Setter Property="Background">
      <Setter.Value>
        <LinearGradientBrush EndPoint="0,1"
                             StartPoint="0,0">
          <GradientStop Color="#FFF"
                        Offset="0.0" />
          <GradientStop Color="#AAA"
                        Offset="1.0" />
        </LinearGradientBrush>
      </Setter.Value>
    </Setter>
    <Setter Property="BorderThickness"
            Value="4" />
    <Setter Property="BorderBrush"
            Value="#FFA6AAAB" />
  </Style> 
  
    
  <!-- the context menu for the tree -->
  <ContextMenu x:Key="CategoryMenu">
    <MenuItem Header="Add Subcategory"
              Command="New">
      <MenuItem.Icon>
        <Image Source="/Images/Add.png"
               Width="16"
               Height="16" />
      </MenuItem.Icon>
    </MenuItem>

    <MenuItem Header="Remove Category"
              Command="Delete">
      <MenuItem.Icon>
        <Image Source="/Images/Remove.png"
               Width="16"
               Height="16" />
      </MenuItem.Icon>
    </MenuItem>
    
  </ContextMenu>

  
  <!-- sorts categories by names in ascending order -->
  <cm:SortDescriptionCollection x:Key="AscendingNames">
    <cm:SortDescription PropertyName="Header.CategoryName"
                        Direction="Ascending" />
  </cm:SortDescriptionCollection>

  <!-- sorts categories by names in descending order -->
  <cm:SortDescriptionCollection x:Key="DescendingNames">
    <cm:SortDescription PropertyName="Header.CategoryName"
                        Direction="Descending" />
  </cm:SortDescriptionCollection>

  
  
  <!-- default text style -->
  <Style TargetType="TextBlock">
    <Setter Property="TextWrapping"
            Value="Wrap" />
  </Style>

  
  <!-- the background of the main window -->
  <LinearGradientBrush x:Key="WindowBrush"
                       EndPoint="0.5,1"
                       StartPoint="0.5,0">
    <GradientStop Color="#FFFAFAFA"
                  Offset="0.382" />
    <GradientStop Color="#FF405159"
                  Offset="0" />
    <GradientStop Color="#FF2D3539"
                  Offset="1" />
    <GradientStop Color="#FFDBDDDD"
                  Offset="0.592" />
    <GradientStop Color="#FFA6AAAB"
                  Offset="0.803" />
  </LinearGradientBrush>


  <!-- default style for hyperlinks -->
  <Style TargetType="{x:Type Hyperlink}">
    <Setter Property="Foreground"
            Value="#FFA72222" />
    <Setter Property="TextDecorations"
            Value="None" />
    <Setter Property="ToolTip"
            Value="Visit website" />
  </Style>

</ResourceDictionary>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect I'm a gun for hire
Switzerland Switzerland
Philipp is an independent software engineer with great love for all things .NET.
He lives in Winterthur, Switzerland and his home on the web is at http://www.hardcodet.net.

Comments and Discussions