MVVM模型的责任

时间:2013-08-03 14:05:14

标签: wpf mvvm mvvm-light mvvm-foundation

这是一个基本的MVVM问题。

假设我有一个学生编辑窗口,允许用户设置学生的付款方式(现金或支票)。为了灵活性,必须从服务器检索可能的付款方式,列表根据学生的年龄而变化,也可以更改。

问题是:

  1. 应该在哪里存储可能的付款方式?模型或视图模型?

  2. 如果型号,当用户更改年龄时应该下载新的付款方式列表?

  3. 模型在MVVM中应包含哪些内容?

2 个答案:

答案 0 :(得分:2)

模型是存放付款方式和与每种方法相关的业务规则的合理位置。一种方法是使用描述每种付款方式的枚举,并使用“switch”语句查询。

另一种设计结合了多态性的优点,可能看起来像这样......

public class Model
{
    private readonly List<PaymentMethod> _allPaymentMethods; 
    public Model()
    {
        // get payment types from the db
        // to populate master list
        _allPaymentMethods = new List<PaymentMethod> {new Cash(), new CreditCard()};
    }
    public List<PaymentMethod> GetPaymentMethods(int age)
    {
        List<PaymentMethod> result =
            _allPaymentMethods.Where(q => q.Age == age).ToList();
        return result;
    }
}
public abstract class PaymentMethod
{
    public string Name { get; protected set; }
    public int Age { get; protected set; }
    public abstract void ProcessPayment();
    public override string ToString()
    {
        return Name;
    }
}
public class CreditCard:PaymentMethod
{
    public CreditCard()
    {
        Name = "Credit Card";
        Age = 25;
    }
    public override void ProcessPayment()
    {
        Console.WriteLine("Thanks for using your card");
    }
}
public class Cash:PaymentMethod
{
    public Cash()
    {
        Name = "Cash";
        Age = 22;
    }
    public override void ProcessPayment()
    {
        Console.WriteLine("Thanks for paying cash");
    }
}

此示例硬编码两种方法:现金和信用卡,每个类都知道如何在依赖继承来处理公共属性的同时完成其工作。这种方法避免了“切换”,并封装了每个类中的所有业务规则和方法。因此,模型仅公开ViewModel需要知道的内容,以便在项目控件中向用户显示各种付款方式。

当用户更改其年龄时,您的VM可以刷新列表。

VM的代码片段看起来像......

public class ViewModel :INotifyPropertyChanged
{
    public ObservableCollection<PaymentMethod> Methods { get; set; }
    public ViewModel()
    {
        Model m = new Model();
        Methods = new ObservableCollection<PaymentMethod>(m.GetPaymentMethods(22));
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange
               (ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}

无论使用哪种方法(枚举或多态),经验法则是“VM是否绝对需要了解这一点?我可以利用继承和多态的OO优势进入我的架构吗?”

答案 1 :(得分:1)

嗯,在我看来,模型应该包含付款方式列表,而VM应该包含一个绑定到视图的列表。例如,我要做的是在模型上有List<PaymentOptions>,为VM有BindingList<PaymentOptions>ObservableCollection<PaymentOptions>