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

时间:2021-04-06 00:05:12

I am struggling to implement MVVM pattern in my current project.

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

"ClassA" continuously gets required data from a remote device and stores this data inside it's fields. It is a model, I guess. ClassA updates required information via Update method.

“ClassA”不断从远程设备获取所需数据,并将此数据存储在其字段中。我想这是一个模型。 ClassA通过Update方法更新所需信息。

"ClassB" continuously gets the data from "ClassA" and stores it in corresponding properties. Looks like it is a view model.

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

View is a simple MainWindow.xaml with a DataGrid inside.

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

I have the following questions:

我有以下问题:

1) How do I update ViewModel? Should ClassB have an Update method, which accepts an instance of ClassA and updates corresponding fields?

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

2) Where do I store an instance of ClassA? Should ClassA be a field of ClassB? If it should, then how do I update Model? I thought of something like the following:

2)我在哪里存储ClassA的实例? ClassA应该是ClassB的一个领域吗?如果应该,那我该如何更新模型?我想到了类似以下内容:

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

4) Does model have it's update method at all or model just stores the data?

4)模型是否具有它的更新方法或模型只存储数据?

3) What do I do inside MainWindow.cs, aside from windows initialization? Do I update view model (ClassB) there?

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

2 个解决方案

#1


1  

I find it best to have a object representing an item in each layer of abstraction. This includes the form of the data as it exists on the disk. Remember that in MVVM, the only real goal is to promote loose coupling between the interface(User Interface) and the implementation(ViewModel functionality).

我发现最好有一个对象代表每个抽象层中的一个项目。这包括磁盘上存在的数据的形式。请记住,在MVVM中,唯一真正的目标是促进接口(用户界面)和实现(ViewModel功能)之间的松散耦合。

For example, if I have objects stored in XML files, I will have an object in my data access layer that exists only for the proper management of the XML data. Let's call it ObjectXml. This object only contains data in the form that is native to the data on the disk. In this case, all data has a string representation, as in the XML files.

例如,如果我将对象存储在XML文件中,那么我的数据访问层中将有一个对象,该对象仅用于正确管理XML数据。我们称之为ObjectXml。此对象仅包含磁盘上数据本机格式的数据。在这种情况下,所有数据都具有字符串表示形式,如XML文件中所示。

In the model layer, you will have the data representation of the XML file in the expected data types. Let's call this Object. The property getters and setters may access and set the string representation of the data by performing conversions in both directions. This way, the data is ready to be persisted to the data source(xml file, database etc.).

在模型层中,您将在预期的数据类型中拥有XML文件的数据表示。我们称这个为对象。属性getter和setter可以通过在两个方向上执行转换来访问和设置数据的字符串表示。这样,数据就可以保存到数据源(xml文件,数据库等)。

In ObjectViewModel, properties may access those in Object. The viewmodel contains all the members for representing and modifying the model.

在ObjectViewModel中,属性可以访问Object中的属性。 viewmodel包含用于表示和修改模型的所有成员。

Note that ObjectXml is really only beneficial when you are only allowed to store string information, or when a suitable schema does not exist for your data types.

请注意,只有当您只允许存储字符串信息或者数据类型不存在合适的模式时,ObjectXml才真正有用。

At the end, you have a hierarchy of containment such as the one below:

最后,您有一个包含层次结构,如下所示:

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

Here is the model for the Xml object:

这是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(); }
    }
}

Obviously, it's not wise to name your class Object as it's a reserved word in C#. Hopefully I've given you some ideas of how to access and update data in a robust and extensible manner.

显然,将类Object命名为C#中的保留字是不明智的。希望我已经给你一些关于如何以健壮和可扩展的方式访问和更新数据的想法。

In short, you don't need an update method at all. Also, short of constants and property backing fields, there are very few reasons to need direct field access in C# MVVM.

简而言之,您根本不需要更新方法。此外,缺少常量和属性支持字段,在C#MVVM中需要直接字段访问的原因很少。

  1. See below. Do not listen to people that say the ViewModel and Model need to be decoupled. The main purpose of the model is an intermediary layer that prepares data to be saved or loaded into the program and to store data in a way that is agnostic to both the data and the program functionality(ViewModel)
  2. 见下文。不要听那些说ViewModel和Model需要解耦的人。该模型的主要目的是一个中间层,用于准备要保存或加载到程序中的数据,并以与数据和程序功能无关的方式存储数据(ViewModel)
  3. You do not need an update method. Use properties that access the data model and persist to the data storage(xml, database etc.) if needed.
  4. 您不需要更新方法。如果需要,使用访问数据模型的属性并持久保存到数据存储(xml,数据库等)。
  5. You do not need an update method.
  6. 您不需要更新方法。
  7. You should not have to do anything inside of ViewModel.cs. Only code that modifies the view should be in the codebehind. The only ViewModel you should ever access in a view is one that follows the form of MainWindowViewModel, which is more like an ApplicationViewModel that carries instances of other required viewmodels.
  8. 您不必在ViewModel.cs中执行任何操作。只有修改视图的代码才应该在代码隐藏中。您应该在视图中访问的唯一ViewModel是遵循MainWindowViewModel形式的ViewModel,它更像是一个ApplicationViewModel,它携带其他所需视图模型的实例。

Finally, don't get stuck using an overcomplicated MVVM "framework" as most of the functionality is not useful or necessary.

最后,不要使用过于复杂的MVVM“框架”,因为大多数功能都没有用或没必要。

#2


0  

Like stated in Yuris comment, you should not use any update method, but rather implement the INotifyPropertyChanged interface. Like the name says this notifies all subscribers when the value of a certain Property changed.

