Инжекторы контекста xaml

В предыдущей части мы познакомились с расширениями привязки и разобрались, как их применять на практике, например, для локализации. Сегодня же продолжим изучать особенности библиотеки Aero Framework и рассмотрим довольно интересную тему об инжекции контекста данных в xaml-разметку представлений, а заодно применим познания из прошлой статьи.На практике часто встречается следующая задача: связать вью-модель, которая хранится в unity-контейнере, с одним или несколькими её представлениями (экранами). Обычно такое связывание происходит в бехаинд-коде, в результате чего у представления устанавливается нужное значение в свойство DataContext.

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

Все эти трудности так или иначе решаемы, но существует универсальный и очень простой способ их красиво разрешить. О нём и пойдет речь.7415d88d178848f6a1c93df00c75657c.jpgДля начала определимся с терминологией. Каждый элементарный визуальный контрол — это маленькое атомарное представление. Сложные комплексные представления строятся на основе простых, образуя древовидную структуру (визуальное дерево), где каждый узел также является представлением вплоть до корня. Будем различать особый род представлений — экраны, которые в том или ином виде поддерживают навигацию и зачастую являются корневыми.

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

Выглядит всё очень просто:

Получить доступ к вью-моделям из C#-кода также крайне легко: var appViewModel = Store.Get(); var userViewModel = Store.Get(); Более того, WPF позволяет выполнить инжектирование даже в привязку! Обратите внимание на строку Visibility=»{Binding ShowSlider, Source=»{Store Key=viewModels: SettingsViewModel}»…, такой гибкости тяжело достичь даже с помощью бехаин-кода, а наша запись получилась очень лаконичной.Справедливости ради нужно сказать, что парсеры разметки на многих других платформах требуют префиксы, а также не поддерживают вложенных друг в друга расширений, но эта проблема решается элементарно с помощью расширения привязки (Binding Extension):

За деталями реализации отсылаю к исходным кодам библиотеки Aero Framework, там всё очень прозрачно и понятно. Ключом же обычно является тип вью-модели или тип интерфейса, который она реализует, но ничто не запрещает использовать любые другие.То есть, чтобы связать экран приложения (страницу или окно) достаточно лишь нескольких строк:

И никакого бехаинд-кода! С контекстными меню теперь всё очень изящно: Но как красиво решаются подобные ситуации: Надеюсь, что вам уже захотелось применить на деле рассмотренный поход. Это и есть реализация принципа прямых инжекций (Direct Injections Principle), который предложен в статье. Отметим, у одной вью-модели может быть несколько представлений, однако обратная ситуация, когда представлене работает сразу с несколькими вью-моделями, на пракике редкость из-за описаных выше технических сложностей. Но с помощью прямых инжекций отношение вью-модель-представление запросто расширяется с однин ко многим до многие ко многим.Спасибо за интерес!

© Habrahabr.ru