0

I have a datagrid populated from a viewmodel, I want to use Template selector based on the viewmodels property (basic template selector using a boolean field to decide which template is needed)

public class CarViewModel : INotifyPropertyChanged
{
    private bool _isElectric;

    public bool IsElectric
    {
        get => _isElectric;
        set
        {
            if (_isElectric != value)
            {
                _isElectric = value;
                OnPropertyChanged(nameof(IsElectric));
            }
        }
    }

    public string Model { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
public class CarTemplateSelector : DataTemplateSelector
{
    public DataTemplate ElectricCarTemplate { get; set; }
    public DataTemplate GasCarTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var car = item as CarViewModel;
        if (car == null) return base.SelectTemplate(item, container);

        return car.IsElectric ? ElectricCarTemplate : GasCarTemplate;
    }
}
 <Window.Resources>
        <!-- Define the DataTemplates -->
        <DataTemplate x:Key="ElectricCarTemplate">
            <TextBlock Text="{Binding Model}" Foreground="Green"/>
        </DataTemplate>

        <DataTemplate x:Key="GasCarTemplate">
            <TextBlock Text="{Binding Model}" Foreground="Red"/>
        </DataTemplate>

        <!-- Define the DataTemplateSelector -->
        <local:CarTemplateSelector x:Key="CarTemplateSelector"
                                   ElectricCarTemplate="{StaticResource ElectricCarTemplate}"
                                   GasCarTemplate="{StaticResource GasCarTemplate}"/>

how to use the template selector to decide what kind of cell it put into my datagrid?

 <controls:DataGrid ItemsSource="{x:Bind Items}">
     
     <controls:DataGrid.Columns>

         <controls:DataGridTemplateColumn  Header="Name"  Width="324">
             <controls:DataGridTemplateColumn.CellTemplate  >
                 <DataTemplate x:DataType="viewmodels:CarViewModel">
                     
                 </DataTemplate>
             </controls:DataGridTemplateColumn.CellTemplate>
         </controls:DataGridTemplateColumn>

        
     </controls:DataGrid.Columns>
 </controls:DataGrid>

tried searching for the datagrid properties and documentation, setting the ContentPresenter of the Datacontext but could not the get the CarViewModel value through

1 Answer 1

0

You can create your own DataGridTemplateColumn.

For example:

public class DataGridTemplateCellEx : CommunityToolkit.WinUI.UI.Controls.DataGridTemplateColumn
{
    public DataTemplateSelector? CellTemplateSelector { get; set; }

    protected override FrameworkElement? GenerateElement(DataGridCell cell, object dataItem)
    {
        if (CellTemplate is not null)
        {
            return CellTemplate.LoadContent() as FrameworkElement;
        }

        if (CellTemplateSelector is not null)
        {
            return CellTemplateSelector.SelectTemplate(dataItem).LoadContent() as FrameworkElement;
        }

        throw new NotSupportedException();
    }
}

Then use it like this:

<local:DataGridTemplateCellEx
    CellTemplateSelector="{StaticResource SomeCellTemplateSelector}"
    Header="Some Header" />
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer it works great when I use it with TextBlock as in the question, but for some reason If I want to use it with a combobox with an itemsource of ObservableCollection<string> it throws an exception: The type initializer for 'Missing template. Cannot initialize CommunityToolkit.WinUI.UI.Controls.DataGridTemplateColumn.' threw an exception.
Found Issue, GenerateEditingElement has to be overriden as well, thanks again for the answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.