【问题标题】:For MVVM, what is the best practice for viewmodel to export the property in model to view?对于 MVVM,viewmodel 将模型中的属性导出到视图的最佳做法是什么?
【发布时间】:2013-03-25 23:24:08
【问题描述】:

作为 WPF 的新手,我最近开始了我的 MVVM 之旅。我可以理解为什么我们需要 MVVM 的原始意图,但是一些实现细节仍然让我很困惑。

这是我的一个问题:

我应该如何通过ViewModelmodel中的属性导出到View

我可以在这里展示我的一些想法,所以请与我分享你的观点。

这是我的一个实现:

    class MyModel : INotifyPropertyChanged
    {
        private String _name;
        public String Name
        {
            get { return _name; }
            set 
            {
                if (_name != value)
                {
                    _name = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("Name"));
                    }
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

    class MyViewModel
    {
        private MyModel _model;

        public MyModel Model
        {
            get { return _model; }
            set { _model = value; }
        }
    }

我认为问题在于我们没有将视图与模型分离。并且视图需要知道模型实现的每一个细节来完成绑定过程。在我看来,将Model 直接 中的属性导出以从ViewModel 查看不能被视为一个好的设计。

所以我希望你能分享你关于这个主题的设计经验。

顺便说一句, 如果我们从视图模型中导出许多对象,例如 ListMyModel 对象以查看,我该如何实现这一点以将视图与模型解耦?

【问题讨论】:

  • 视图不需要知道模型实现的每一个细节,视图只需要知道要绑定的属性的名称。在您的情况下,这将是 Name 属性。如果您有某种方法来格式化此名称,从数据库中检索此名称等。这将在您的 Model/ViewModel 类中,并且视图根本不需要知道任何这些 => 解耦。

标签: wpf design-patterns mvvm viewmodel


【解决方案1】:

不是你的模型,而是你的 ViewModel 应该实现 INotifyPropertyChanged。然后可以在 View 中使用 Binding 从 ViewModel 中获取数据。

在您的视图/XAML 中有类似的语句

... Content="{Binding myViewModelProperty}" ... 

取决于您要绑定的内容。

myViewModelProperty 必须是 ViewModel 中的公共属性

public string myViewModelProperty { get; set; }

不要忘记在 setter 中调用 RaiseNotifyPropertyChanged(或调用你的处理程序)以获取视图中的更新。

private string myViewModelField;

public string myViewModelProperty 
{ 
   get
   {
        return myViewModelField;
   }
   set
   {
       myViewModelField = value;
       RaiseNotifyPropertyChanged(() => myViewModelProperty);
   }
}

** 更新**

列表通常通过ObservableCollection<Type>“导出”。 理想情况下,Type 是这里的一些 ViewModel,使用模型中的数据创建到 显示在您的视图中。您可以将 ViewModel 想象为 Adapter 之间 你的模型和你的观点。

【讨论】:

  • 如果我这样创建 ViewModel,是否意味着我需要编写代码将每个 Model 属性映射到 ViewModel 属性?是不是太复杂了?
  • 这应该是微不足道的。有时我会添加一个像 public SomeViewModel FromModel(SomeModel model) 这样的工厂方法,它可以在几行中完成这个映射。重要的部分是您为视图调整模型数据,并且在模型更新的情况下您可以清晰地分离关注点。
  • 如果我的回答有帮助,请考虑接受。
【解决方案2】:

这不是一个严格的规则,但在我的情况下,我更喜欢在 ViewModel 中实现 INotifyPropertyChanged 并将模型保留为简单的 POCO。

在 ViewModel 中“重复”模型的属性可能很烦人,但是:

  1. 通常您不需要将所有属性都公开给视图。
  2. 它允许您在 VM 中添加其他代码(例如用户输入验证)并保持模型“干净”。

所以在你的例子中应该是:

   class MyModel
    {
        public String Name
        {
            get;
            set;
        }     
    }

    class MyViewModel : ViewModelBase //let's say you have this base class in your framework
    {
        private MyModel model;

        public MyViewModel(MyModel model)
        {
            this.model = model;
        }

        public string Name 
        {
            get
            {
                 return this.model.Name;
            }

            set
            {
                 if(IsValidInput(value)
                 {
                     this.model.Name = value;
                     this.RaisePropertyChanged("Name"); // the ViewModelBase  base class provide this helper.
                 }
            }       
        }    
    }

关于您的第二个问题,ObservableCollection 通常是向视图公开模型集合的好方法:

class ContactListViewModel
{
    public ObservableCollection<MyModel> Contacts { get; private set;}
}

【讨论】:

    【解决方案3】:

    您可以简单地使用 Model.Name 在视图上绑定您的属性

    【讨论】:

      猜你喜欢
      • 2013-02-03
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-09
      • 1970-01-01
      • 1970-01-01
      • 2018-02-07
      相关资源
      最近更新 更多