wpfxamlconditional-statementsdatagriddatatemplate

WPF XAML DataGridTemplateColumn assign to two DataTemplate with conditional types


Struggling with the great WPF and XAML, I found lots of info, e.g. this SO question, on how to use multiple DataTemplates with a data type condition, but I don't know how to connect those to a DataGrid column.

For example, to display data from class Material differently from class Usage, each with a Value field, here are two DataTemplates as suggested by the post linked above:

    <Grid.Resources>
        <!-- Do NOT set the x:Key -->
        <DataTemplate DataType="{x:Type models:Material}">
            <TextBlock Text="{Binding Value}" 
                Foreground="White"
                Background="Gray"
            />
        </DataTemplate>
        <DataTemplate DataType="{x:Type models:Usage}">
            <TextBlock Text="{Binding Value}"  
                Foreground="White"
                Background="Brown"
            />
        </DataTemplate>

This should be used in a DataGrid like this:

<DataGridTemplateColumn CellTemplate="{StaticResource MyTemplate}">

The post I referenced above indicates that I should NOT use the Key property on the DataTemplates. If I would, the Key should be unique, hence different on each DataTemplates, while BOTH templates should connect to the same DataGrid Column.

I have not found an element to group several DataTemplates in order to give them a collective resource name.

I am also seeing examples with in code-behind a C# class implementing a DataTemplateSelector, but that would be contrary to the DataType property in XAML to do the selection.

I could not yet find an XAML example showing the solution to this problem. Any help is greatly appreciated.


Solution

  • Since you are using the type to bind to the DataTemplate via resouces, you just need to supply an empty element to relay that binding. In this case I used a ContentControl, but pretty much any other content control element will work (i.e. ContentPresenter, Button, etc).

    I think the example below generated what you are looking for:

    <Grid.Resources>
        <DataTemplate DataType="{x:Type models:Usage}">
            <TextBlock Text="{Binding Value}" Foreground="White" Background="Gray" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type models:Material}">
            <TextBlock Text="{Binding Value}" Foreground="White" Background="Brown" />
        </DataTemplate>
    </Grid.Resources>
    
    <DataGrid ItemsSource="{Binding Data}" AutoGenerateColumns="False" CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Values">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentControl Content="{Binding}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    

    Result

    Result