Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

Конечно, фактический ответ зависит от обстоятельств. Реализация классами моделей интерфейсов

INotifyPropertyChanged
,
IDataErrorInfо
и
INotifyDataErrorInfo
гарантирует, что соответствующий код близок к своей цели (как вы увидите далее в главе) и реализован только однократно для каждой модели. Другими словами, есть ситуации, когда сами классы моделей представлений необходимо разрабатывать как наблюдаемые. По большому счету вы должны самостоятельно выяснить, что имеет больший смысл для приложения, не приводя к чрезмерному усложнению кода и не принося в жертву преимущества MWM.

На заметку! Для WPF

доступны многочисленные инфраструктуры MWM, такие как MWMLite, Caliburn.Micro и Prism (хотя Prism — нечто намного большее, чем просто инфраструктура MWM). В настоящей главе обсуждается паттерн MWM и функциональные средства WPF, которые поддерживают его реализацию. Исследование других инфраструктур и выбор среди них наиболее подходящей для нужд приложения остается за вами как разработчиком.

Система уведомлений привязки WPF

Значительным недостатком системы привязки Windows Forms является отсутствие уведомлений. Если находящиеся внутри представления данные модифицируются в коде, то пользовательский интерфейс также должен обновляться программно, чтобы оставаться в синхронном состоянии с ними. Итогом будет большое количество вызовов метода

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

Система привязки, встроенная в приложения на основе XAML, устраняет указанную проблему за счет того, что позволяет привязывать объекты данных и коллекции к системе уведомлений, разрабатывая их как наблюдаемые. Всякий раз, когда изменяется значение свойства в наблюдаемой модели либо происходит изменение в наблюдаемой коллекции (например, добавление, удаление или переупорядочение элементов), инициируется событие (

NotifyPropertyChanged
либо
NotifyCollectionChanged
). Инфраструктура привязки автоматически прослушивает такие события и в случае их появления обновляет привязанные элементы управления. Более того, разработчики имеют контроль над тем, для каких свойств выдаются уведомления. Выглядит безупречно, не так ли? На самом деле все не настолько безупречно. Настройка наблюдаемых моделей вручную требует написания довольно большого объема кода. К счастью, как вы вскоре увидите, существует инфраструктура с открытым кодом, которая значительно упрощает работу.

Наблюдаемые модели и коллекции

В этом разделе вы построите приложение, в котором используются наблюдаемые модели и коллекции. Для начала создайте новый проект приложения WPF по имени

WpfNotifications
. В приложении будет применяться форма "главная-подробности", которая позволит пользователю выбирать объект автомобиля в элементе управления
ComboBox
и просматривать детальную информацию о нем в расположенных ниже элементах управления
TextBox
. Поместите в файл
MainWindow.xaml
следующую разметку:

<Grid IsSharedSizeScope="True" Margin="5,0,5,5">

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

</Grid.RowDefinitions>

<Grid Grid.Row="0">

<Grid.ColumnDefinitions>

<ColumnDefinition Width="Auto"

SharedSizeGroup="CarLabels"/>

<ColumnDefinition Width="*"/>

</Grid.ColumnDefinitions>

<Label Grid.Column="0" Content="Vehicle"/>

<ComboBox Name="cboCars" Grid.Column="1"

DisplayMemberPath="PetName" />

</Grid>

<Grid Grid.Row="1" Name="DetailsGrid">

<Grid.ColumnDefinitions>

<ColumnDefinition Width="Auto"

SharedSizeGroup="CarLabels"/>

<ColumnDefinition Width="*"/>

</Grid.ColumnDefinitions>

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

</Grid.RowDefinitions>

<Label Grid.Column="0" Grid.Row="0" Content="Id"/>

<TextBox Grid.Column="1" Grid.Row="0" />

<Label Grid.Column="0" Grid.Row="1" Content="Make"/>

<TextBox Grid.Column="1" Grid.Row="1" />

<Label Grid.Column="0" Grid.Row="2" Content="Color"/>

<TextBox Grid.Column="1" Grid.Row="2" />

<Label Grid.Column="0" Grid.Row="3" Content="Pet Name"/>

<TextBox Grid.Column="1" Grid.Row="3" />

<StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4"

HorizontalAlignment="Right" Orientation="Horizontal" Margin="0,5,0,5">

<Button x:Name="btnAddCar" Content="Add Car" Margin="5,0,5,0" Padding="4, 2" />

<Button x:Name="btnChangeColor" Content="Change Color" Margin="5,0,5,0"

Padding="4, 2"/>

</StackPanel>

</Grid>

</Grid>

Окно

должно напоминать показанное на рис. 28.1.

Свойство

IsSharedSizeScope
элемента управления
Grid
заставляет дочерние сетки разделять размеры. Элемент
ColumnDefinitions
, помеченный как
SharedSizeGroup
, автоматически получит ту же самую ширину без каких-либо потребностей в программировании. В рассматриваемом примере, если размер метки Pet Name (Дружественное имя) изменяется из-за более длинного значения, тогда соответствующим образом корректируется и размер колонки Vehicle (Автомобиль), который находится в другом элементе управления
Grid
, сохраняя аккуратный внешний вид окна.

Поделиться с друзьями: