MVVM中的数据模板是否过时? [英] Are data templates obsolete in MVVM?

查看:59
本文介绍了MVVM中的数据模板是否过时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 { ... }   
    ...
}

最后,视图:

<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;否则,将显示personTemplate.反之亦然,当模型为Company时,将显示companyTemplate.

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.

我的问题是:

  1. 这种方法是否有意义?删除Model会更聪明吗 ViewModel类中的属性,并引入一个枚举或只是一个简单的bool 如果true会显示人员,如果`false会显示公司?
  2. 在定义数据模板时,我为PersonCompany指定了DataType s 类型(这种方式对我来说很自然).我是否需要它,因为在非常 下一行我要设置一个新的数据上下文为UserControl中的那个吗?
  3. 数据模板的DataType应该是不同的视图模型,例如 PersonViewModelCompanyViewModel?创建它们有意义吗?
  4. 我怎样才能使数据模板完全继承自 ContentControl自动吗?
  1. Does this approach make sense at all? Would it be smarter to delete the Model property in the ViewModel class and to introduce an enum or just a simple bool which would show person if true, or company if `false?
  2. While defining the data templates, I specified DataTypes to Person and Company 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 the UserControl?
  3. Should the DataTypes of the data templates be different view models, something like PersonViewModel and CompanyViewModel? Does it make sense to create them?
  4. How can I, and can I at all, make data template inherit the data context from the ContentControl automatically?

我知道所有这些最终都是个人选择的问题,但是由于我正在学习MVVM(我正在使用MVVM Light),所以我想知道哪种方法最值得推荐?我仍然不完全了解何时应将模型中的类用作数据模板的数据类型,以及何时应将视图模型用于此目的.代表模型的程序集是否应该甚至在视图程序集中引用(假设该视图,模型和视图模型都位于单独的程序集中)?

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)?

感谢所有澄清!

更新:

此更新应解释当模型类的属性未直接绑定到视图中的仅一个控件时,在数据模板中将模型类作为DataType的问题.

This update should explain the problem of having classes of the model as DataTypes in the data templates when the property of the model class is not directly binded to just one control in the view.

Person中有一个枚举和一个新属性,因此现在看起来像这样:

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>

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

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?

推荐答案

我将其更改为:

<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类中的所有字符串属性:

like this you define implicit styles for your classes and you don't have to use a templateselector. Also then you don't need all your string properties in the ViewModel class:

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

免责声明,RadioButtons中的绑定使用此处.

Disclaimer, the binding in the RadioButtons uses a Converter from here.

这篇关于MVVM中的数据模板是否过时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