Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю
Затем вы более глубоко погрузитесь в систему команд WPF и создадите специальные команды для инкапсуляции программной логики почти так, как поступали в главе 25 со встроенными командами. С созданием специальных команд связано несколько преимуществ, включая (помимо прочего) возможность многократного использования кода, инкапсуляцию логики и разделение обязанностей.
Наконец, вы задействуете все это в примере приложения MWM.
Введение в паттерн MWM
Прежде чем приступить к детальному исследованию уведомлений, проверки достоверности и команд в WPF, было бы неплохо пролить свет на конечную цель настоящей главы, которой является паттерн "модель-представление-модель представления" (MWM). Будучи производным от паттерна проектирования "Модель представления" (Presentation Model) Мартина Фаулера, паттерн MWM задействует обсуждаемые в главе возможности, специфичные для XAML, чтобы сделать процесс разработки приложений WPF более быстрым и ясным. Само название паттерна отражает его основные компоненты: модель (Model), представление (View) и модель представления (ViewModel).
Модель
Модель — это объектное представление имеющихся данных. В паттерне MWM модели концептуально совпадают с моделями внутри нашего уровня доступа к данным (Data Access Layer — DAL). Иногда они являются теми же физическими классами, но поступать так вовсе не обязательно. По мере чтения главы вы узнаете, каким образом решать, применять ли модели DAL или же создавать новые модели.
Модели обычно используют в своих интересах встроенную (либо специальную) проверку достоверности через аннотации данных и интерфейс
INotifyDataErrorInfo
Представление
Представление — это пользовательский интерфейс приложения, который спроектирован так, чтобы быть чрезвычайно легковесным. Вспомните о стенде меню в ресторане для автомобилистов. На стенде отображаются позиции меню и цены, а также имеется механизм взаимодействия клиента с внутренними системами. Однако в стенд не внедрены какие-либо интеллектуальные возможности, разве что он может быть снабжен специальной логикой пользовательского интерфейса, такой как включение освещения в темное время суток.
Представления MWM должны разрабатываться с учетом аналогичных целей. Любые интеллектуальные возможности необходимо встраивать в какие-то другие места приложения. Иметь прямое отношение к манипулированию пользовательским интерфейсом может только код в файле отделенного кода (например, в
MainWindow.xaml.cs
Модель представления
В WPF и других технологиях XAML модель представления служит двум целям.
• Модель представления предлагает единственное местоположение для всех данных, необходимых представлению. Это вовсе не означает, что модель представления отвечает за получение действительных данных; взамен она является просто транспортным механизмом для перемещения данных из хранилища в представление. Обычно между представлениями и моделями представлений имеется отношение "один к одному", но существуют архитектурные отличия, которые в каждом конкретном случае могут варьироваться.
• Вторая цель модели представления касается ее действия в качестве контроллера для представления. Почти как стенд меню модель представления принимает указание от пользователя и передает их соответствующему коду для выполнения подходящих действий. Довольно часто такой код имеет форму специальных команд.
Анемичные модели или анемичные модели представлений
На заре развития WPF, когда разработчики все еще были в поиске лучшей реализации паттерна MWM, велись бурные (а временами и жаркие) дискуссии о том, где реализовывать элементы, подобные проверке достоверности и паттерну "Наблюдатель". Один лагерь (сторонников анемичной (иногда называемой бескровной) модели) аргументировал, что все элементы должны находиться в моделях представлений, поскольку добавление таких возможностей к модели нарушает принцип разделения обязанностей. Другой лагерь (сторонников анемичной модели представления) утверждал, что все элементы должны находиться в моделях, т.к. тогда сокращается дублирование кода.
Конечно, фактический ответ зависит от обстоятельств. Реализация классами моделей интерфейсов
INotifyPropertyChanged
IDataErrorInfо
INotifyDataErrorInfo
На заметку! Для WPF доступны многочисленные инфраструктуры MWM, такие как MWMLite, Caliburn.Micro и Prism (хотя Prism — нечто намного большее, чем просто инфраструктура MWM). В настоящей главе обсуждается паттерн MWM и функциональные средства WPF, которые поддерживают его реализацию. Исследование других инфраструктур и выбор среди них наиболее подходящей для нужд приложения остается за вами как разработчиком.
Система уведомлений привязки WPF
Значительным недостатком системы привязки Windows Forms является отсутствие уведомлений. Если находящиеся внутри представления данные модифицируются в коде, то пользовательский интерфейс также должен обновляться программно, чтобы оставаться в синхронном состоянии с ними. Итогом будет большое количество вызовов метода
Refresh()
Refresh()
Система привязки, встроенная в приложения на основе XAML, устраняет указанную проблему за счет того, что позволяет привязывать объекты данных и коллекции к системе уведомлений, разрабатывая их как наблюдаемые. Всякий раз, когда изменяется значение свойства в наблюдаемой модели либо происходит изменение в наблюдаемой коллекции (например, добавление, удаление или переупорядочение элементов), инициируется событие (
NotifyPropertyChanged
NotifyCollectionChanged
Наблюдаемые модели и коллекции
В этом разделе вы построите приложение, в котором используются наблюдаемые модели и коллекции. Для начала создайте новый проект приложения WPF по имени
WpfNotifications
ComboBox
TextBox
MainWindow.xaml