Привязка данных в XAML
156WinRT --- Привязка данных в XAML
Совместное использование объектов в файле XAML также может осуществляться через привязку данных. По сути привязка данных (data binding) связывает между собой два свойства разных объектов. Как будет показано позже, привязки данных чаще всего применяются для связывания визуальных элементов страницы с источниками данных; кроме того, они являются важной составляющей реализации популярного архитектурного паттерна MVVM (Model-View-ViewModel). Привязки также играют важную роль при определении шаблонов отображения объектов данных.
Привязки данных могут использоваться для связывания свойств двух элементов. Элемент Binding, как и StaticResource, обычно выражается в виде расширения разметки, то есть заключается в фигурные скобки. Однако элемент Binding также допускает альтернативное выражение в виде синтаксиса элементов свойств.
Используйте следующий словарь ресурсов в нашем тестовом проекте:
<ResourceDictionary ...>
<x:String x:Key="title">Настройки кистей</x:String>
<LinearGradientBrush x:Key="rainbowBrush">
<GradientStop Offset="0" Color="Red" />
<GradientStop Offset="0.17" Color="Orange" />
<GradientStop Offset="0.34" Color="Yellow" />
<GradientStop Offset="0.5" Color="Green" />
<GradientStop Offset="0.66" Color="Blue" />
<GradientStop Offset="0.83" Color="Indigo" />
<GradientStop Offset="1" Color="Violet" />
</LinearGradientBrush>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="80" />
<Setter Property="FontFamily" Value="Arial" />
</Style>
</ResourceDictionary>
Неявный стиль TextBlock не содержит свойства Foreground. Кисть LinearGradientBrush определяется для первого из четырех элементов TextBlock, использующих эту кисть, а последующие элементы TextBlock ссылаются на эту же кисть через привязку:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<TextBlock Text="{StaticResource title}"
FontSize="42"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
<TextBlock x:Name="topTxb"
Text="Текст сверху"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Foreground="{StaticResource rainbowBrush}"/>
<TextBlock Text="Текст слева"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{Binding ElementName=topTxb, Path=Foreground}" />
<TextBlock Text="Текст справа"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Foreground="{Binding ElementName=topTxb, Path=Foreground}" />
<TextBlock Text="Текст снизу"
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
<TextBlock.Foreground>
<Binding ElementName="topTxb" Path="Foreground" />
</TextBlock.Foreground>
</TextBlock>
</Grid>
У привязки данных имеется источник (source) и приемник (target). Приемником всегда является свойство, для которого устанавливается привязка, а источником - свойство, к которому оно привязывается. Источником приведенных привязок является элемент TextBlock с именем topTxb; приемниками - три элемента TextBlock, совместно использующих свойство Foreground. Два приемника представляют более стандартный способ выражения объекта Binding как расширения разметки XAML:
{Binding ElementName=topTxb, Path=Foreground}
Расширения разметки XAML всегда размещаются в фигурных скобках. В расширении разметки для Binding обычно необходимо задать пару свойств, разделяемых запятыми. Свойство ElementName обозначает имя элемента, для которого задано желаемое свойство; свойство Path предоставляет имя свойства.
При вводе расширений разметки Binding мне всегда хочется заключить значения свойств в кавычки, но это неправильно. Кавычки в выражениях привязки не нужны.
Последний элемент TextBlock демонстрирует выражение Binding в менее распространенном синтаксисе элементов свойств:
<TextBlock Text="Текст снизу"
HorizontalAlignment="Center"
VerticalAlignment="Bottom">
<TextBlock.Foreground>
<Binding ElementName="topTxb" Path="Foreground" />
</TextBlock.Foreground>
</TextBlock>
В этом синтаксисе кавычки вокруг значений свойств обязательны, т.к. это обычные атрибуты XML. Вы также можете создать объект Binding в коде и назначить его приемному свойству методом SetBinding(), определенным в FrameworkElement. При этом выясняется, что приемник привязки всегда должен быть свойством зависимости.
Свойство Path класса Binding называется так потому, что оно может содержать несколько имен свойств, разделенных точками. Например, попробуйте заменить одно из значений Text в проекте следующим значением:
Text="{Binding ElementName=topTxb, Path=FontFamily.Source}"
Первая часть Path указывает, что нам нужны данные из свойства FontFamily. Свойству задается объект типа FontFamily, содержащий с именем Source, обозначающим название семейства шрифта. Следовательно, в TextBlock будет выведен текст «Arial».
Попробуйте применить следующую конструкцию к любому элементу TextBlock в нашем проекте:
Text="{Binding RelativeSource={RelativeSource Self}, Path=FontSize}"
Здесь расширение разметки RelativeSource находится внутри расширения разметки Binding и используется для ссылки на свойство того элемента, для которого задается привязка.
StaticResource, Binding и RelativeSource составляют 60 процентов расширений разметки XAML, поддерживаемых Windows Runtime. Расширение разметки TemplateBinding мы рассмотрим позже, при рассмотрении шаблонов элементов управления.
Последнее расширение разметки используется нечасто, но в этих редких случаях оно воистину незаменимо. Допустим, вы определили для Grid неявный стиль, включающий свойство Background, и все работает, как нужно, кроме одного: по умолчанию свойству Background должно присваиваться значение null. Как задать null в разметке? А вот как:
Background="{x:Null}"
Или предположим, что вы определили неявный стиль и есть один элемент, в котором этот стиль применяться не должен. Запретите применение неявного стиля следующим образом:
Style="{x:Null}"
К настоящему моменту мы рассмотрели практически все элементы и атрибуты, встречающиеся с префиксом «x» в файлах XAML Windows Runtime. Это типы данных x:Boolean, x:Double, x:Int32, x:String, атрибуты x:Class, x:Name и x:Key, а также расширение разметки x:Null. Я не упомянул только атрибут x:Uid, которому присваивается строка, уникальная на уровне приложения; она идентифицирует ресурсы для целей локализации.