wpf - MVVM中的数据模板是否过时?

标签 wpf mvvm mvvm-light

我创建了以下模型(简化了代码以说明这种情况):

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指定为PersonCompany类型(这种方式对我来说很自然)。我是否需要它,因为在非常
    下一行我要设置一个新的数据上下文,使其成为UserControl中的那个?
  • 数据模板的DataType是否应为不同的 View 模型,例如PersonViewModelCompanyViewModel吗?创建它们有意义吗?
  • 我怎样才能使数据模板继承自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>
    

    如果ContentContentControl设置为ModelViewModel属性,我将如何解决性别/单选按钮的情况;因为,现在它们不以一种控件/一种属性的方式匹配?

    最佳答案

    我将其更改为:

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

    相关文章:

    wpf - MVVM 多命令处理程序

    c# - 将所选项目作为命令参数传递与使用绑定(bind)的 ViewModel 对象 (MVVM)

    wpf - MVVM:模型状态更改时通知 View

    c# - 将 FlowDocument 绑定(bind)到我的 FlowDocumentScrollViewer

    c# - WPF - MVVM DataTemplate 加载到内存以供重用

    android - livedata builder可以进行一次性操作吗?

    modal-dialog - 如何使用 MVVM Light 创建模态对话框

    c# - 使用 MVVM Light Messanger 代替事件

    wpf - 在 tabControl 中为 TabItems 使用数据模板

    wpf - 除非先单击行,否则 ListView 行内的WPF MVVM按钮不起作用