首页 文章

集合的MVVM

提问于
浏览
5

我最近开始学习wpf并尝试使用mvvm .

我的理解是,在mvvm中,视图或模型都不应该知道另一个存在 .

我要做的是在屏幕上显示客户列表 . 但是如果我对viewModel进行编码,如下所示 . 这与我在网上看到的许多例子类似,然后我最终得到了一些看起来像这样的代码

class Customer 
{    
    public String Name {get;set;}     
    public String Address {get;set;} }
}

class MainWindowViewModel
{
    ObservableCollection<Customer> customers = new ObservableCollection<Customer>();

    public ObservableCollection<Customer> Customer 
    {
      get {return customers;}
    } 

    public MainWindowViewModel() 
    {
     //cust1 and cust2 are Customer objets
      customers.Add(cust1);
      customers.Add(cust2);
    }
}

现在,如果我创建了 MainWindowViewModel 的实例并将其设置为我的 MainWindowView (我的视图)的datacontext,并且我进一步将viewmodels Customers 属性绑定到listBox,那么视图将需要对包含我的模型的程序集的引用 .

所以我的问题是 .

1)在MVVM中添加对允许的模型程序集的引用,因为这意味着视图知道模型 .

2)更好的解决方案是将每个 Customer 对象包装在 CustomerViewModel 中,并让MainWindowViewModel包含 ObservableCollection of CustomerViewModel 而不是 ObservableCollection of Customer . 这会将模型与视图完全分开 .

5 回答

  • 2
    • 我不确定为什么你认为包含你的观点的项目需要引用你的模型项目?您的视图中没有任何内容直接引用您的模型 - XAML中的绑定表达式仅按名称链接,并且无论如何都链接到视图模型上的属性,而不是您的模型 .

    • 如果您的视图需要比模型提供的更多数据,则在视图模型中包装模型是一个不错的选择,并且不希望更改模型 . 例如,您可能需要显示 User 类型的 Age ,但 User 只有 DateOfBirth 属性 . 如果您不想更改模型,则使用 Age 属性创建 UserViewModel 将是一个不错的选择 .

  • 0

    您的问题的答案:

    • 参考模型的视图有什么不好?这在简化代码时绝对可以 . 反过来说(模型 - >视图)是不好的做法 .

    • 当您没有特殊需要时,不需要在 CustomerViewModel 中包装每个 Customer 对象 . 我建议采用务实的方式并保持代码简单 .

    您可能对 WPF Application Framework (WAF) 的示例应用程序感兴趣,该应用程序显示了您在此处描述的场景 .

  • 0

    我们通常会创建一个CustomerViewModel . 这是由我们的通用CollectionViewModelBase类强制执行的 . 这不确定用户界面使用的每个部分都是特别创建的以便显示,并且我们在模型中没有任何与UI相关的代码,这些代码通常是可序列化的POCO .

  • 3

    MVVM模式与任何其他MVx模式(MVC,MVP,...)类似,因为它鼓励关注点分离(SoC),从而提高代码的可维护性/可测试性 . 除了通常的SoC之外,MVVM还提供以下内容:

    • 视图逻辑的单元测试;这是因为您将逻辑从视图移动到视图模型中,使您的视图尽可能愚蠢 .

    • 开发人员 - 设计师工作流程;因为视图是'dumb',所以在没有背后的逻辑的情况下使用XAML更容易 .

    关于可见性,即什么是可见的,严格如下:

    Model <= ViewModel <= View
    

    换句话说,ViewModel可以看到Model,但Model看不到ViewModel . 同样,View可以看到ViewModel,但反之亦然 .

    由于ViewModel没有对View的引用,因此它可以在没有任何视图组件的情况下执行代码,这将启用上面的(1) .

    ViewModel的目的是“塑造”您的模型以更轻松地绑定到View . 如果您的View很简单,那么执行以下操作是完全可以接受的:

    Model <= View
    

    这仍然允许(1)单元测试,(2)开发人员 - 设计者工作流程 .

    使用混合方法也很好,有时会将模型暴露给您的视图,有时将其包装在ViewModel中 . 例如:

    http://www.scottlogic.co.uk/blog/colin/2009/08/the-mini-viewmodel-pattern/

    请不要创建一堆样板的ViewModel代码,只是因为你认为你必须这样做!

  • 0

    您肯定希望仅在视图中包装您的模型,如下所示:

    /// <summary>
    /// Business model object : Should be in your separate business model only library
    /// </summary>
    public class BusinessModelObject
    {
        public string Prop1 { get; set; }
        public int Prop2 { get; set; }
    }
    
    
    
    /// <summary>
    /// Base notifying object : Should be in your GUI library
    /// </summary>
    public abstract class NotifyingObject<T> : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void NotifyPropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, e);
        }
    
    
        private static readonly PropertyChangedEventArgs ModelPropertyChanged = new PropertyChangedEventArgs("Model");
        private T _model;
        public T Model
        {
            get { return _model; }
            set
            {
                _model = value;
                NotifyPropertyChanged(ModelPropertyChanged);
            }
        }
    }
    
    /// <summary>
    /// Model decorator : Should be in your GUI library
    /// </summary>
    public class BusinessModelObjectAdapter : NotifyingObject<BusinessModelObject>
    {
        public BusinessModelObjectAdapter(BusinessModelObject model)
        {
            this.Model = Model;
        }
    
        private static readonly PropertyChangedEventArgs Prop1PropertyChanged = new PropertyChangedEventArgs("Prop1");
        private string _prop1;
        public string Prop1
        {
            get { return Model.Prop1; }
            set
            {
                Model.Prop1 = value;
                NotifyPropertyChanged(Prop1PropertyChanged);
            }
        }
    
        private static readonly PropertyChangedEventArgs Prop2PropertyChanged = new PropertyChangedEventArgs("Prop2");
        private int _prop2;
        public int Prop2
        {
            get { return Model.Prop2; }
            set
            {
                Model.Prop2 = value;
                NotifyPropertyChanged(Prop1PropertyChanged);
            }
        }
    
        //and here you can add whatever property aimed a presenting your model without altering it at any time
    }
    

相关问题