2017-01-03 5 views
2

У меня есть реализация ICommand, которая является автономной. Он изменяет информацию об объекте. Тот же объект привязан к View, как свойство View's ViewModel.Отзыв от ICommand

То, что я хочу достичь, - сущность (и, следовательно, ViewModel, следовательно - вид) для обновления новой информацией после выполнения команды. То, как я это понимаю, ICommand -s - улица с односторонним движением. Они изменяют базовые данные, но не должны давать прямой результат.

Итак, я достиг этого, отправив Message из командной строки в конце ее выполнения с использованием структуры MVVMLight. Модель просмотра, которая предоставляет объект, также подписывается на одно и то же сообщение и сама обновляется, когда сообщение получено (обновленная информация передается как свойство сообщения).

Дополнительным преимуществом является то, что другие модели просмотра также могут подписаться и реагировать на одно и то же событие. Тем не менее, «запахи» в этом заключается в том, что основой этой реализации является events. Из того, что я прочитал, вся концепция событий не очень хорошо вписывается в шаблон MVVM. Или перекрестная VM-коммуникация в порядке, чтобы сделать это?

Пример:

Домен Модель

  • пользователя
    • First Name
    • Last Name
    • Full Name { get { return First Name + Last Name } }

вид Модель

  • User View Model - обернут вокруг User Domain Model, но не хранит экземпляр этого
    • string First Name
    • string Last Name
    • string Full Name (Примечание: Есть ли что-нибудь о том, как она рассчитывается не знаю)
    • ICommand Change First Name
    • Метод: MapFromDomainModel(UserDomainModel). Вызывается, когда модель просмотра получает сообщение UserDomainChanged.

Команда

  • Change First Name : ICommand
    • Изменяет First Name в User Domain Model
    • Посылает UserDomainChanged(UserDomainModel) сообщение

Престол в этом примере вид Модель не знает, как Full Name рассчитывается и не/не должен знать, что, когда First Name изменяется, Full Name должна быть изменена тоже. Вот почему команда работает непосредственно над моделью домена и запускает сообщение.

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

Это хороший подход? Есть ли лучший?

+0

Я бы сказал, что этот подход полностью прекрасен. если вы не хотите добавить ссылку на viewmodel в свою команду или реализовать INotifyPropertyChanged на вашей сущности. – Jehof

+0

Обычно я изменяю некоторые свойства в своих командах, а затем обновляет представление из-за NotifyPropertyChanges и соответствующих привязок. Будет ли это достаточно или у вас более сложный сценарий? – heltonbiker

+0

@heltonbiker, поэтому ваша команда изменяет модель просмотра, а не базовую модель данных? Выполняемая мной команда выполняет постоянное изменение - против модели домена и из-за выполненной бизнес-логики другие свойства View Model могут измениться без знания Command или View Model. –

ответ

2

Как я понимаю, ICommand - это улица с односторонним движением. Они изменяют базовые данные, но не должны давать прямой результат.

Вы верны. Метод Execute интерфейса ICommand имеет тип возврата void, означающий, что он не возвращает никакого значения или результата вызывающему элементу команды.

Или перекрестная связь VM в порядке, чтобы это было сделано так?

Да. Большая разница между использованием агрегатора событий или мессенджера для связи между двумя объектами и с использованием обычного события является связыванием. Когда вы подписываетесь на обычное мероприятие, вы создаете плотную связь между издателем и подписчиком события. Абонент требует ссылки на издателя, чтобы иметь возможность подписаться на это событие, и издателю требуется ссылка на подписчика через делегата обработчика событий, чтобы иметь возможность публиковать событие. Это приводит к плотной связи между компонентами, что, в свою очередь, ведет к меньшему обслуживанию.

Внедрив агрегатор событий между издателями и подписчиками, вы можете удалить эту плотную муфту. Абонент регистрирует агрегатор событий вместо издателя, и издатель знает только об агрегаторе событий, а не о подписчиках. Пожалуйста, обратитесь к следующему сообщению в блоге, если вы хотите получить общую картину: https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/

Это хороший подход? Есть ли лучший?

Да. Использование агрегатора событий/мессенджера для обмена информацией между компонентами в слабосвязанной форме обычно является хорошим подходом. Другой вариант - использовать совместно используемую службу. Это просто класс, который обеспечивает функциональность нескольких компонентов развязанным способом.Он должен реализовать интерфейс, и вы обычно регистрируете его как одиночный элемент в контейнере IoC: https://social.msdn.microsoft.com/Forums/en-US/22907a0f-d805-4195-8272-7c284b72d2ee/example-of-using-shared-services-prism?forum=wpf

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