views:

648

answers:

1

Hello,

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 :-)

A: 

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>
Pavel Minaev
Thanks for the quick reply! The problem is only that i want to add different controls into a stack panel depending on the type in the items collection. How would you solve that?So as <DataTemplate> if have a <StackPanel> that should have added different control object depending on the type in the ItemsCollection..
franklyn
Then just bind the `ItemTemplate` property using `TypeSwitchConverter` above to different templates.
Pavel Minaev
Actually, sorry, a slight correction - you won't be able to bind it directly because you won't have a current item when setting `ItemTemplate`. So you define an `ItemTemplate` containing a single element of any type (e.g. `ContentPresenter`), and then bind `Template` property of that element using a switch converter.
Pavel Minaev