Связывание элементов

52

Простейший сценарий привязки данных подразумевает ситуацию, когда исходным объектом является элемент WPF, а исходным свойством — свойство зависимости. Причина в том, что свойство зависимости имеет встроенную поддержку уведомлений об изменениях. В результате, когда значение свойства зависимости изменяется в исходном объекте, привязанное свойство целевого объекта немедленно обновляется. Это именно то, что требуется, и происходит оно без необходимости построения любой дополнительной инфраструктуры.

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

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

Чтобы понять, как привязывать один элемент к другому, рассмотрим простое окно. Оно содержит два элемента управления: Slider (ползунок) и TextBlock (текстовый блок) с единственной строкой текста. Перемещение ползунка вправо приводит к немедленному увеличению размера шрифта текста, а перемещение влево — к уменьшению размера шрифта.

<Slider Margin="5" Minimum="1" Maximum="72" Value="12" Name="sld"
                TickFrequency="5" TickPlacement="BottomRight"></Slider>
        <TextBlock Margin="5" Text="Какой-то текст" 
                   FontSize="{Binding ElementName=sld, Path=Value}"></TextBlock>
Элементы управления, объединенные привязкой

Привязка определена в элементе TextBlock. Вместо установки FontSize с использованием литерального значения применяется выражение привязки.

Выражения привязки данных используют расширение разметки XAML (и потому помещаются в фигурные скобки). В начале идет слово Binding, потому что создается экземпляр класса System.Windows.Data.Binding. Хотя объект Binding может быть сконфигурирован различными способами, в данной ситуации необходимо установить только два свойства: ElementName, которое указывает исходный элемент, и Path, указывающее свойство в исходном элементе.

Вместо Property используется Path, потому что Path может указывать на свойство свойства (например, FontFamily.Source) или индексатор, используемый свойством (например, Content.Children[0]). Путь может включать множество фрагментов, переходящих от свойства к свойству, и т.д.

Чтобы сослаться на присоединенное свойство (свойство, которое определено в другом классе, но применяется к привязанному элементу), имя свойства должно быть указано в круглых скобках. Например, в случае привязки к элементу, помещенному в Grid, путь (Grid.Row) извлекает номер строки, в которой он находится.

Ошибки привязки

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

Например, попытка привязки к несуществующему свойству приводит к выводу в выходное окно следующего сообщения:

Шаг с заходом: обход кода, не являющегося кодом пользователя "WpfApplication1.App.App"
Шаг с заходом: обход кода, не являющегося кодом пользователя "WpfApplication1.App.InitializeComponent"
System.Windows.Data Error: 40 : BindingExpression path error: 
'SliderValue' property not found on 'object' ''Slider' (Name='sld')'
.BindingExpression:Path=SliderValue; DataItem='Slider' (Name='sld'); target element 
is 'TextBlock' (Name=''); target property is 'FontSize' (type 'Double')

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

Пройди тесты
Лучший чат для C# программистов