问:我应该如何处理模型的数据模板?

Q: How should I handle Datatemplates for Models?

在 MVVM 模式中,视图不应该知道模型的任何信息,但是如果我想以不同的方式显示不同的类型怎么办?

例如我有两个 classes。 class Message 和继承自 Message.

的 class AttachmentMessage

留言

public class Message
{
    public string Content { get; set; }
}

附件消息

public class AttachmentMessage : Message
{
    public string Filename { get; set; }
}

现在当我在 ObservableCollection<Message> 中使用它们时,我在这个集合中有两个模型,但我无法告诉 WPF 它必须使用哪个数据模板,不知道有哪些模型。

那么这个问题的解决方案是什么?

最常见和推荐的方法是为您需要的每种类型创建一个数据模板并将其放入您的资源中。 以下代码假定您的可观察集合的名称为 Messages。 示例:

<ItemsControl ItemsSource="{Binding Messages}">
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:Message}">
            <TextBlock Text="{Binding Content}"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:AttachmentMessage}">
            <TextBlock Text="{Binding Filename}"/>
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

另一种方法是创建 DataTemplateSelector。假设您的消息都有一个 属性 表示它们的优先级。您可以创建如下所示的模板选择器。 DataTemplateSelector 可以在您需要更精细地控制选择哪个模板时使用。

public class MyDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is Message m && container is FrameworkElement fm)
        {
            if (m.Priority == Priority.High)
            {
                return fm.FindResource("HighPriorityTemplate") as DataTemplate;
            }
            else
            {
                return fm.FindResource("NormalPriorityTemplate") as DataTemplate;
            }
        }

        return null;
    }
}

并在 xaml 中使用它,如下所示:

<Window.Resources>
    <!-- Put your templates here-->
    <local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"/>
</Window.Resources>
<ItemsControl ItemsSource="{Binding Messages}" ItemTemplateSelector="{StaticResource MyDataTemplateSelector}">

正如我所说,在 MVVM 模式中,通常有三个部分,ModelViewViewModel。有些人采取直接绑定到 Model 的快捷方式,但我通常会避免这种情况。你可以找到关于这个的讨论 here.