Adding images to a Tree View in WPF using C#

Like I’ve said before, once you find what your looking for, it is wasy to find examples about how to use and implement it. I had this again while trying to add images to a treeview. The term I was looking for, while trying to find a solution was ValueConverter. In this solution I will use a ValueConveter to convert a treeview header to an image. It is really quit simple to do this. It was hard to find the solution than it was to implement the solution. I think this is most always the case. Using my previous example of a treeview class, let make a few quick changes to add some images. The end result will look like this.

image

Let’s modify the treeview model first by adding a Boolean to the properties called IsRoot.

public bool IsRoot { get; private set; } 

I was it to be readable from everywhere, but I only want it set from within the class. therefore I made the property pubilc but made the setter private. This is because I can’t think of a reason this value should be changed after the creation of the treeview has been completed. I also modified the constructor by defaulting the IsRoot property to false.

TreeViewModel(string name)
{
   Name = name;
   Children = new List<TreeViewModel>();
   IsRoot = false;
}

The final thing I did in my treeview model class was to set the IsRoot value to true where a treeview item had children. For example:

tv.IsRoot = true;
tvChild4.IsRoot = true;
grtGrdChild2.IsRoot = true;

The next step is to create a new class that converts the treeview header into an image. This class needs to implement the IValueConverter which requires that we implement a Convert and ConvertBack method.

[ValueConversion(typeof(string), typeof(bool))]
public class HeaderToImageConverter : IValueConverter
{
  public static HeaderToImageConverter Instance =
          new HeaderToImageConverter();
 
  public object Convert(object value, Type targetType,
               object parameter, CultureInfo culture)
  {
   if (value is TreeViewModel)
   {
    TreeViewModel tvm = (TreeViewModel)value;
    if (tvm.IsRoot)
    {
      Uri uri = new Uri("pack://application:,,,/green.png");
      BitmapImage source = new BitmapImage(uri);
      return source;
     }
     else
     {
       Uri uri = new Uri("pack://application:,,,/blue.png");
       BitmapImage source = new BitmapImage(uri);
       return source;
      }
     }
     return null;
}
 
public object ConvertBack(object value, Type targetType,
                  object parameter, CultureInfo culture)
{
  throw new NotSupportedException("Cannot convert back");
}

The Convert method simply checks if the class being passed to the method is of type TreeViewModel, casts it and then checks the IsRoot Boolean value. Pretty simple.

The final step is to add the XAML code to the window.

<Image Name="img" Source="{Binding RelativeSource={RelativeSource
                Mode=FindAncestor,
                AncestorType={x:Type TreeViewItem}},
                         Path=Header,
                         Converter={x:Static
                 local:HeaderToImageConverter.Instance}}"/>

The above calls accesses the HeaderToImageConverter class via the static variable named Instance. During the binding of the treeview to the window, the convert method is called and the image is swapped for the header.

This was a pretty cool exercise. I suggest you download my source example that does not include the above and then try to add what I discussed here. Just as an exercise.

If you don’t want too, download it from here.

Download the source