如何在MVVM模式中更新模型和视图模型?

3

我正在努力在我的当前项目中实现MVVM模式。

"ClassA" 不断地从远程设备获取所需的数据并将这些数据存储在它的字段中。我猜这是一个模型。ClassA通过Update方法更新所需的信息。

"ClassB" 不断地从 "ClassA" 获取数据并将其存储在相应的属性中。看起来像是一个视图模型。

视图是一个简单的MainWindow.xaml,里面有一个DataGrid。

我有以下问题:

1) 如何更新ViewModel? ClassB是否应该有一个Update方法,该方法接受ClassA的实例并更新相应的字段?

2) 在哪里存储ClassA的实例? ClassA是否应该是ClassB的一个字段?如果是的话,那么如何更新Model呢? 我考虑了以下内容:

public void UpdateB()
{
    ClassA.UpdateA();
    this.FieldOne = ClassA.FieldOne;
    this.FieldTwo = ClassA.FieldTwo;
}

4) 模型是否有更新方法,还是仅存储数据?

3) 除了窗口初始化之外,在MainWindow.cs中我应该做些什么?我在那里更新视图模型(ClassB)吗?


2
你应该为ClassB(视图模型)实现INotifyPropertyChanged接口,并将ClassB设置为MainWindow的DataContext(可以从代码后台或xaml中进行设置)。然后,您需要将UI元素绑定到视图模型字段并填充这些字段。您可以找到许多简单的MVVM模式实现示例。 - Yuri Dorokhov
2个回答

1
我发现在每个抽象层都有一个代表项的对象是最好的做法。这包括数据形式在磁盘上的存在方式。请记住,在MVVM中,唯一真正的目标是促进界面(用户界面)和实现(ViewModel功能)之间的松散耦合。
例如,如果我有存储在XML文件中的对象,则在我的数据访问层中会有一个仅用于正确管理XML数据的对象。我们称其为ObjectXml。该对象仅包含数据以与磁盘上的数据本地格式相同的形式存在。在这种情况下,所有数据都具有字符串表示形式,如XML文件中所示。
在模型层中,您将使用预期数据类型的数据表示XML文件。我们称之为Object。属性getter和setter可以通过执行双向转换来访问和设置数据的字符串表示形式。这样,数据就准备好被持久化到数据源(xml文件、数据库等)了。
在ObjectViewModel中,属性可以访问Object中的属性。ViewModel包含用于表示和修改模型的所有成员。
请注意,只有当您只允许存储字符串信息或者适合您的数据类型不存在合适的模式时,ObjectXml 才是真正有益的。
最后,您会得到一个包含层次结构,如下所示:
public class ObjectXml
{
    [XmlArray("People"), XmlArrayItem("Person")]
    public List<PersonXml> People { get; set; }
    //PersonXml is an xml data model similar to this one

    [XmlElement("Item")]
    public string Items { get; set; }
}

这里是Xml对象的模型:

public class Object
{
    private ObjectXml _xmlContext;

    public Object(ObjectXml xmlContext)
    {
        this._xmlContext = xmlContext;
    }

    public List<Person> People
    {
        get
        {
            //Person requires a constructor that takes a PersonXml object in order for this to work properly
            return this._xmlContext.People.Select(x => new Person(x)).ToList();
        }
        set
        {
            this._xmlContext.People = value.Select(x => new PersonXml(x)).ToList();
        }
    }

    public double Item
    {
        get { return double.Parse(this._xmlContext.Item); }
        set { this._xmlContext.Item = value.ToString(); }
    }
}

显然,在C#中将您的类命名为Object是不明智的,因为它是保留字。希望我已经给您提供了一些关于如何以强大和可扩展的方式访问和更新数据的想法。
简而言之,您根本不需要更新方法。此外,在C# MVVM中除了常量和属性后备字段之外,几乎没有理由需要直接访问字段。
请看下方内容。不要听那些说需要将ViewModel和Model解耦的人。Model的主要作用是作为中介层,准备数据以便保存或加载到程序中,并以一种对数据和程序功能(ViewModel)都不了解的方式存储数据。
您不需要更新方法。使用访问数据模型并在需要时将其持久化到数据存储(xml、数据库等)的属性即可。
您不需要更新方法。
您不应该在ViewModel.cs中执行任何操作。只有修改视图的代码应该在代码后台中。您在视图中唯一应该访问的ViewModel是遵循MainWindowViewModel形式的ViewModel,它更像是一个ApplicationViewModel,携带其他所需的viewmodels实例。
最后,不要陷入使用过于复杂的MVVM“框架”中,因为大部分功能都是不必要的。

看起来我终于明白了。谢谢你。 - CorellianAle
这很好,直到你有除了最琐碎的应用程序之外的任何东西,你不仅需要更新持久化的XML文件,还需要更新依赖于该持久化XML的其他视图。 - wired_in

0

如Yuris评论中所述,您不应使用任何更新方法,而应实现INotifyPropertyChanged接口。正如名称所示,当某个属性的值更改时,它会通知所有订阅者。

这篇是一篇很好的文章,其中包含了一个简约的MVVM实现代码。如果您在从头开始实现模式时遇到麻烦,请尝试使用此示例,并逐个替换现有类为您自己的类。

至于您的MainWindow.cs中的更新机制-如果您在xaml代码中像上面链接的示例中所做的那样指定DataBinding,则不需要任何更新机制。

希望这可以帮助您入门!


这篇文章帮了很大的忙,非常感谢。 - CorellianAle
我很高兴听到这个 :) - H W

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接