Как бороться с ситуациями, когда представление зависит от нескольких моделей в контексте MVVM? - PullRequest
0 голосов
/ 30 мая 2019

Я работаю над игрой на линкоре, используя WPF.У меня есть модель Coordinate и ViewModel , которые я связываю с объектом Grid .Эта ViewModel имеет свойство списка Coordinate объектов и описывает каждый как Border с меткой .

Проблема в том, что данных класса Coordinate недостаточно для моего стиля просмотра Border .Он имеет только свойства Row и Column , но я также хочу узнать, содержит ли он Ship , а также узнать, что это Ship Раненый или Потоплен .В зависимости от этих значений я хочу изменить Фон моего объекта Граница .


Сценарий 1

Если я свяжу свой Граница с Кораблем , тогда я потеряю привязку с объектом Координата (что важно, и моя Граница все еще зависит от него).

Сценарий 2

Если я переопределю свою ViewModel , чтобы она стала привязкой 1 к 1 для Границы (количество экземпляров моей ViewModel, чтобы соответствовать количеству экземпляров Border объектов), тогда он выглядит немного грязным и недостаточно элегантным.Но в этом случае я смогу определить все необходимые свойства, которые будут использовать мои Граница и к которым он будет привязан.

Сценарий 3

Если я создам дополнительный класскоторый был бы гибридом Coordinate и Ship , и этот класс будет использоваться в списке как свойство ViewModel , и этот список будет связан с моим Граница , тогда я вижу две проблемы:

  1. Свойства этого класса будут зависеть друг от друга.Допустим, будет свойство HasShip , а затем свойство IsShipSunk .Но последний не имеет смысла, когда первый имеет значение false.
  2. Каким-то образом мне нужно найти способ для моего Coordinate и Ship classобщаться с этим дополнительным классом, чтобы значения были синхронизированы.Похоже на дополнительную работу.

Сценарий 4

Если я изменю свой класс модели Coordinate на все необходимые свойства, то у нас возникнет та же проблема:описал в моем предыдущем «если» (первая точка).

Сценарий 5

Если я вообще не использую привязки, то я не знаю, что будет лучшей практикой (в данном случае) реализовать связывание между моим Border view и Coordinate model.Также мне нужно будет получить объект Поле битвы , к которому относится эта Координата , чтобы иметь возможность получить все объекты Корабль оттуда.И этот подход выглядит как «Почему вы выбираете WPF, если вы не используете MVVM?».Я выбрал WPF, потому что я люблю C #, а также потому, что WPF обладает великолепной архитектурой UI Controls.

Я прекрасно понимаю, что WPF и MVVM могут не подходить для таких игр, как эта, и он предназначен для разных целей.,Но я все же хотел бы найти хорошее и аккуратное решение, если оно существует.


Итак, в двух словах: как построить следующее:

  1. Пользователь нажимает на Граница (выглядит как ячейка)
  2. Выбран соответствующий Координат объект
  3. Соответствующий Поле битвы , где это Координата принадлежит выбранному
  4. Итерация Корабль объектов выполняется для проверки, если какой-либо из них содержит эту координату
  5. В зависимости от результата измените цветмоего Границы Фон ( Синий - при пропущении, Оранжевый - при попадании, Черный - при Корабль потоплен (пожалуйста, обратите внимание, я хочу все связанные Границы объекты для измененияцвет от Оранжевый до Черный когда затонул Корабль ))

Заранее большое спасибо.

1 Ответ

1 голос
/ 30 мая 2019

Если вы по какой-то причине выбрали именно это представление (список кораблей) для своего игрового состояния, вы не должны изменять его для презентации пользовательского интерфейса. То, что вы делаете в представлении, теоретически не должно влиять на вас, чтобы изменить модель.

Номер 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...