Как быть в ситуациях, когда представление зависит от нескольких моделей в контексте MVVM?

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

Проблема в том, что данных класса Координация недостаточно для моего стиля просмотра Граница. Он имеет только свойства Ряд и Столбец, но я также хочу знать, содержит ли он Корабль, а также знать, является ли этот КорабльРаненый или затонул. В зависимости от этих значений я хочу изменить цвет Задний план моего объекта Граница.


Сценарий 1

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

Сценарий 2

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

Сценарий 3

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

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

Сценарий 4

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

Сценарий 5

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

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


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

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

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

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
150
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

Другие вопросы по теме