Resolving harmless binding errors in WPF II : 2 approaches for removing data binding errors due to heterogeneous types in a hierarchical view

This is a continuation post to my previous post Resolving harmless binding errors in WPF in which I talked about various ways of  resolving different binding errors etc. I recently came across another situation in which we get these binding errors and how they can be resolved.

Problem: If you have a tree with 2 types of items in it and you use different DataTypes for each of them, then you will get binding errors because of missing Properties in either one of the item. In our case we had binding errors due to some items having an IsExpanded property and others not. The same was true of some other properties. (IsDeleted, ...).

This is a very common scenario as you might have different types deriving from a common base type and you want to show all of them in a single Tree.

Solution 1: MultiDataTrigger conditions according to type

We can add a converter to check the Data type as the first condition of a MultiDataTrigger. Further conditions won't be evaluated and hence there won't be binding errors if the type is incorrect...

public class DataTypeConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        ////string type = value.GetType().ToString();
        return value != null ? value.GetType() : null;
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
<MultiDataTrigger.Conditions>
   <Condition 
       Binding="{Binding Converter={StaticResource DataTypeConverter}}" 
       Value="SpecialType" />
   <Condition 
       Binding="{Binding Path=”IsDeleted"
       Value="true" />
</MultiDataTrigger.Conditions>

Solution 2: StyleSelector (different style for different tree nodes)

We can create a style selector and tell the tree to use the StyleSelector for items in the tree:

namespace StyleSelectors
{
    public class TreeViewItemStyleSelector : StyleSelector
    {
        public Style SpecialItemStyle
        {
            get;
            set;
        }
 
        public Style DefaultItemStyle
        {
            get;
            set;
        }
 
        public override Style SelectStyle(object item, DependencyObject container)
        {
            // Choose your test
            bool isSpecialItem = item is SpecialItem;
 
            if (isSpecialItem)
            {
                return SpecialItemStyle;
            }
            else
            {
                return DefaultItemStyle;
            }
        }
    }
}

Then we set one of these as the ItemContainerStyleSelector:

<StyleSelectors:TreeViewItemStyleSelector
   x:Key="TreeViewItemStyleSelector"
   DefaultItemStyle="{StaticResource DefaultItemStyle}"
   ScenarioRecordItemStyle="{StaticResource SpecialItemStyle}" />
<TreeView 
   Name="treeViewSmall"
   MinHeight="40"
   BorderThickness="1"
   DockPanel.Dock="Top"
   Grid.IsSharedSizeScope="true"
   ItemContainerStyleSelector="{StaticResource TreeViewItemStyleSelector}"
   ItemsSource="{Binding ItemSource}">
   <TreeView.Resources>
      <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Green" />
   </TreeView.Resources>
</TreeView>

Using any of these solutions will make sure that there are no binding errors in your output window and don’t have any impact on the performance of your application.

- akjoshi

2 Comments

Add a Comment

As it will appear on the website

Not displayed

Your website