WPF中的DataTemplates

Qua*_*nta 6 c# wpf datatemplate mvvm

我对WPF中的数据模板有一般性问题.假设我有一个名为"问题"的抽象类,以及各种子类,如"MathQuestion","GeographyQuestion"等.在某些情况下,使用"问题"数据模板将问题呈现为"问题"已经足够了,但是假设我有一个不同子类的随机问题对象列表,我想反过来显示它们.我想使用他们的特定数据模板而不是他们的通用问题数据模板将它们显示给用户,但由于我不知道在设计时,无论如何都告诉WPF,"嘿,这是一个Quesitons列表,但是使用反射来弄清楚他们的具体类型并使用那个数据模板?"

我曾想过到目前为止:我认为,除了有我的问题集,我使用反射可以创建特定类型的另一采集并以某种方式结合,为"嗒嗒",那么我会得到预期的影响,但你只能绑定到WPF中的DependencyProperties,所以我不确定我绑定到什么.我真的不喜欢这个想法,我的直觉告诉我有一个更优雅的方法来解决这个问题.

我不是在寻找具体的代码,只是一个完成我想要做的事情的一般策略.另外,如果有帮助的话,我大部分时间都在使用MVVM.

谢谢

dev*_*xer 13

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

<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}">
Run Code Online (Sandbox Code Playgroud)

编辑:

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

主视图模型

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

    public MainWindowViewModel()
    {
        QuestionViewModels = new ObservableCollection<QuestionViewModel>
        {
            new GenericQuestionViewModel(),
            new GeographyQuestionViewModel(),
            new BiologyQuestionViewModel()
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

问题查看模型

public abstract class QuestionViewModel : ViewModelBase
{
}

public class GenericQuestionViewModel : QuestionViewModel
{
}

public class GeographyQuestionViewModel : QuestionViewModel
{
}

public class BiologyQuestionViewModel : QuestionViewModel
{
}
Run Code Online (Sandbox Code Playgroud)

问题用户控制

<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>
Run Code Online (Sandbox Code Playgroud)

主窗口

<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>
Run Code Online (Sandbox Code Playgroud)

更新

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

<ItemsControl ItemsSource="{Binding QuestionViewModels}"
              ItemTemplate="{Binding}" /> 
Run Code Online (Sandbox Code Playgroud)