c# - WPF 中的数据模板

标签 c# wpf mvvm datatemplate

我有一个关于 WPF 中的数据模板的一般性问题。假设我有一个名为“Question”的抽象类和各种子类,如“MathQuestion”、“GeographyQuestion”等。在某些情况下,使用“Question”数据模板将问题呈现为“Question”就足够了,但是假设我有一个我想依次显示的不同子类的随机 Question 对象列表。我想使用他们的特定数据模板而不是他们的通用问题数据模板将它们显示给用户,但由于我不知道在设计时,是否可以告诉 WPF,“嘿,这是一个问题列表,但是使用反射来找出它们的特定类型并使用那个数据模板?”

到目前为止我想到了什么:我认为除了我的问题集合之外,我还可以使用反射创建另一个特定类型的集合并以某种方式将其绑定(bind)到“blah”,然后我会得到想要的影响,但您只能绑定(bind)到 WPF 中的 DependencyProperties,所以我不确定我要绑定(bind)到什么。我真的不喜欢这个想法,我的直觉告诉我有一种更优雅的方法来解决这个问题。

我不是在寻找特定的代码,只是为了完成我正在尝试做的事情的一般策略。另外,如果有帮助的话,我大部分时间都在使用 MVVM。

谢谢

最佳答案

我认为像这样的东西应该开箱即用:

<UserControl.Resources>
    <DataTemplate DataType="{x:Type vm:GenericQuestionViewModel}">
        <v:GenericQuestion/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type tvm:GeographyQuestionViewModel}">
        <tv:GeographyQuestion/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type tvm:BiologyQuestionViewModel}">
        <tv:BiologyQuestion/>
    </DataTemplate>
</UserControl.Resources>

<ContentControl Content="{Binding QuestionViewModel}">

编辑:

是的,这绝对应该有效。这是一个更完整的示例:

主视图模型

public class MainWindowViewModel : ViewModelBase
{
    public ObservableCollection<QuestionViewModel> QuestionViewModels { get; set; }

    public MainWindowViewModel()
    {
        QuestionViewModels = new ObservableCollection<QuestionViewModel>
        {
            new GenericQuestionViewModel(),
            new GeographyQuestionViewModel(),
            new BiologyQuestionViewModel()
        };
    }
}

问题 View 模型

public abstract class QuestionViewModel : ViewModelBase
{
}

public class GenericQuestionViewModel : QuestionViewModel
{
}

public class GeographyQuestionViewModel : QuestionViewModel
{
}

public class BiologyQuestionViewModel : QuestionViewModel
{
}

质疑用户控制

<UserControl x:Class="WpfApplication1.GenericQuestion" ...>
    <Grid>
        <TextBlock Text="Generic Question" />
    </Grid>
</UserControl>

<UserControl x:Class="WpfApplication1.GeographyQuestion" ...>
    <Grid>
        <TextBlock Text="Geography Question" />
    </Grid>
</UserControl>

<UserControl x:Class="WpfApplication1.BiologyQuestion" ...>
    <Grid>
        <TextBlock Text="Biology Question" />
    </Grid>
</UserControl>

主窗口

<Window x:Class="WpfApplication1.MainWindow" ...
        Title="MainWindow"
        Height="900"
        Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:GenericQuestionViewModel}">
            <local:GenericQuestion />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:GeographyQuestionViewModel}">
            <local:GeographyQuestion />
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:BiologyQuestionViewModel}">
            <local:BiologyQuestion />
        </DataTemplate>
    </Window.Resources>
    <ItemsControl ItemsSource="{Binding QuestionViewModels}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <ContentControl Content="{Binding}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Window>

更新

Kyle Tolle 指出了设置 ItemsControl.ItemTemplate 的一个很好的简化。这是结果代码:

<ItemsControl ItemsSource="{Binding QuestionViewModels}"
              ItemTemplate="{Binding}" /> 

关于c# - WPF 中的数据模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9133389/

相关文章:

java - 片段之间的导航出现问题

c# - 在接口(interface)中实现接口(interface)属性?

c# - GroupItem中的Datagrid “Addrow”

c# - 有人得到了 C# MVC 的出生日期验证属性吗?

javascript - 如何在asp gridview中使用<EmptyDataTemplate>

c# - 隐藏 WPF 窗口中的所有按钮

c# - WPF slider ValueChanged 事件的频率

c# - 如何在 C# 中序列化一个对象数组?

c# - Recursive Hierarchy - 使用 Linq 的递归查询

c# - 从 WPF 客户端访问安全的 Web API