Подтвердить что ты не робот

Конкретные примеры совместного использования состояний между несколькими режимами просмотра (WPF MVVM)

У меня есть проект WPF/Entity Framework (4.0) со многими объектами. Я хотел бы создать приложение, чтобы у меня могло быть состояние выбора объекта, совместно используемого в моделях viewmodels.

Например: у нас есть классы Cars, Drivers, Passengers и Cargo. У нас также есть UserControls для CarList, DriverList и т.д. И окна редактора для CarEditor, DriverEditor и т.д. Кроме того, у нас есть модели просмотра для всех этих моделей (CarListViewModel, DriverListViewModel, CargoEditorViewModel и т.д.). Все это представляет собой стыковочный интерфейс, в котором пользователь может открывать несколько списков объектов, редакторов и зрителей.

То, что я хочу, - это конкретный пример кода, как подключить несколько моделей просмотра, чтобы выбор автомобиля в CarList заставил этот автомобиль работать в режиме CarEditorView, но также должен быть выбран в любом другом представлении, для которого контекст действителен (например, DriverByCarView или просто DriverList, если есть предикат фильтра).

На этот вопрос предлагается ряд предложений и обсуждений. Двумя способами, которые кажутся доминирующими, являются:

  • 3018307: обсуждает разделение состояний, указав подсистему обмена сообщениями
  • 1159035: обсуждает совместное использование состояний с помощью встроенной модели просмотра

Один из этих подходов лучше другого?

Есть ли у кого-нибудь конкретный пример обоих/обоих этих методов в виде проекта с записью или небольшим кодом?

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

Спасибо


В случае, если кто-то заинтересован, вот несколько других подобных обсуждений:

  • 3816961: обсуждает возврат нескольких режимов просмотра в зависимости от типа объекта (т.е. набор произвольных типов, привязанных к определенному интерфейсу).
  • 1928130: обсуждает, является ли хорошей идеей объединить viewmodels как свойства других режимов просмотра (например, модель представления MainWindow, состоящая из панельных моделей просмотра).
  • 1120061: в основном обсуждается, следует ли использовать стратегию viewmodel-per-model или стратегию viewmodel-for-view-element.
  • 4244222: обсуждает, нужно ли встраивать модели представления при использовании иерархии вложенных объектов.
  • 4429708: обсуждает совместное использование коллекций между режимами просмотра напрямую, но не вдаваясь в подробности.
  • Элемент списка: обсуждает управление несколькими выборами в пределах одной модели просмотра.
4b9b3361

Ответ 1

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

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

В Prism мессенджер - это EventAggregator и используется для публикации и подписки на сообщения.

Обновление

Помимо архитектурных преимуществ, которые приносит EventAggregator, он также реализует слабые события, чтобы предотвратить проблемы с утечкой памяти с подписчиками, которые явно не подписываются.

Для документации EventAggregator см. следующее:

http://msdn.microsoft.com/en-us/library/ff649187.aspx

Prism:

http://compositewpf.codeplex.com/

Призматический пример

public class ViewModel1
{
    private readonly IEventAggregator _eventService;
    private Car _selectedCar;

    public ViewModel1(IEventAggregator eventService)
    {
        _eventService = eventService;
    }

    //Databound property...
    public Car SelectedCar
    {
        set
        {
            _selectedCar = value;

            var msg = new CarSelectedMessage { Car = _selectedCar };

            _eventService.GetEvent<CarSelectedEvent>().Publish(msg);
        }
    }
}

public class ViewModel2
{
    public ViewModel2(IEventAggregator eventService)
    {
        eventService.GetEvent<CarSelectedEvent>().Subscribe(msg =>
        {
            //DoStuff with msg...
        });
    }
}

public class Car {}

public class CarMessage
{
    public Car Car { get; set; }
}

public class CarSelectedEvent : CompositePresentationEvent<CarMessage> {}