将不同的 DataTemplate 绑定到接口实现

问题描述

此问题与我的问题中已接受的答案有关:Dynamic content in DataGrid or GridView CellTemplate

我对DataGrid的ItemSource有不同数据类型的集合,根据DataSignalModel集合中当前索引的数据类型,使用对应的DataType。

这是在链接问题中帮助我的解决方案:

当您存储一个数据类型成员而不是创建两个不同的模型类型时,您必须创建一个自定义 DataTemplateSelector 以根据 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);
    }
}

我想遵循以下建议。

关于数据类型的说明:您在 DataSignalModel 中保留一个成员 DataType 以确定其类型。通常你会为每个数据创建专门的类型,而不是一个单一的模式

因此,当我将设计更改为具有不同类型的接口或基类以及具体实现时,我该如何调整当前的解决方案以使用不同的 DataTemplate?

  • 摆脱自定义 DataTemplateSelector 并以某种方式将不同的 DataTemplate 绑定到相应的 IDataSignalModel 实现?
  • 调整自定义 DataTemplateSelector 以返回有关项目类型的 DataTemplate?
  • 或者可能采用不同的方法

解决方法

如上一个答案所述,您将为数据创建不同的类型,例如:

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

只需根据需要创建尽可能多的模型。它们不一定必须共享公共基类型,这对于数据模板无关紧要。我猜你的数据收集仍然是这样暴露的:

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

如果您在运行时不更改集合,这没关系,否则使用 ObservableCollection<T>。现在,为 XAML 中的每个模型定义一个数据模板,并将 DataType 设置为您的模型类型,例如:

<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>

请注意,您不要定义x:Key,否则它将无法工作。如果将这些数据模板放在您绑定集合的项目控件范围内的资源字典中,它将根据项目类型自动选择适当的数据模板。不需要数据模板选择器或基类。

有关详细信息,请参阅 Data Templating Overview