与Yuris注释中所述,您不应使用任何更新方法,而应实现INotifyPropertyChanged接口。就像名称所说的那样,当某个Property的值发生变化时,会通知所有订阅者。

This is a nice article which contains code to a minimalistic MVVM implementation. If you have trouble implementing the pattern from scratch, try to start with this example and replace the existing classes with your own one-by-one.

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

As to the update mechanic inside your MainWindow.cs - you don't need any, if you specify the DataBinding in your xaml code like it is done in the example linked above.

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

I hope this helps you getting started!

我希望这可以帮助您入门!

#1


1  

I find it best to have a object representing an item in each layer of abstraction. This includes the form of the data as it exists on the disk. Remember that in MVVM, the only real goal is to promote loose coupling between the interface(User Interface) and the implementation(ViewModel functionality).

我发现最好有一个对象代表每个抽象层中的一个项目。这包括磁盘上存在的数据的形式。请记住,在MVVM中,唯一真正的目标是促进接口(用户界面)和实现(ViewModel功能)之间的松散耦合。

For example, if I have objects stored in XML files, I will have an object in my data access layer that exists only for the proper management of the XML data. Let's call it ObjectXml. This object only contains data in the form that is native to the data on the disk. In this case, all data has a string representation, as in the XML files.

例如,如果我将对象存储在XML文件中,那么我的数据访问层中将有一个对象,该对象仅用于正确管理XML数据。我们称之为ObjectXml。此对象仅包含磁盘上数据本机格式的数据。在这种情况下,所有数据都具有字符串表示形式,如XML文件中所示。

In the model layer, you will have the data representation of the XML file in the expected data types. Let's call this Object. The property getters and setters may access and set the string representation of the data by performing conversions in both directions. This way, the data is ready to be persisted to the data source(xml file, database etc.).

在模型层中,您将在预期的数据类型中拥有XML文件的数据表示。我们称这个为对象。属性getter和setter可以通过在两个方向上执行转换来访问和设置数据的字符串表示。这样,数据就可以保存到数据源(xml文件,数据库等)。

In ObjectViewModel, properties may access those in Object. The viewmodel contains all the members for representing and modifying the model.

在ObjectViewModel中,属性可以访问Object中的属性。 viewmodel包含用于表示和修改模型的所有成员。

Note that ObjectXml is really only beneficial when you are only allowed to store string information, or when a suitable schema does not exist for your data types.

请注意,只有当您只允许存储字符串信息或者数据类型不存在合适的模式时,ObjectXml才真正有用。

At the end, you have a hierarchy of containment such as the one below:

最后,您有一个包含层次结构,如下所示:

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

Here is the model for the Xml object:

这是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(); }
    }
}

Obviously, it's not wise to name your class Object as it's a reserved word in C#. Hopefully I've given you some ideas of how to access and update data in a robust and extensible manner.

显然,将类Object命名为C#中的保留字是不明智的。希望我已经给你一些关于如何以健壮和可扩展的方式访问和更新数据的想法。

In short, you don't need an update method at all. Also, short of constants and property backing fields, there are very few reasons to need direct field access in C# MVVM.

简而言之,您根本不需要更新方法。此外,缺少常量和属性支持字段,在C#MVVM中需要直接字段访问的原因很少。

  1. See below. Do not listen to people that say the ViewModel and Model need to be decoupled. The main purpose of the model is an intermediary layer that prepares data to be saved or loaded into the program and to store data in a way that is agnostic to both the data and the program functionality(ViewModel)
  2. 见下文。不要听那些说ViewModel和Model需要解耦的人。该模型的主要目的是一个中间层,用于准备要保存或加载到程序中的数据,并以与数据和程序功能无关的方式存储数据(ViewModel)
  3. You do not need an update method. Use properties that access the data model and persist to the data storage(xml, database etc.) if needed.
  4. 您不需要更新方法。如果需要,使用访问数据模型的属性并持久保存到数据存储(xml,数据库等)。
  5. You do not need an update method.
  6. 您不需要更新方法。
  7. You should not have to do anything inside of ViewModel.cs. Only code that modifies the view should be in the codebehind. The only ViewModel you should ever access in a view is one that follows the form of MainWindowViewModel, which is more like an ApplicationViewModel that carries instances of other required viewmodels.
  8. 您不必在ViewModel.cs中执行任何操作。只有修改视图的代码才应该在代码隐藏中。您应该在视图中访问的唯一ViewModel是遵循MainWindowViewModel形式的ViewModel,它更像是一个ApplicationViewModel,它携带其他所需视图模型的实例。

Finally, don't get stuck using an overcomplicated MVVM "framework" as most of the functionality is not useful or necessary.

最后,不要使用过于复杂的MVVM“框架”,因为大多数功能都没有用或没必要。

#2


0  

Like stated in Yuris comment, you should not use any update method, but rather implement the INotifyPropertyChanged interface. Like the name says this notifies all subscribers when the value of a certain Property changed.

与Yuris注释中所述,您不应使用任何更新方法,而应实现INotifyPropertyChanged接口。就像名称所说的那样,当某个Property的值发生变化时,会通知所有订阅者。

This is a nice article which contains code to a minimalistic MVVM implementation. If you have trouble implementing the pattern from scratch, try to start with this example and replace the existing classes with your own one-by-one.

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

As to the update mechanic inside your MainWindow.cs - you don't need any, if you specify the DataBinding in your xaml code like it is done in the example linked above.

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

I hope this helps you getting started!

我希望这可以帮助您入门!