【问题标题】:With an MVVM Pattern (Specifically Using MVVM Light), How To Implement Model With More Than Just Primitives?使用 MVVM 模式(特别是使用 MVVM Light),如何实现不只是 Primitives 的模型?
【发布时间】:2015-05-08 21:36:28
【问题描述】:

我刚刚开始使用 MVVM 模式,并已决定将 MVVM Light 工具包用于我的 Windows Phone 应用程序。

我的问题是这样的:

我无法生成一个视图模型,该模型将视图正确绑定到具有不仅仅是原始类型的属性的模型——什么是构造模型和随附视图模型的有效方式,以便视图将绑定通过视图模型到模型,并在模型中的值发生变化时正确更新?

如中,我如何正确地从视图模型中引用模型的值?


这种模型的一个例子是一个类 Foo,它有一个属性 b,它是一个基元,还有另一个属性,a ,即 Bar 类型,具有自己的属性——基元或其他。

富:

public class Foo : ObservableObject
{

    public Foo()
    {

        a = new Bar();
    }

    public const string aPropertyName = "a";
    private Bar _a;
    public Bar a
    {
        get
        {
            return _a;
        }
        set
        {
            Set(aPropertyName, ref _a, value);
        }
    }

    public const string bPropertyName = "b";
    private bool _b;
    public bool b
    {
        get
        {
            return _b;
        }
        set
        {
            Set(bPropertyName, ref _b, value);
        }
    }
}

酒吧:

public class Bar : ObservableObject
{

    public const string cPropertyName = "c";
    private bool _c;
    public bool c
    {
        get
        {
            return _c;
        }
        set
        {
            Set(cPropertyName, ref _c, value);
        }
    }
}

编辑:澄清一下,在视图模型中设置属性时,我应该这样做:

    public const string cPropertyName = "c";
    public bool c
    {
        get
        {
            return model.a.c;
        }
        set
        {

            model.a.c = value;
            RaisePropertyChanged(cPropertyName);
        }
    }

还是有什么不同?

【问题讨论】:

  • 我不确定您的意思...在您的 ViewModel 中有一个私有模型实例并通过它公开模型属性。如果您想公开其他复杂对象,请在同一个 ViewModel 中公开其属性或创建一个新对象。
  • @RodrigoSilva 请查看编辑。
  • 不需要使用变量来保存属性名称,imo。而且我不明白你为什么不应该这样做。
  • @RodrigoSilva 适当地注意到了。

标签: c# wpf mvvm windows-phone-8.1 mvvm-light


【解决方案1】:

我认为您要问的问题是嵌套与平面视图模型。两者都是正确的方法,具体取决于具体情况[尽管我更喜欢嵌套视图模型]。 我不能建议你使用什么,但在 Foo-Bar 示例的情况下,用 Foo 中的属性包装 Bar 的属性会更有意义 [平面视图模型方法]。所以你通过创建属性 c 所做的事情是正确的。

以下是我对这两种方法的看法

嵌套视图模型的优势

  • 这就是面向对象的全部意义所在。
  • 如果您使用 LINQ to SQL 或实体或 ORM,您可以简单地传递 ORM 对象,而不必传递各种属性。
  • 您可以传递其他视图,因此您可以为分部视图创建单独的模型,如果该视图使用分部,您可以将分部视图模型类作为视图模型类的属性传递。

平面视图模型的优势

  • 让事情变得简单易读。

【讨论】:

    【解决方案2】:

    在我们公司开发的最后两个 WPF 应用程序中,我们使用了MVVMCaliburn.Micro

    对于大部分ViewModels,我们没有创建Models,因为您应该创建Model,不是因为否则您会违反一些OOP 规则,而是因为您需要它。 什么时候应该创建一个单独的Model
    在我看来,分两种情况:

    • 何时可以在其他应用程序中重用 Model

    • ViewModel 变得复杂并且您开始意识到您希望通过分离关注点来简化它时。从ViewModel 中提取Model 几乎总是很简单,即使不是微不足道的。

    总是为每个ViewModel 创建一个Model 是没有意义的。这样一来,系统就会变得过于复杂,而您可以避免复杂化。

    关于绑定到非原始类型。好了,直接给类型添加通知的支持是没有任何问题的。

    【讨论】:

      【解决方案3】:

      这真的取决于您对 ViewModel 的使用。

      如果您只需要一个或两个复杂类型的属性(在您的示例中为Bar),您可以在 ViewModel 中将其展平。如果您知道自己总是/大部分需要所有复杂属性,那么为您的复杂模型创建自己的 ViewModel 并公开您的 ViewModel 而不是模型可能是有意义的。

      public class Foo : ObservableObject
      {
          public BarViewModel A 
          {
              public const string aPropertyName = "a";
              private Bar _a;
              get
              {
                  return _a;
              }
              set
              {
                  Set(aPropertyName, ref _a, value);
              }
          }
      }
      

      最后但同样重要的是: 您的复杂模型是否需要双向绑定?如果不是,您可以为您的模型实现一个属性。

      但请注意! 绑定不实现INotifyPropertyChanged的对象可能会导致内存泄漏!this的回答

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-03
        • 2011-10-11
        • 1970-01-01
        • 2011-04-01
        • 2011-01-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多