Search code examples
c#winui-3winuiwindows-community-toolkitwinui-xaml

How to use TemplateSelector for WinUI Datagrid


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


Solution

  • 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" />