WPF(MVVM):在模型或视图模型

时间:2016-09-24 20:47:32

标签: c# wpf mvvm

我对WinForms编码有一些经验,但我正在尝试用WPF(和mvvm模式)来做我的新东西。 我在网上搜索互联网几天的一件事是获得以下权利:

我需要在模型中实现什么以及在视图模型中“管理存储库(模型?)数据”时的内容。

(我认为)我确实理解了mvvm的基本概念并对所有数据进行了修饰,但我很难弄清楚正确的实现。

假设我有一个现有服务(没有任何UI的应用程序),它能够从(ini)配置文件中读取值,执行其预期的功能,并将配置写入本地注册表。也许将来我想要将配置更改为存储在xml或json而不是ini中。从我的观点来看,这完全放在现有的代码中 - 假设一个带有类配置的configuration.cs文件 - 这与我下一步要实现的新的wpf控制台应用程序完全无关。

namespace ExistingConfigurationCode
{
    public enum Setting
    {   
        some,
        values
    }
    public class ConfigurationItemProperties
    {
        public property1
        public property 2
    }

    public class ApplicationConfiguration
    {
        List<ConfigurationItemProperties> config;

        public void LoadConfig()
        public void SaveConfig()
    }
}

正如刚才所说,现在我确实希望实现一个用户界面来设置这些配置。

到目前为止,我所理解的是:

  • 视图只是视图,根本不包含任何逻辑
  • viewmodel负责向视图“传递”所有需要的信息并从视图接收命令
  • 模型是我们正在处理的数据模型

我理解(以及知道如何继续)的问题是:

  • 这个现有的课程已经是我的模特吗?但是在这个类中添加所有RaisePropertyChange内容是没有意义的,因为它也在服务中使用。此外,我看到很多教程,我被告知不要在模型中添加任何代码
  • 如果现有的类应该在我的视图模型中,那么我需要什么样的模型?
  • 模型是否只有对我已经存在的类的引用,并通过某种包装器控制所有读写内容到registry / xml / ini?
  • 我在哪里添加“RaisePropertyChange”getter和setter?因为他们“控制”用户界面,我猜他们应该放在视图模型中,但我看到很多例子,他们也在模型中?

我遇到了某种困扰。 我认为绑定应该在视图和视图模型之间,因此RaisePropertyChange应该在视图模型中,但在这种情况下,我将不得不在视图模型中第二次重新创建所有内容

回应评论的其他信息

我现在明白了,我可以使用现有的代码作为模型。

除了现有的使用现有命名空间/类的“执行引擎”之外,我还必须使用UI创建两个应用程序。 “管理控制台”和最终用户控制台。
(我认为)我对管理控制台很好,因为它有一个ConfigurationItemProperties的所有属性的视图,所以我可以关注Fabios的第一个解释。 但是最终用户的第二个UI应该有一个精简的UI,可能是列表视图,每个列表视图项都有一些复选框。这是我的问题。
对于listview,我需要ObservableCollection,但是对于列表视图中的项目,我需要提到“facade”fabio。我到目前为止对吗?

如果是这样,ObservableCollection和“ConfigurationItemPropertiesFacade”正在使用“模型”,它没有任何INotifyPropertyChanged或INotifyCollectionChanges内容的实现。但我认为“集合”必须引用外观中的“单个项目”,因为集合(来自视图模型)没有引用视图模型中的外观。

2 个答案:

答案 0 :(得分:2)

尝试考虑MVVM类似于应用程序的三个层(而不是文件)。

  • 视图 - 仅包含视图逻辑的命名空间/项目(XAML和代码 后面)
  • 模型 - 名称空间/项目,其中包含所有&#34;业务逻辑&#34;
  • ViewModel - 名称空间/项目,其中包含链接View和的逻辑 模型不知道View的命名空间。另一方面,ViewModel层负责成为模型和视图之间的桥梁 - 调用模型的方法,在某些值更改为通知View有关更改时,引发PropertyChanged事件。

因此,请将所有配置逻辑保留在Model命名空间中。 如果需要在具有编辑可能性的视图中表示Model类,请在ViewModel图层中创建Facade类

public class ConfigurationItemPropertiesFacade : INotifyPropertyChanged
{
    private ConfigurationItemProperties _Model;

    public string Property1
    {
        get { return _Model.Property1; }
        set
        {
            if(Equals(_Model.Property1, value)) return;
            _Model.Property1 = value;
            RaisePropertyChanged();
        }
    }

    public ConfigurationItemPropertiesFacade(ConfigurationItemProperties model)
    {
        _Model = model;
    }
}

在视图中使用ConfigurationItemPropertiesFacade类作为ViewModel 使用这种方法,您的模型层保持干净,可以在任何地方使用。

回复评论:
所以教导告诉它不允许放置&#34;代码&#34;在模型中是错的,对吗?
再次尝试考虑ModelMVVM不是一个类/文件,而是层/名称/项目,它可以包含多个类。
没有对错 - 你可以实现你的逻辑,因为你填写了更好的套件规格。但是如果你尊重单一责任原则https://softwareengineering.stackexchange.com/a/17170/102569),那么你将把ApplicationConfiguration的责任分开(我不知道方法的内在逻辑{{1 }和Load

  • &#34;型号&#34;只代表数据的类,没有代表的类 功能只是保存数据的属性。 您已经拥有Save
  • &#34;服务&#34;包含保存和加载功能的类 配置。你的课可以分两个班。
ConfigurationItemProperties

然后,您的ViewModel将使用这些类来表示和修改UI中的配置。

// Have one responsibility take configurations as parameter and save them somewhere
public class SaveService  
{
    public void Save(List<ConfigurationItemProperties> items) {}
}

// Have one responsibility load configurations and return them to the caller
public class LoadService
{
    public List<ConfigurationItemProperties> Load() {}
}

答案 1 :(得分:1)

让我们考虑一下这些定义:

  1. 模型 - 数据访问和业务逻辑。
  2. ViewModel - 它的职责是提供模型的数据和逻辑,以便从视图中轻松消费。
  3. 我相信这些定义会给你一个明确的答案:

    ExistingConfigurationCode类应被视为模型的一部分。

    然而,更多的想法:

    • 更改INotifyPropertyChanged和INotifyCollection不仅限于DataBinding或WPF。这些界面更为通用。

    • 如果您希望模型通知其他图层或组件有关更改,那么在模型中实现INotifyPropertyChanged没有错误

    • 通常的做法是将视图直接绑定到模型实体。 ViewModel通常只是将Model中的实体作为属性公开。

    • 在ViewModel中包装模型属性是一种方法。另一种方法是在ViewModel中使用自己的支持字段分别拥有属性。您可以在用户访问页面时将ViewModel属性设置为初始值,并在用户单击保存时将编辑后的值保存回模型。