5 МОДЕЛЬ ПРИВЯЗКИ ДАННЫХ WPF
Привязкой данных WPF (data binding) называется методика связывания элементов управления и интерфейсных элементов с данными.
Привязка данных применяется для отображения некоторой информации из объекта-источника в свойстве целевого объекта пользовательского интерфейса. Кроме отображения информации в элементе управления возникает задача изменения отображаемых данных. При этом необходимо проводить синхронизацию данных объекта-источника и свойства целевого объекта при изменении любого из них.
Привязка данных представляет собой отношение, которое определяет для WPF какую информацию необходимо извлечь из объекта-источника и использовать её для установки свойства целевого объекта.
Целевое свойство должно обязательно быть свойством зависимостей и, как правило, принадлежать элементу WPF. Объект-источник может быть объектом данных приложения - общедоступным свойством класса, элементом WPF, объектом данных .
При проектировании приложений возникает задача создания привязки для некоторых свойств объектов и элементов интерфейса. Такая привязка возможна только в том случае, если свойство объекта-источника является общедоступным.
Для достижения поставленной цели необходимо:
- познакомиться с основами привязки данных WPF, направлениями потока данных связывания и механизмом обновления привязок;
- изучить варианты синтаксиса привязки данных с помощью расширения разметки и свойств Binding;
- научиться разрабатывать код XAM-разметки и программный код для организации привязки данных WPF с различными направлениями потока привязки.
В методических указаниях приводится примеры реализации привязки, в которых источником данных выступают свойства элементов управления WPF, свойства объектов процедурного кода, в том числе объекты таблиц баз данных.
5.2.2 Реализация привязки данных, в качестве которых выступают свойства элементов WPF.
В данном варианте привязки данных источник и приёмник (целевой элемент) являются свойствами зависимости элементов управления WPF. Привязка данных может обеспечивать однонаправленный или двунаправленный обмен данными связанных свойств элементов. В некоторых случаях различия между источником и приёмником стираются, а иногда даже их роли меняются местами - приёмник начинает поставлять данные источнику.
Для исследования различных механизмов передачи данных необходимо создать новый проект типа WPF, использующий многостраничный интерфейс.
Шаг 1. Создать проект типа WPF Application.
Шаг 2. Удалить из состава проекта автоматически созданный мастером файл MainWindow. xaml и добавить к проекту страницу WPF с именем Page1.xaml.
Шаг 3. В файле App. xaml изменить атрибут StartupUri и добавить ресурс кисти ControlColorBrush для оформления страниц приложения.
Листинг App. xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas. /winfx/2006/xaml/presentation"
xmlns:x="http://schemas. /winfx/2006/xaml"
StartupUri="Page1.xaml" >
<Application. Resources>
<SolidColorBrush x:Key="ControlColorBrush"
Color="{x:Static SystemColors. ControlColor}" />
</Application. Resources>
</Application>
Шаг 4. В файле Page1.xaml добавить разметку, основным интерфейсным элементом которой будет <TreeView>.
<Page x:Class="WpfApplication1.Page1"
xmlns="http://schemas. /winfx/2006/xaml/presentation"
xmlns:x="http://schemas. /winfx/2006/xaml"
xmlns:mc="http://schemas. openxmlformats. org/markup-compatibility/2006"
xmlns:d="http://schemas. /expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" WindowTitle="Изучаем механизм привязки" Name="startPage" Background="{StaticResource ControlColorBrush}">
<StackPanel>
<TreeView VerticalAlignment="Top"></TreeView>
<Image VerticalAlignment="Bottom" Source="d:\NET. png" ></Image>
</StackPanel>
</Page>
5.2.2.1 Обновить значения свойств элементов WPF можно без привязки, используя события для передачи данных между элементами, как это традиционно делается в обычных приложениях.
В примере будет использована передача данных между элементами WPF <Slider>, <Label>, <TextBlock> и <TextBox>, которая осуществляется с помощью событий page2_Loaded(),slider1_ValueChanged() и TextBox_TextChanged(). События перечислены в порядке их генерации при переходе на страницу.
Шаг 1. Добавить к проекту страницу WPF с именем Page2.xaml и перенести XAML-разметку:
<Page x:Class="WpfApplication1.Page2"
xmlns="http://schemas. /winfx/2006/xaml/presentation"
xmlns:x="http://schemas. /winfx/2006/xaml"
xmlns:mc="http://schemas. openxmlformats. org/markup-compatibility/2006"
xmlns:d="http://schemas. /expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="400" Title="Page2" Name="page2" Loaded="page2_Loaded">
<Grid Margin="20">
<Grid. ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
</Grid. ColumnDefinitions>
<Grid. RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid. RowDefinitions>
<TextBlock Grid. Row="0" FontSize="16" TextAlignment="Left" VerticalAlignment="Center" Margin="5">Источник привязки данных - свойство Value элемента Slider</TextBlock>
<StackPanel Grid. Row="1" Orientation="Horizontal" Margin="5">
<Label Name="label1" FontSize="10" Foreground="Red" HorizontalAlignment="Left" VerticalContentAlignment="Center" />
<Slider Name="slider1" Maximum="60" Height="30" Width="400" BorderThickness="1" TickPlacement="TopLeft"
ValueChanged="slider1_ValueChanged">
</Slider>
</StackPanel>
<TextBlock Grid. Row="2" FontSize="16" TextAlignment="Left" VerticalAlignment="Center" Margin="5">Приёмники - свойство Content элемента Label и свойство FontSize элемента TextBlock</TextBlock>
<TextBlock Grid. Row="3" Name="textBlock1" Margin="5" Foreground="Red" FontSize="10"></TextBlock>
<TextBox Grid. Row="4" Name="textBox1" Margin="0" Foreground="Red" FontSize="14" BorderBrush="DarkBlue" TextChanged="TextBox_TextChanged"></TextBox>
</Grid>
</Page>
Шаг 2. С помощью контекстного меню поля разметки Navigate to Event Handler добавить заготовки обработчиков событий Loaded="page2_Loaded", ValueChanged="slider1_ValueChanged" и TextChanged="TextBox_TextChanged" в файл Page2.xaml. cs.
Шаг 3. Перенести фрагменты нижеследующего процедурного кода в заготовки обработчиков событий файла Page2.xaml. cs:
private void page2_Loaded(object sender, RoutedEventArgs e)
{
// Инициализация Page2
// Явное приведение типов
int value = Convert. ToInt32(textBlock1.FontSize);
// Тип int приводится к double по умолчанию
slider1.Minimum = value;
// Content имеет тип Object и принимает все типы
label1.Content = value. ToString();
textBlock1.Text = "FontSize=" + label1.Content;
}
private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
// Событие генерируется, а элементы ещё не созданы
if (!this. IsLoaded)
return;
// Получаем указатель на источник события явно
Slider slider = (Slider)sender;
// Явное приведение типов
int value = (int)slider. Value;
// Content имеет тип Object и принимает все типы
label1.Content = value;
label1.FontSize = value;
textBlock1.Text = "FontSize=" + label1.Content;
// Тип int приводится к double неявно
textBlock1.FontSize = value;
textBox1.Text = Convert. ToString(value);
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
// Получаем указатель на источник события явно
TextBox textBox = (TextBox)sender;
// Строка не должна быть пустой, но фильтрация не цифровых символов не выполняется
if (textBox. Text!= "")
{
slider1.Value = Convert. ToDouble(textBox. Text);
}
}
Шаг 3. В файле Page1.xaml добавить в разметку дерева <TreeView> два вложенных элемента с заголовком <TreeViewItem>, внутренний элемент содержит ссылку <Hyperlink>:
<TreeView VerticalAlignment="Top">
<TreeViewItem Header="Привязка элемента WPF к элементу WPF" FontSize="14" FontWeight="ExtraBold" Foreground="Navy" IsExpanded="True">
<TreeViewItem Header="Передача данных между элементами с использованием событий" FontWeight="Normal" IsExpanded="True">
<Hyperlink NavigateUri="Page2.xaml">Пример №1 без привязки</Hyperlink>
</TreeViewItem>
</TreeViewItem>
</TreeView>
Шаг 4. Запустить проект на выполнение. Рисунок 5.1 иллюстрирует стартовое окно приложения.

