умолчанию все определения типов C#/XAML являются открытыми (
public
), а члены — внутренними (
internal
). Однако для показанного выше определения XAML результирующий автоматически сгенерированный файл содержит внутренний тип класса с открытой переменной-членом
Button
:
internal partial class MainWindow : System.Windows.Window,
System.Windows.Markup.IComponentConnector
{
public System.Windows.Controls.Button myButton;
...
}
Элементы XAML, атрибуты XAML и преобразователи типов
После установки корневого элемента и необходимых пространств имен XML следующая задача заключается в наполнении корня дочерним элементом. В реальном приложении WPF дочерним элементом будет диспетчер компоновки (такой как
Grid
или
StackPanel
), который в свою очередь содержит любое количество дополнительных элементов, описывающих пользовательский интерфейс. Такие диспетчеры компоновки рассматриваются в главе 25, а пока предположим, что элемент
<Window>
будет содержать единственный элемент
Button
.
Как было показано ранее в главе, элементы XAML отображаются на типы классов или структур внутри заданного пространства имен .NET Core, тогда как атрибуты в открывающем дескрипторе элемента отображаются на свойства или события конкретного типа. В целях иллюстрации введите в редакторе Kaxaml следующее определение
Обратите внимание, что присвоенные свойствам значения представлены с помощью простого текста. Это может выглядеть как полное несоответствие типам данных, поскольку после создания такого элемента
Button
в коде C# данным свойствам будут присваиваться не строковые объекты, а значения специфических типов данных. Например, ниже показано, как та же самая кнопка описана в коде:
public void MakeAButton
{
Button myBtn = new Button;
myBtn.Height = 50;
myBtn.Width = 100;
myBtn.FontSize = 20;
myBtn.Content = "OK!";
myBtn.Background = new SolidColorBrush(Colors.Green);
myBtn.Foreground = new SolidColorBrush(Colors.Yellow);
}
Оказывается,
что инфраструктура WPF поставляется с несколькими классами преобразователей типов, которые будут применяться для трансформации простых текстовых значений в корректные типы данных. Такой процесс происходит прозрачно (и автоматически).
Тем не менее, нередко возникает потребность в присваивании атрибуту XAML намного более сложного значения, которое невозможно выразить посредством простой строки. Например, пусть необходимо построить специальную кисть для установки свойства
Background
элемента
Button
. Создать кисть подобного рода в коде довольно просто:
public void MakeAButton
{
...
// Необычная кисть для фона.
LinearGradientBrush fancyBruch =
new LinearGradientBrush(Colors.DarkGreen, Colors.LightGreen, 45);
myBtn.Background = fancyBruch;
myBtn.Foreground = new SolidColorBrush(Colors.Yellow);
}
Но можно ли представить эту сложную кисть в виде строки? Нет, нельзя! К счастью, в XAML предусмотрен специальный синтаксис, который можно использовать всякий раз, когда нужно присвоить сложный объект в качестве значения свойства; он называется синтаксисом "свойство-элемент".
Понятие синтаксиса "свойство-элемент" в XAML
Синтаксис "свойство-элемент" позволяет присваивать свойству сложные объекты. Ниже показано описание XAML элемента Button, в котором для установки свойства
Background
применяется объект
LinearGradientBrush
:
<Button Height="50" Width="100" Content="OK!"
FontSize="20" Foreground="Yellow">
<Button.Background>
<LinearGradientBrush>
<GradientStop Color="DarkGreen" Offset="0"/>
<GradientStop Color="LightGreen" Offset="1"/>
</LinearGradientBrush>
</Button.Background>
</Button>
Обратите внимание, что внутри дескрипторов
<Button>
и
</Button>
определена вложенная область по имени
<Button.Backgrounds>
, а в ней — специальный элемент
<LinearGradientBrush>
. (Пока не беспокойтесь о коде кисти; вы освоите графику WPF в главе 26.)