Are data patterns obsolete in MVVM?

I created the following model (the code is simplified to illustrate the situation):

public abstract class Account { public string Name { get; set; } } public class Person : Account { public string FirstName { get; set; } public string LastName { get; set; } } public class Company : Account { public string Owner { get; set; } } 

Next, I created a view model:

 public class ViewModel { public Account Model { ... } public string Name { ... } public string FirstName { ... } public string LastName { ... } public string Owner { ... } ... } 

And finally, the view:

 <UserControl> <UserControl.Resources> <!-- Person data template --> <DataTemplate x:Key="personTemplate" DataType="{x:Type model:Person}"> <Grid DataContext="{Binding ElementName=rootLayout, Path=DataContext}"> <TextBlock Text="{Binding Path=Name}" /> <TextBlock Text="{Binding Path=FirstName}" /> <TextBlock Text="{Binding Path=LastName}" /> </Grid> </DataTemplate> <!-- Company data template --> <DataTemplate x:Key="companyTemplate" DataType="{x:Type model:Company}"> <Grid DataContext="{Binding ElementName=rootLayout, Path=DataContext}"> <TextBlock Text="{Binding Path=Name}" /> <TextBlock Text="{Binding Path=Owner}" /> </Grid> </DataTemplate> <!-- Data template selector for different account types --> <local:AccountTemplateSelector x:Key="templateSelector" PersonTemplate="{StaticResource personTemplate}" CompanyTemplate="{StaticResource companyTemplate}" /> </UserControl.Resources> <StackPanel Name="rootLayout" DataContext="{Binding Path=viewModel}"> <ContentControl Content="{Binding Path=Model}" ContentTemplateSelector="{StaticResource templateSelector}"/> <Button Content="Save" /> <Button Content="Close" /> </StackPanel> </UserControl> 

So, when the loaded model is of type Person , personTemplate displayed; on the contrary, when the Company model is shown companyTemplate .

My questions:

  • Does this approach make sense at all? It would be more reasonable to remove the Model property in the ViewModel class and introduce an enumeration or just a simple bool that would show the person if true , or the company if `false?
  • When defining data templates, I pointed DataType to Person and Company (it was natural for me to do this). Do I need this at all, because in the very next line I am setting a new data context as one of UserControl ?
  • If DataType data templates are different view models, something like PersonViewModel and CompanyViewModel ? Does it make sense to create them?
  • How can I and generally can make a data template inherit a data context from ContentControl automatically?

I know that it all depends on personal choices at the end, but since I'm studying MVVM (I use MVVM Light), I wonder which approach would be most recommended? I still do not quite understand when classes from models should be used as data types for data templates and when models should be used for this purpose. If the assembly representing the model is even mentioned in the view assembly (assuming that the view model, model, and view are all in separate assemblies)?

Thanks for all the clarifications!

UPDATE:

This update should explain the problem of having model classes as DataType in data templates when the property of the model class is not directly tied to a single control in the view.

Person has an enumeration and a new property, so now it looks like this:

 public class Person : Account { public enum GenderType { Female, Male, NotSpecified } public string FirstName { get; set; } public string LastName { get; set; } public GenderType Gender {get; set; } } 

And in the view, naturally, the human data template also changes:

 <!-- Person data template --> <DataTemplate x:Key="personTemplate" DataType="{x:Type model:Person}"> <Grid DataContext="{Binding ElementName=rootLayout, Path=DataContext}"> <TextBlock Text="{Binding Path=Name}" /> <TextBlock Text="{Binding Path=FirstName}" /> <TextBlock Text="{Binding Path=LastName}" /> <RadioButton Name="Female" /> <RadioButton Name="Male" /> <RadioButton Name="NotSpecified" /> </Grid> </DataTemplate> 

If the Content parameter for ContentControl set to Model ViewModel property, how to resolve the situation with the floor / switches; because now they do not correspond to one control / one property?

+2
wpf mvvm mvvm-light
source share
2 answers

I would change it to this:

 <UserControl> <UserControl.Resources> <!-- Person data template --> <DataTemplate DataType="{x:Type model:Person}"> <Grid> <TextBlock Text="{Binding Path=Name}" /> <TextBlock Text="{Binding Path=FirstName}" /> <TextBlock Text="{Binding Path=LastName}" /> <RadioButton Name="Female" IsChecked="{Binding Gender , Converter={StaticResource enumBooleanConverter}, ConverterParameter=Female}" /> <RadioButton Name="Male" IsChecked="{Binding Gender , Converter={StaticResource enumBooleanConverter}, ConverterParameter=Male}" /> <RadioButton Name="NotSpecified" IsChecked="{Binding Gender , Converter={StaticResource enumBooleanConverter}, ConverterParameter=NotSpecified }" /> </Grid> </DataTemplate> <!-- Company data template --> <DataTemplate DataType="{x:Type model:Company}"> <Grid> <TextBlock Text="{Binding Path=Name}" /> <TextBlock Text="{Binding Path=Owner}" /> </Grid> </DataTemplate> </UserControl.Resources> <StackPanel DataContext="{Binding viewModel}"> <ContentControl Content="{Binding Model}" /> <Button Content="Save" /> <Button Content="Save" /> <Button Content="Close" /> </StackPanel> </UserControl> 

like you, you define implicit styles for your classes, and you don't need to use a template. In addition, you do not need all your string properties in the ViewModel class:

 public class ViewModel { public Account Model { ... } ... } 

Disclaimer, binding in RadioButtons uses the converter here .

+2
source share

Absolutely positive no (they are outdated).

  • Yes, that makes sense, but your bindings are not many. These problems can be handled in various ways. For example, an account may have a Parent property that provides the ViewModel in which it is contained (I did not say that this is the best approach).
  • This is a problem with the design of the ViewModel, where you should not be attached to the account, but to the ViewModel. It may be possible to change the design so that you do not need to do this; it's hard to tell with the snapshot you provided.
  • I do not think this will help you with this. I would see if there is a way to save your ViewModel-related interface from a DataTemplate.
  • Here's one good solution: Create a DataTemplateSelector that selects the template based on the Account property. So you can associate the ItemsSource directly with the DataContext and it will be available in the DataTemplate.
0
source share

All Articles