【问题标题】:How to deal with situations when a view depends on multiple models in MVVM context?如何处理视图依赖于 MVVM 上下文中的多个模型的情况?
【发布时间】:2019-05-30 21:21:33
【问题描述】:

我正在使用 WPF 开发战舰游戏。我有一个 Coordinate 模型和我与 Grid 对象绑定的 ViewModel。此 ViewModel 具有 Coordinate 对象列表的属性,并将每个对象描述为带有 LabelBorder。 p>

问题是 Coordinate 类的数据不足以满足我的 Border 视图样式。它只有 RowColumn 属性,但我还想知道它是否包含 Ship 以及是否该 Ship 受伤沉没。根据这些值,我想更改 Border 对象的 Background 颜色。


场景 1

如果我将 BorderShip 绑定,那么我将失去与 Coordinate 对象的绑定(这很重要,我的 >边界仍然取决于它)。

场景 2

如果我重新定义我的 ViewModel 以成为 Border 的一对一绑定(我的 ViewModel 实例数以匹配多个Border 对象的实例)然后感觉有点脏,不够优雅。但在这种情况下,我将能够定义我的 Border 使用并将绑定到的所有必需属性。

场景 3

如果我创建一个额外的类,它将是 CoordinateShip 的混合体,并且该类将在列表中用作 ViewModel 属性,并且该列表将与我的 Border 绑定,然后我看到两个问题:

  1. 此类的属性将相互依赖。让我们 说会有一个属性 HasShip 然后它有一个属性 IsShipSunk。但是当第一个时,后一个没有意义 值为 false。
  2. 不知何故,我需要为我的 CoordinateShip 类构建一种方法 与该附加类进行通信,以便值在 同步。感觉像是一项额外的工作。

场景 4

如果我更改我的 坐标 模型类以包含所有必需的属性,那么我们将遇到我在之前的“如果”(第一点)中描述的相同问题。

场景 5

如果我根本不使用绑定,那么我不知道在我的 Border 视图和 Coordinate 之间实现链接的最佳做法(在这种情况下)是什么 模型。我还需要获取 Coordinate 所属的 Battlefield 对象,以便能够从那里获取所有 Ship 对象。这种方法感觉就像“如果您不使用 MVVM,为什么要选择 WPF?”。我之所以选择 WPF,是因为我喜欢 C#,还因为 WPF 具有出色的 UI 控件架构。

我非常清楚 WPF 和 MVVM 可能不适合像这样的游戏,而且它是为不同的目的而设计的。但我仍然想找到一个很好的解决方案,以防万一。


所以,简而言之:如何构建以下内容:

  1. 用户点击边框(看起来像一个单元格)
  2. 获取对应的坐标对象
  3. 坐标所属的对应战场 已提取
  4. Ship 对象的迭代被执行以检查是否有任何 它们包含该坐标
  5. 根据结果更改我的边框颜色 背景蓝色 - 未命中时,橙色 - 被击中时,黑色 - 被击中时 Ship 沉没(请注意,我希望 all 相关的 Border 对象发生变化 当沉没时,颜色从橙色变为黑色))

非常感谢。

【问题讨论】:

    标签: c# wpf mvvm data-binding architecture


    【解决方案1】:

    如果您出于充分的理由为游戏状态选择了该特定表示(舰船列表),则不应为 UI 表示更改它。您在视图中所做的操作理论上不应影响您更改模型。

    3 号是最适合 MVVM 开发的解决方案。您创建一个真实的视图模型来包装您的实际模型。

    请记住,您不需要保留两种状态,您的属性可以依赖于其他属性和对象。您可以在字段中引用您的船舶列表,并根据它所包含的内容生成其属性,例如:

    public class Field
    {
        GameStateModel GameState { get; set; }
    
        public int Row { get; set; }
        public int Col { get; set; }
    
        private Ship ShipOnField
        {
            get
            {
                return GameState.Ships.Where(s => s.Row == Row && s.Col == Col).FirstOrDefault();
            }
        }
    
        public bool HasShip
        {
            get
            {
                return ShipOnField != null;
            }
        }
    
        public bool IsShipSunk
        {
            get
            {
                return ShipOnField != null && ShipOnField.Ded;
            }
        }
    }
    

    这个解决方案有两个问题。一是性能。另一个是更新模型更改视图的问题。您要么必须在每次更改时更新所有内容,要么将模型中的更改链接到您的 ViewModel 更新。

    【讨论】:

      猜你喜欢
      • 2019-06-24
      • 2018-08-25
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 2021-04-24
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多