DataTemplates in WPF

I have a general question about data patterns in WPF. Say I have an abstract class called “Question” and various subclasses like “MathQuestion”, “GeographyQuestion”, etc. In some contexts, providing questions like “Question” using the Question data template is good enough, but let's say that I have a list of random Question objects of various subclasses that I want to display in the queue. I want to show them to the user using their specific data templates, not their general question data template, but since I don’t know what is at development time, I still need to tell WPF: "Hey, here is a list of Quesitons, but use reflection to find out their specific types and use the THAT data template? "

What I was thinking so far: I thought that in addition to my collection of questions I could create another collection of specific types using reflection and somehow associate it with “blah”, then I would get the desired effect, but you can only bind to DependencyProperties in WPF, so I'm not sure what I'm bound to. I really do not like this idea, and my intuition tells me a more elegant way to approach this problem.

I'm not looking for specific code here, just a general strategy to achieve what I'm trying to do. Also, I use MVVM for the most part if that helps.

thanks

+6
source share
2 answers

I think something like this should work right out of the box:

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

Edit:

Yes, this should definitely work. Here is a more complete example:

Basic view model

 public class MainWindowViewModel : ViewModelBase { public ObservableCollection<QuestionViewModel> QuestionViewModels { get; set; } public MainWindowViewModel() { QuestionViewModels = new ObservableCollection<QuestionViewModel> { new GenericQuestionViewModel(), new GeographyQuestionViewModel(), new BiologyQuestionViewModel() }; } } 

Question View Models

 public abstract class QuestionViewModel : ViewModelBase { } public class GenericQuestionViewModel : QuestionViewModel { } public class GeographyQuestionViewModel : QuestionViewModel { } public class BiologyQuestionViewModel : QuestionViewModel { } 

User controls

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

Main window

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

Update

Kyle Tolle noted a nice simplification for setting ItemsControl.ItemTemplate . Here is the resulting code:

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

Generally, if you need to dynamically change a DataTemplate based on some non-static logic, you should use a DataTemplateSelector . Another option is to use the DataTriggers in your DataTemplate to change the look accordingly.

+4
source

Source: https://habr.com/ru/post/907601/


All Articles