0
votes

This question is related to the accepted answer in my question: Dynamic content in DataGrid or GridView CellTemplate

I have a collection of different datatypes to the ItemSource of the DataGrid, and depending on the datatype of the current index in the DataSignalModel collection, the corresponding DataType is to be used.

This the solution that helped me in the linked question:

As you store a data type member instead of creating two distinct model types, you will have to create a custom DataTemplateSelector for selecting the data template depending on DataType.

public class DataSignalModelTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (!(item is SignalDisplayModel dataSignalModel) || !(container is FrameworkElement containerFrameworkElement))
            return null;

        switch (dataSignalModel.DataType)
        {
            case DataType.Bool:
                return FindDataTemplate(containerFrameworkElement, "DataSignalModelBoolTemplate");
            case DataType.Int:
            case DataType.Float:
                return FindDataTemplate(containerFrameworkElement, "DataSignalModelNumericTemplate");
            default:
                throw new ArgumentOutOfRangeException();
        }
    }

    private static DataTemplate FindDataTemplate(FrameworkElement frameworkElement, string key)
    {
        return (DataTemplate)frameworkElement.FindResource(key);
    }
}

And I want to follow the advice below.

A note on data types: You keep a member DataType in your DataSignalModel to determine its type. Usually you would create specialized types for each data and not a one-for-all mode

So when I change my design to have an interface or base class and concrete implementation of the different types, how do I adapt my current solution to use the different DataTemplate's?

  • Get rid of the custom DataTemplateSelector and somehow bind the different DataTemplates to the corresponding IDataSignalModel implementations?
  • Adapt the custom DataTemplateSelector to return the DataTemplate on item type?
  • Or maybe a different approach?
1
Not sure why you think you would even need a common interface or a DataTemplateSelector. You could put instances or arbitrary classes into an ObservableCollection<object> used as ItemsSource. Then have DataTemplates with appropriate DataTypes for all types you need.Clemens

1 Answers

0
votes

As said in the previous answer, you would create distinct types for your data, e.g.:

public class BoolDataSignalModel: INotifyPropertyChanged
{
   // ...
}
public class IntDataSignalModel: INotifyPropertyChanged
{
   // ...
}

Just create as many models as you need. They do not necessarily have to share a common base type, it does not matter for data templating. I guess your data collection is still exposed like this:

public IList<DataSignalModel> DataSignalsList
{
   get { return _dataSignalsList; }
   set { _dataSignalsList = value; }
}

If you do not change your collection at runtime this is alright, otherwise use ObservableCollection<T>. Now, define a data template for each model in XAML with the DataType set to your model type, e.g.:

<DataTemplate DataType="{x:Type local:BoolDataSignalModel}">
   <StackPanel Orientation="Horizontal" Margin="5">
      <Button Content="Click Me" FontSize="10" Height="18"/>
   </StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:IntDataSignalModel}">
   <StackPanel Orientation="Horizontal">
      <TextBlock Text="0" Margin="10 5 10 5"/>
      <Slider Value="50" Minimum="0" Maximum="100" MinWidth="150"/>
      <TextBlock Text="100" Margin="10 5 10 5"/>
   </StackPanel>
</DataTemplate>

Please note, that you do not define an x:Key, otherwise it will not work. If you put these data templates in a resource dictionary in scope of the items control that you bound your collection to, it will automatically select the appropriate data template based on the item type. No need for a data template selector or a base class.

For more information, refer to Data Templating Overview.