Как мы можем реализовать распространение уведомлений об изменениях для WPF и SL в шаблоне MVVM? - PullRequest
2 голосов
/ 31 декабря 2010

Вот пример сценария, нацеленного на разработку MVVM WPF / SL:

  • Просмотр привязок данных для просмотра модели Свойство "Цель"
  • "Цель«выставляет поле объекта с именем« data », которое существует в локальной модели приложения, и называется« Original »
  • , когда« Original »изменяется, оно должно вызывать уведомление для модели представления изатем распространите это уведомление об изменении в View.

Вот решения, которые я придумала, но мне не все из них нравятся.Я ищу другие идеи, и к тому времени, когда мы придумаем что-то невероятное, я уверен, что Microsoft выпустит .NET 5 с расширениями WPF / SL для улучшения инструментов для разработки MVVM.

На данный момент вопрос звучит так: «Что вы сделали для решения этой проблемы и как она сработала для вас?»

Вариант 1.

Предложение:

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

Почему мне это не нравится:

Изменения не всплывают естественным образом, объекты должны явно наблюдаться, если данные переходят на новый источник, события должны быть отключены-регистрация / регистрация.

Почему мне это нравится:

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

Вариант 2.

Предложение:

Присоединить обработчик к data sСобытие PropertyChanged, которое повторно вызывает событие во всех свойствах, используя имя свойства name.

Почему мне это не нравится:

По сути, это то же самое, что и option1, но менее разумно и вынуждает меня никогда не менять имена своих свойств, поскольку они должны совпадать с именами свойств в data

Почему мне это нравится:

Это очень легко настроить, и мне не нужно об этом думать ... Опять же, если я пытаюсь думать и меняю имена на вещи, которые имеют смысл, я стреляю в себяногу, и тогда я должен думать об этом!

Вариант 3.

Предложение:

Наследовать мой взглядмодель из объекта зависимости и напрямую уведомлять источники привязки об изменениях.

Почему мне это не нравится:

Я даже на 100% не уверен в свойствах зависимости /оbjects может сделать это, это была просто мысль, чтобы разобраться.Также я лично не чувствую, что типы WPF / SL, такие как Dep Obj, принадлежат на уровне модели представления.

Почему мне это нравится:

ЕСЛИ оно имеетвозможность, которую я ищу, это хороший ответ!минус эта досадная проблема с наслоениями.

Вариант 4.

Предложение:

Используйте постоянную систему обмена сообщениями агента, основанную наЗадайте Parallels DataFlow Library, чтобы распространить все через связанную конвейерную обработку.

Почему мне это не нравится:

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

Почему мне это нравится:

У него есть возможность разрешитьмне сделать ОЧЕНЬ забавные манипуляции с моделью данных на основе push и использованием ActionBlocks в качестве проверочных и установочных параметров, чтобы затем в частном порядке изменить свойства модели представления и явно контролировать уведомления PropertyChanged.

1 Ответ

1 голос
/ 31 декабря 2010

Я в основном использовал Вариант 4. Когда состояние приложения изменяется (и, следовательно, изменяются данные в модели), я отправляю уведомление, используя MVVM Foundation Messenger.ViewModels, которым нужны эти данные для привязки данных, может затем подписаться на это сообщение, соответствующим образом обновить локальные свойства и вызвать RaisePropertyChanged()*, чтобы уведомить систему привязки о том, что произошло изменение.

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

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

В недавнем приложении, над которым я работал, я решил централизовать все изменения данных приложения в одном большом, но простом классе, называемом AppDataManager.Этот класс имеет поля для всех данных, которые должны отслеживаться.После некоторой инициализации при запуске изменения данных всегда или почти всегда инициируются пользователем.Благодаря двустороннему связыванию данных пользовательские действия приводят к изменению свойства в ViewModel.Это изменение затем пересылается на AppDataManager с помощью сообщения.AppDataManager затем изменяет собственную ссылку на эти данные и отправляет сообщение, чтобы уведомить любые заинтересованные ViewModels, что эти данные изменились.Я обычно включаю измененные данные в сообщение (поэтому получателю не нужно знать, где найти данные).Я не уверен, что это лучшая архитектура, и я не знаю, как она будет масштабироваться для больших приложений, но пока мне кажется, что она хорошо работает.

Очевидно, альтернативный подход к централизациибудет сетевой подход, где ViewModels подписываются непосредственно на сообщения друг друга.Это очень хорошо может сработать, но я не пробовал.Я обнаружил, что я мог бы реализовать систему отмены намного проще, если бы все изменения данных были направлены через один класс.Мои данные также были иерархически упорядочены, поэтому изменения в верхней части иерархии должны были бы каскадно переходить к «листьям» (например, если вы меняете карту, вам нужно изменить дороги, и если вы измените дороги, у вас естьизменить путевые точки, составляющие дороги).Мне было гораздо проще централизованно управлять этим каскадированием, чем выбирать произвольную ViewModel для этого.

*RaisePropertyChanged является членом ObservableObject, который также является частью MVVM Foundation.Все ViewModels в моем проекте наследуются от ObservableObject.

Примечание: Я думаю о переходе с MVVM Foundation на MVVM Light Toolkit , который, кажется,дальнейшее развитие фонда MVVM.

...