gpt4 book ai didi

wpf - WPF MVVM : an issue of organising ViewModels

转载 作者:行者123 更新时间:2023-12-03 10:33:55 24 4
gpt4 key购买 nike

我认为我面临的是设计问题-我认为这个问题已经被很多人解决了很多次,因为这似乎很普遍。

我将WPF与XAML和简单的MVVM方法结合使用,以供记录。

我的意图是使用WPF中的MVVM设计模式创建TreeView。

我有一个包含两个类的数据模型:场景和角色。每个场景都包含许多角色。

我创建了一个CharacterViewModel,它非常简单(并且运行良好)。自然地,这将环绕现有的Character类。

Scene类让我感到困惑。据我了解,SceneViewModel应该环绕Scene类,就像CharacterViewModel对Character类所做的一样。但是不同之处在于,场景包含角色列表,因此增加了exta的复杂性。

这两个选项似乎如下:

选项1:场景包含角色列表,因此SceneViewModel也将其作为它的一部分。

选项2:场景包含CharacterViewModel的列表,因此SceneViewModel也将其作为它的一部分。

老实说,我不确定该去哪一个。我怀疑这是第二个(而且this教程似乎同意(示例6是我所指的部分的标题)。第一个选项似乎会使事情真的很奇怪(以及为什么还要创建CharacterViewModel?)但是第二个似乎很奇怪,因为在程序的模型部分应该包含什么以及在程序的 View 模型部分应该包含什么,这似乎使人感到困惑。

我希望我已经解释了我的问题,也希望有人可以提供一些帮助。

谢谢。

最佳答案

首先让我谈谈这一声明:

...the SceneViewModel should wrap around the Scene class, just as the CharacterViewModel did for the Character class.



这不是真的。应该为每个 View 创建 View 模型。您的模型类可能一对一,但这并不是MVVM想法的严格部分。一个 View 可能需要显示来自多个“根”模型元素(与您的应用程序中的父子关系没有显式关系的模型元素)的数据,或者您可能需要为一个模型元素拥有多个 View 。并且进一步详细说明,理想情况下,每个 View 模型应尽可能与 View 技术隔离(即,单个 View 模型足以创建WinForms View 或WPF View 或HTML View 等)。

例如,您可能有一个显示 Scene类中的数据的 View 。该 View 还可能显示 Character中每个 Scene的数据。用户可能能够单击 Character并打开仅针对该 Character的 View (例如,弹出窗口)。在这种情况下,可能会有单独的 View 模型来表示根 View 和弹出窗口中的 Character。我倾向于根据 View 的根来命名 View 模型类。对于像您这样的应用程序,我会有类似 SceneViewModelSceneCharacterViewModel(或 SceneViewModel_CharacterCharacterInSceneViewModel -这些名称中的任何一个都表明该类用于在 Character的 View 中表示 Scene)。这将使该 View 模型与弹出 View (以 Character为中心,并被命名为 CharacterViewModel(甚至是 CharacterDialogViewModelCharacterPopupViewModelCharacterEditorViewModel)类似。

使模型与 View 模型之间的集合保持同步很烦人,但通常是必要的。请注意,并非总是必要的-在某些情况下,您会发现不需要向模型添加其他 View 模型功能,因此在这种情况下 View 直接引用模型是完全可以接受的。

保持模型集合和 View 模型集契约(Contract)步的示例:假设您的根 SceneView的每个 Character都有一个按钮。该按钮将显示 Character的弹出窗口。进一步假设 Character弹出窗口没有类似的按钮,因为这样它将允许弹出窗口打开另一个弹出窗口(等)。您可能需要使用 ICommand实现,以便可以将按钮绑定(bind)到命令。 ICommand实例绝对不在模型中(即使命令可能在模型上调用公共(public)方法)。适当的位置应该在 Character View 中的 Scene的 View 模型中(而不是弹出窗口中 Character的 View 模型中)。对于模型中的每个 Character,您都需要创建一个引用 Character的 View 模型并存储其他 View 模型内容( ICommand对象)。

这意味着,随着 Character的添加/从 Scene中删除,您需要专门为 Character View 模型中的 Scene创建 View 模型。我通常会这样做:
  • 在构造时(或 View 模型最初接收模型的任何时间),为每个子对象创建一个 View 模型。将这些 View 模型放入带有ReadOnlyCollection<SceneCharacterViewModel>之类的公共(public)属性中。您的 View 将绑定(bind)到该集合。
  • 在将子对象添加到模型中时(内部或通过模型上的公共(public)方法),模型应以适当的方式通知 View 模型。由于模型不应该直接引用 View 模型(甚至不通过接口(interface),模型也应该完全起作用,即使在没有 View 模型的非UI上下文中也是如此),最合适的方法是使用事件。您可以通过以下两种方法执行此操作:
  • 公开模型中的事件,例如CharacterAddedCharacterRemoved甚至CharactersUpdated(这些事件的最后一个将能够使用单个事件传达添加或删除的信息)
  • View 模型中最常用的
  • ObservableCollection(或ReadOnlyObservableCollection)也可以在模型中使用,在这种情况下,所有事件都已经可用。缺点是处理这些集合类型的事件并不是最简单的事情。
  • 完全不同的第三个选项:如果 View 模型或命令实例直接调用sceneModel.AddCharacter(newCharacterModel)之类的方法,则只需在此行之后立即更新 View 模型,而无需任何事件。我经常因为这种方法很简单而开始使用这种方法,但是我几乎总是总是使用前两种技术之一,因为这些技术即使在内部进行更新的情况下,也允许模型通知 View 模型(例如,在内部进行更新)。对定时事件或模型控制的异步操作的响应)。

  • 综上所述,这就是您的应用程序看起来像“纯” MVVM架构的样子。纯度可能是以简单为代价的,因此有时最好在这里和那里走一些捷径。一个常见的快捷方式:在WPF中,仅将所有子窗口小部件内容放在用来显示 child 的 ItemTemplateItemsControl中,而不是为 child 创建单独的 UserControl,通常会更容易。

    enter image description here

    关于wpf - WPF MVVM : an issue of organising ViewModels,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42566082/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com