Search code examples
wpfdatagridtoolkit

Different cell styling in a wpf datagrid depending on datatype in the ItemsSource


I am wondering if it was possible to change the styling of a column in a wpf datagrid depending on the type of item in the ItemsSource collection.

I have a wpf datagrid from the wpf toolkit. The single rows in the grid should be styled depending of the type of item from the ItemsSource collection. So all items are of the same base class type but the columns of some derived types should get a different stylization.

Is this possible?

Thank you :-)


Solution

  • Yes, it is possible to do it in several ways. The one I would go for is writing your own custom "typeswitch" converter that selects a value depending on type of input. Like this:

    public class TypeSwitchConverter : Dictionary<Type, object>, IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, .CultureInfo culture)
        {
            foreach (var mapping in this)
            {
                if (mapping.Key.IsAssignableFrom(value.GetType()))
                {
                    return mapping.Value;
                }
            }
    
            return null;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    And then use a binding for the Style of the top-level element in template for your cell, and use the above converter for that binding as needed. Here's a simplified example that styles items in a ListBox using it:

        <ListBox ItemsSource="{Binding}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}">
                        <TextBlock.Style>
                            <Binding>
                                <Binding.Converter>
                                    <my:TypeSwitchConverter>
                                        <Style x:Key="{x:Type cor:Int32}" TargetType="{x:Type TextBlock}">
                                            <Setter Property="Background" Value="Red" />
                                        </Style>
                                        <Style x:Key="{x:Type cor:String}" TargetType="{x:Type TextBlock}">
                                            <Setter Property="Background" Value="Green" />
                                        </Style>
                                        <Style x:Key="{x:Type sys:Uri}" TargetType="{x:Type TextBlock}">
                                            <Setter Property="Background" Value="Blue" />
                                        </Style>
                                    </my:TypeSwitchConverter>
                                </Binding.Converter>
                            </Binding>
                        </TextBlock.Style>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>