使用MVVM模式(特别是使用MVVM Light),如何实现具有多个基元的模型

本文关键字:MVVM 模型 实现 特别是 模式 Light 何实现 使用 | 更新日期: 2024-10-22 04:35:27

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

我的问题是:

我在生成一个视图模型时遇到了问题,该模型将视图正确地绑定到一个属性不仅仅是基元类型的模型上——构建模型和附带的视图模型的有效方法是什么,以便视图通过视图模型绑定到模型,并在模型中的值发生变化时正确更新?

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


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

Foo:

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);
        }
    }

还是其他什么?

使用MVVM模式(特别是使用MVVM Light),如何实现具有多个基元的模型

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

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

嵌套视图模型的优势

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

平面视图模型的优势

  • 让事情变得简单易读

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

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

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

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

总是为每个ViewModel创建一个Model是没有意义的。这样做,当你可以避免并发症时,你会使系统过于复杂。

关于绑定到非基元类型。好吧,将直接通知的支持添加到类型中没有任何问题。

这实际上取决于您对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的对象可能导致内存泄漏查看此答案