Рисунок 5.1
Шаг 5. Выполнить переход на страницу с примером №1. Рисунок 5.2 иллюстрирует результаты передачи данных между элементами.
При перемещении ползунка осуществляется передача значения свойства slider1.Value другим элементам, которые можно рассматривать в качестве приёмников. Один из этих элементов <TextBox> может выступать в качестве источника при вводе строки с числом, как иллюстрирует рисунок 5.3.

Рисунок 5.2

Рисунок 5.3
При вводе строки в <TextBox> генерируется обратная последовательность событий от источника TextBox_TextChanged к приёмнику slider1_ValueChanged.
5.2.2.2 Однонаправленная привязка может быть выполнена на основе разметки по синтаксису элементов сложных свойств.
Для изучения этой возможности необходимо выполнить следующие шаги.
Шаг 1. Добавить в состав проекта страницу WPF с именем Page3.xaml и перенести XAML-разметку:
<Page x:Class="WpfApplication1.Page3"
xmlns="http://schemas. /winfx/2006/xaml/presentation"
xmlns:x="http://schemas. /winfx/2006/xaml"
xmlns:mc="http://schemas. openxmlformats. org/markup-compatibility/2006"
xmlns:d="http://schemas. /expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Title="Page3" >
<StackPanel>
<TextBlock FontSize="16" TextAlignment="Left" Margin="5">
Однонаправленная привязка на основе разметки по синтаксису элементов сложных свойств.<LineBreak/> Источник привязки данных - свойство Value элемента Slider.<LineBreak/> Приёмники привязки сложные свойства элементов Label. Content и TextBlock. FontSize.
</TextBlock>
<StackPanel Orientation="Horizontal" Margin="5">
<Label Width="40" ContentStringFormat="F0">
<Label. Content>
<Binding ElementName="slider1" Path="Value" Mode="OneWay" />
</Label. Content>
</Label>
<Slider Name="slider1" Height="30" Width="400" Minimum="10" Maximum="60" TickFrequency="2" TickPlacement="Both" />
</StackPanel>
<TextBlock Margin="10" Foreground="Red">
<TextBlock. FontSize>
<Binding ElementName="slider1" Path="Value" Mode="OneWay" />
</TextBlock. FontSize>
Строка текста
</TextBlock>
</StackPanel>
</Page>
Элементы привязки <Binding> указаны в соответствии с синтаксисом сложных свойств <Label. Content> и <TextBlock. FontSize>, которые выступают в роли приёмников:
<Binding ElementName="slider1" Path="Value" Mode="OneWay" />
Свойство ElementName привязки указывает на элемент-источник slider1, а свойство Path - на свойство зависимости Value из источника привязки данных. Свойство Mode устанавливает однонаправленный поток данных OneWay от источника <Slider> к приёмникам <Label. Content> и <TextBlock. FontSize>.
Шаг 2. В файле Page1.xaml в разметку дерева <TreeView> добавить вложенный элемент <TreeViewItem>, который содержит ссылку <Hyperlink>:
<TreeViewItem Header="Однонаправленная привязка на основе разметки по синтаксису элементов сложных свойств " FontWeight="Normal" IsExpanded="True">
<Hyperlink NavigateUri="Page3.xaml">Пример №2 привязки</Hyperlink>
</TreeViewItem>
Внешний вид страницы иллюстрирует рисунок 5.4.

Рисунок 5.4
Шаг 3. Запустить проект на выполнение. Рисунок 5.5 иллюстрирует результат работы привязки по синтаксису элементов сложных свойств без написания процедурного кода.

Рисунок 5.5
Свойство ContentStringFormat="F0" в элементе <Label> запрещает выводить дробную часть значения ползунка.


