具有聚合模型类的MVVM - 如何在ViewModels中包装?

Mar*_*rio 4 wpf mvvm

我目前正在尝试使用MVVM模式创建一个小应用程序.但是我真的不知道如何在我的ViewModel中正确包装聚合的Model类.从我对MVVM的了解不多,您不应该将ViewModel中的Models公开为属性,否则您可以直接从View中绑定到Model.所以我似乎必须将嵌套模型包装在另一个ViewModel中,但是这会在稍后同步Model和ViewModel时带来一些问题.

那么你如何有效地做到这一点?

我举一个简短的例子.假设我有以下模型类:

public class Bar
{
    public string Name { get; set; }
}

public class Foo
{
    public Bar NestedBar { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在我相应地创建了两个ViewModel类,包装了Models,但遇到了FooViewModel的问题:

public class BarViewModel
{
    private Bar _bar;
    public string Name 
    { 
        get { return _bar.Name; }
        set { _bar.Name = value; }
    }
}

public class FooViewModel
{
    private Foo _foo;
    public BarViewModel Bar
    {
        get { return ???; }
        set { ??? = value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我如何处理FooViewModel的Bar属性?为了"get"工作,我需要返回一个BarViewModel实例.我是否在FooViewModel中创建了该类型的新字段,并将_foo.NestedBar对象包装在那里?对该字段属性的更改应向下传播到基础Bar实例,对吧?

如果我需要将另一个BarViewModel实例分配给该属性,如下所示:

foo.Bar = new BarViewModel();
Run Code Online (Sandbox Code Playgroud)

现在,它不会传播到模型,模型仍然保留类型Bar的旧实例.我需要创建一个基于新BarViewModel和assing它_Foo一个新的酒吧对象,但你怎么做优雅?这是该样品中很琐碎,但如果酒吧要复杂得多,有很多的属性,那将是大量的输入...更何况它会很容易出错,如果你忘记了设置的一个属性.

Eli*_*eth 7

@Goblin

您的代码存在一些缺陷:例如,如果我从数据库中获取Foo对象列表并且我想将它们包装在ObservableCollection中,该怎么办?

那么你的FooViewModel的构造函数应该接受Foo模型作为参数,而不是在构造函数中创建它!

通常,您可以将模型包装到viewmodel中,并将其同时放入可绑定的Collection中:

IEnumerable<Foo> foos = fooRepository.GetFoos();
foos.Select( m => viewmodelCollection.Add(new ViewModel(m,e.g.Service)));
Run Code Online (Sandbox Code Playgroud)

模型属性不会复制到ViewModel地狱没有!!! ViewModel将其属性委托给模型属性,如:

public class FooViewModel
{
   private Foo _foo;

   public FooViewModel(Foo foo,IService service)
   {
      _foo = foo;

   }

   public string FoosName
   { 
      get{return _foo.Name };
      set
      {
         if(_foo.Name == value)
            return;

         _foo.Name = value;
         this.NotifyPropertyChanged("FoosName");
      }
   }

}
Run Code Online (Sandbox Code Playgroud)

就像Goblin所说的所有UI特定界面一样:

IDataErrorInfo
INotifyPropertyChanged
IEditableObject
Run Code Online (Sandbox Code Playgroud)

等等...

仅由ViewModel实现.