C# WPF中的数据模板
我有一个关于WPF中的数据模板的一般性问题。假设我有一个名为“Question”的抽象类,以及各种子类,如“MathQuestion”、“GeographyQuestion”等。在某些上下文中,使用“Question”数据模板将问题呈现为“Question”已经足够了,但假设我有一个随机问题对象列表,其中包含各种子类,我希望依次显示这些子类。我想使用特定的数据模板而不是通用的问题数据模板向用户显示它们,但由于我在设计时不知道这一点,是否有必要告诉WPF,“嘿,这里有一个问题列表,但是使用反射来找出它们的特定类型并使用该数据模板?” 到目前为止我的想法是:我认为除了拥有我的问题集合之外,我还可以使用反射创建另一个特定类型的集合,并以某种方式将其绑定到“blah”,然后我会得到想要的效果,但您只能绑定到WPF中的DependencyProperties,所以我不确定绑定到什么。我真的不喜欢这个想法,我的直觉告诉我有一种更优雅的方法来解决这个问题 这里我不是在寻找特定的代码,只是一个实现我所要做的事情的一般策略。另外,如果有帮助的话,我大部分时间都在使用MVVMC# WPF中的数据模板,c#,wpf,mvvm,datatemplate,C#,Wpf,Mvvm,Datatemplate,我有一个关于WPF中的数据模板的一般性问题。假设我有一个名为“Question”的抽象类,以及各种子类,如“MathQuestion”、“GeographyQuestion”等。在某些上下文中,使用“Question”数据模板将问题呈现为“Question”已经足够了,但假设我有一个随机问题对象列表,其中包含各种子类,我希望依次显示这些子类。我想使用特定的数据模板而不是通用的问题数据模板向用户显示它们,但由于我在设计时不知道这一点,是否有必要告诉WPF,“嘿,这里有一个问题列表,但是使用反射来找
谢谢我在想,像这样的东西应该是开箱即用的:
<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 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>
通常,如果您需要基于一些非静态逻辑动态更改DataTemplate,那么可以使用。另一个选项是在DataTemplate中使用DataTriggers来适当修改外观。假设VM呈现一个ObservableCollection,运行时是否知道使用更具体的数据模板而不是通用的问题数据模板?@Quanta,是的,它应该可以正常工作。您只需将
ContentControl
放入ItemsControl
@Quanta中,更新我的答案以使用observeCollection
和ItemsControl
@Quanta-您将无法为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>
<ItemsControl ItemsSource="{Binding QuestionViewModels}"
ItemTemplate="{Binding}" />