I have 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 have 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 model that is loaded is of type Person
the personTemplate
is shown; vice versa, when the model is Company
the companyTemplate
is shown.
My questions are:
- Does this approach make sense at all? Would it be smarter to delete the
Model
property in theViewModel
class and to introduce an enum or just a simplebool
which would show person iftrue
, or company if `false? - While defining the data templates, I specified
DataType
s toPerson
andCompany
types (it was natural to me to do it this way). Do I need it at all because in the very next line I am setting a new data context to be the one from theUserControl
? - Should the
DataType
s of the data templates be different view models, something likePersonViewModel
andCompanyViewModel
? Does it make sense to create them? - How can I, and can I at all, make data template inherit the data context from the
ContentControl
automatically?
I know that all this is a matter of a personal choice in the end, but since I am learning MVVM (I am using MVVM Light), I am wondering which approach would be the most recommendable one? I still do not fully understand when should the classes from models be used as data types for data templates and when should view models be used for that purpose. Should the assembly that represents the model even be referenced in the view assembly (assuming that view, model and view model all reside in separate assemblies)?
Thanks for all the clarifications!
UPDATE:
This update should explain the problem of having classes of the model as DataType
s in the data templates when the property of the model class is not directly binded to just one control in the view.
There is an enum and a new property in the Person
, 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, the data template of the person is changed as well of course:
<!-- 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
of the ContentControl
is set to Model
property of the ViewModel
, how would I resolve the gender/radio buttons situation; because, now they do not match in the way one control/one property?