我创建了以下模型(简化了代码以说明这种情况):
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; }
}
接下来,我创建了一个 View 模型:
public class ViewModel
{
public Account Model { ... }
public string Name { ... }
public string FirstName { ... }
public string LastName { ... }
public string Owner { ... }
...
}
最后, 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>
因此,当加载的模型的类型为
Person
时,将显示personTemplate
;反之亦然,当模型为Company
时,将显示companyTemplate
。我的问题是:
Model
会更聪明吗属性在
ViewModel
类中,并引入一个枚举或一个简单的bool
如果显示true
,则显示人;如果显示为false,则显示公司? DataType
指定为Person
和Company
类型(这种方式对我来说很自然)。我是否需要它,因为在非常下一行我要设置一个新的数据上下文,使其成为
UserControl
中的那个? DataType
是否应为不同的 View 模型,例如PersonViewModel
和CompanyViewModel
吗?创建它们有意义吗? ContentControl
自动吗? 我知道所有这些最终都是个人选择的问题,但是由于我正在学习MVVM(我正在使用MVVM Light),所以我想知道哪种方法最值得推荐?我仍然不完全了解何时应将模型中的类用作数据模板的数据类型,以及何时应将 View 模型用于此目的。代表模型的部件是否应该甚至在 View 部件中引用(假设 View ,模型和 View 模型都位于单独的部件中)?
感谢您的所有澄清!
更新:
此更新应解释当模型类的属性未直接绑定(bind)到 View 中的仅一个控件时,在数据模板中将模型的类作为
DataType
出现的问题。Person
中有一个枚举和一个新属性,因此现在看起来像这样: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; }
}
并且在 View 中,人员的数据模板当然也发生了变化:
<!-- 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>
如果
Content
的ContentControl
设置为Model
的ViewModel
属性,我将如何解决性别/单选按钮的情况;因为,现在它们不以一种控件/一种属性的方式匹配?
最佳答案
我将其更改为:
<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>
这样,您就可以为类定义隐式样式,而不必使用templateselector。另外,您不需要
ViewModel
类中的所有字符串属性:public class ViewModel
{
public Account Model { ... }
...
}
免责声明,RadioButton中的绑定(bind)使用here中的Converter。
关于wpf - MVVM中的数据模板是否过时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5706500/