Слабосвязанные события в WPF без использования Prism
-
03-07-2019 - |
Вопрос
Я работаю над приложением WPF и использую шаблон Model-View-ViewModel.
На данный момент приложение состоит из двух модулей:
- Левая панель для просмотра дерева и выбора узла
- Главная панель для отображения содержимого выбранного узла дерева.
Я хочу, чтобы эти два модуля были разделены, но когда я выбираю узел на левой панели, мне нужно запустить событие, на которое может подписаться главная панель.Я не хочу объединять левую и главную панели, поэтому не хочу совместно использовать экземпляры классов ViewModel.
В идеале я хотел бы использовать Prism (Руководство по составным приложениям WPF), но в настоящее время я расширяю существующее приложение и не могу добавлять дополнительные зависимости.Проект также работает на .NET 3.0 (а не на 3.5), поэтому мне придется конвертировать Prism обратно в .NET 3.0, как это написано для .NET 3.5.
В Prism я бы решил эту проблему, используя слабосвязанную инфраструктуру событий.Это позволяет вам запускать событие в любом классе на любом уровне и прослушивать любое событие в любом классе на любом уровне.По сути, издатель и подписчик события разделены.
Я использую команды для достижения этой слабой связи между моим представлением и моей моделью представления, но я не уверен, как обеспечить правильную связь между представлениями.
Любые советы или предложения очень ценятся.
Я специально ищу Действительно легкая модель событий pub/sub для .NET 2.0/3.0 (без LINQ) или что-то еще для реализации перекрестной связи View (модуля) без объединения двух модулей.
Обновлять:В итоге я решил эту проблему аналогично тому, что предлагает Глен.У меня есть отдельный EventService (я называю его CommandProxy), и я передаю его каждой ViewModel через конструкторы в моем локаторе сервисов (на данный момент я использую локатор сервисов вместо IoC-контейнера).CommandProxy предоставляет набор MultiDelegateCommants, который является расширением DelegateCommand в Prism (руководство по составному WPF).По сути, он позволяет использовать команды, отделенные от визуального дерева и поддерживающие несколько подписчиков.
Решение
У вас есть контейнер IoC?Один простой подход — создать специальную службу, которая запускает событие.Агрегатор событий является универсальным, но вы можете создать конкретную службу, которая будет делать то, что вы хотите.
Например, создайте EventingService с методом OnNodeSelected.Этот метод запускает событие NodeSelected, которое отключается от службы.Затем служба регистрируется в вашем IoC-контейнере, что позволяет издателям и подписчикам получить к ней доступ.Таким образом, если, скажем, ваша MainPanel должна подписаться, то в вашу MainPanelViewModel будет добавлен EventingServiec в ее конструктор.Затем он подпишется.Другой подход, если вы используете WPF, — извлечь CompositeCommand из кода библиотеки составных приложений и предоставить службе обработки событий CompositeCommand.Затем каждый подписчик (модель представления) регистрирует свою команду в сервисе.При вызове OnNodeSelected вызывается выполнение CompositeCommand, тем самым уведомляя все заинтересованные стороны.
Мы говорим об использовании для этого вашей собственной службы в документации по составному приложению на сайте www.microsoft.com/compositewpf в разделе «Слабосвязанные события» в теме «Связь».(http://msdn.microsoft.com/en-us/library/cc707836.aspx).У Фрэнсиса Чунга также есть пост на эту тему.