Search code examples
c#wpfmvvmdatagrid

WPF DataGrid: Making the column type dynamic for every row


I have a WPF DataGrid. In one column I currently show a ComboBox with values of an enum. The code looks like this:

<DataGridTemplateColumn Header="Solution">
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
             <ComboBox ItemsSource="{utils:Enumerate {x:Type EnumSolution}}" SelectedItem="{Binding Solution, Converter={StaticResource EnumToStringConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        </DataTemplate>
   </DataGridTemplateColumn.CellEditingTemplate>
   <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
             <ComboBox ItemsSource="{utils:Enumerate {x:Type EnumSolution}}" SelectedItem="{Binding Solution, Converter={StaticResource EnumToStringConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

But I do not want to display the ComboBox for all rows. I only want to display it for specific rows and just a text for the other rows. Is that possible like this:

screenshot datagrid


Solution

  • You can use CellTemplateSelector.

    First create a class that represents your selector - the logic what template to choose when:

    public class MyCellTemplateSelector : DataTemplateSelector
    {
        public DataTemplate SolutionTextBlockTemplate { get; set; }
        public DataTemplate SolutionComboboxTemplate { get; set; }
    
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            var diff = item as YourDatGridRowObjectType;
            if(diff != null)
            {
                if (<your condition on when to choose this template>))
                    return SolutionTextBlockTemplate;
                return SolutionComboboxTemplate;
            }
            return null;
        }        
    }
    

    In the control that contains the DataGrid you define the resources for that - how the templates actually look like:

    <Window.Resources>
        <DataTemplate x:Key="SolutionTextBlockTemplate">
            <TextBlock Text="{Binding Solution}" />
        </DataTemplate>
        <DataTemplate x:Key="SolutionComboBoxTemplate">
            <ComboBox ItemsSource="{utils:Enumerate {x:Type connectToEcomp:EnumSolution}}" SelectedItem="{Binding Solution, Converter={StaticResource EnumToStringConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        </DataTemplate> 
    </Window.Resources>
    

    In the DataGrid itself you use those templates like this:

    <DataGridTemplateColumn Header="Solution" >
        <DataGridTemplateColumn.CellTemplateSelector>
            <local:MyCellTemplateSelector 
                 SolutionTextBlockTemplate="{StaticResource SolutionTextBlockTemplate}" 
                 SolutionComboboxTemplate="{StaticResource SolutionComboBoxTemplate}" />
        </DataGridTemplateColumn.CellTemplateSelector>  
    </DataGridTemplateColumn>