【问题标题】:No derived ViewModels but the same behavior?没有派生的 ViewModel 但行为相同?
【发布时间】:2018-05-29 14:54:25
【问题描述】:

我正在编写一个小型 wpf 桌面应用程序。我的 BaseViewModel 如下所示:

public abstract class BaseViewModel : INotifyPropertyChanged, IComparable<BaseViewModel>
{
    public abstract string GetDisplayText();
    public abstract string GetImageName();

    // INotifyPropertyChanged
}

我一直在为 mvvm 寻找最佳的 paxis。大多数人说,一个模型有多个 ViewModel,我同意。

因为我希望所有相同类型的 ViewModel 以相同的方式处理基础,我认为它们应该相互派生。

public abstract class BaseCustomerVm : BaseViewModel
{
    public abstract string Name { get; set; }
    public abstract int Number { get; set; }
    public abstract bool IsPerson { get; set; }

    public override string GetDisplayText()
    {
        return Name;
    }

    public override string GetImageName()
    {
        if (IsPerson)
            return "Person";
        else
            return "Company";
    }
}

public class Customer1Vm : BaseCustomerVm
{
    public override string Name { get; set; }
    public override int Number { get; set; }
    public override bool IsPerson { get; set; }
}

为了实现这一点,我有以下选择:

版本 1:

public class Customer2Vm : BaseCustomerVm
{
    public override string Name { get; set; }
    public override int Number { get; set; }
    public override bool IsPerson { get; set; }
    // Further Properties
}

版本 2:

public class Customer2Vm : Customer1Vm
{
    // Further Properties
}

在我的搜索中,我读到 ViewModels 不应该从彼此派生。 this post 也回答了这个问题。我的问题是:

  1. 我为什么不应该以这种方式推导?
  2. 在没有继承的情况下处理 sutch basics 的正确方法是什么?

【问题讨论】:

  • “在我的搜索中,我读到 ViewModels 不应该相互派生” -- 在我的搜索中,我读到登月是假的。我会应用通常的规则来决定是否编写子类。
  • 没有什么说视图模型不应该从另一个视图模型派生。有复合重用原则,但这是另一回事:en.wikipedia.org/wiki/Composition_over_inheritance
  • 顺便说一下,GetDisplayTextGetImageName 应该是抽象属性 DisplayTextImageName,而不是方法。您很可能希望能够绑定它们,即使没有,它们通常也是一种属性。
  • 扩展我的第一条评论:您找到的答案是说,如果您应用通常的常识规则,您很少会发现有任何充分理由让您的视图模型层次结构更深的情况比AbstractViewModelBase -> FooViewModel。我没有发现它像他建议的那样罕见,而且我已经在工作中使用 WPF 好几年了。逐案使用您自己的判断。

标签: c# wpf inheritance design-patterns mvvm


【解决方案1】:

在您需要从多个(基本)视图模型继承之前,继承不应该成为问题,即如果您有几个不同的基本视图模型提供它们自己的通用基本功能。

由于您不能从 C# 中的多个类继承,因此您需要将通用功能分解为可重用的组件,您可以将这些组件注入到您的视图模型中。

但是,您能够直接绑定到类中定义的一些公共属性的唯一方法是使用继承,从一系列不同的基本视图模型类继承并没有错。事实上,根据我的经验,这是一种非常常见的方法。视图中使用的大多数类型(ControlFrameworkElement 等)也这样做。

【讨论】:

    【解决方案2】:

    就好像Customer2Vm 应该派生自Customer1Vm;我想你想要经典的继承问题:

    Customer2VmCustomer1Vm 是否存在“是”关系?

    只有你知道;但基于名称我会怀疑它。在我看来,它们都应该来自BaseCustomerVm

    至于你是否应该使用继承;我会说这里基本上看起来还可以。如果你想避免它(并且更喜欢组合),我建议让你的虚拟机实现一个ICustomerVm 接口来获取属性;然后消费者将使用服务来获取显示文本和图像名称。我可能会坚持你所拥有的(假设它或多或少正是你所展示的)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 2017-05-04
      • 1970-01-01
      • 2020-02-24
      • 2012-09-26
      • 1970-01-01
      相关资源
      最近更新 更多