【发布时间】:2011-04-18 17:22:29
【问题描述】:
我创建了以下模型(代码被简化以说明情况):
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; }
}
接下来我创建了一个视图模型:
public class ViewModel
{
public Account Model { ... }
public string Name { ... }
public string FirstName { ... }
public string LastName { ... }
public string Owner { ... }
...
}
最后是视图:
<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 会显示公司? - 在定义数据模板时,我将
DataTypes 指定为Person和Company类型(这样做对我来说很自然)。我是否需要它,因为在非常 下一行我将一个新的数据上下文设置为来自UserControl? - 数据模板的
DataTypes 是否应该是不同的视图模型,例如PersonViewModel和CompanyViewModel?创建它们有意义吗? - 我怎样才能让数据模板从
ContentControl自动?
我知道这最终都是个人选择的问题,但是由于我正在学习 MVVM(我正在使用 MVVM Light),我想知道哪种方法最值得推荐?我仍然不完全理解何时应将模型中的类用作数据模板的数据类型,以及何时应将视图模型用于此目的。表示模型的组件是否应该在视图组件中被引用(假设视图、模型和视图模型都位于单独的组件中)?
感谢所有的澄清!
更新:
此更新应解释当模型类的属性未直接绑定到视图中的一个控件时,数据模板中模型的类为DataTypes 的问题。
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; }
}
在视图中,人的数据模板当然也发生了变化:
<!-- 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>
如果ContentControl 的Content 设置为ViewModel 的Model 属性,我将如何解决性别/单选按钮的情况;因为,现在它们在一个控件/一个属性的方式上不匹配?
【问题讨论】:
-
@vorrtex:好点子!实际上,下面提供的解决方案也隐含地打乱了这个问题。感谢您的加入。
-
1) 除了 Model 属性,我会删除 4 个其他属性。 3) 一个视图模型可以有多个数据模板。 4)他们自动继承它。更新问题:使用 ListBox 并将 ItemContainerStyle 属性更改为看起来像 RadioButton。
-
投票支持看起来像带有单选按钮想法的面板的列表框。
-
@Boris 我偶尔按下 Enter 按钮。无论如何,我想说的几乎和 Markus 说的一样:删除不必要的属性并绑定到 rootLayout。
-
@Boris 如果你喜欢这个想法,我可以分享我在我的应用程序中使用的这个模板的代码:pastebin.com/5nrJQNj2 像这样设置它:
ItemContainerStyle="{StaticResource RadioButtonItemContainerStyle}"。但它来自 Silverlight,所以我不知道它在 WPF 中如何工作。
标签: wpf mvvm mvvm-light