Расширения разметки XAML

73

Для большинства свойств синтаксис свойств XAML работает исключительно хорошо. Но в некоторых случаях просто невозможно жестко закодировать значение свойства. Например, значение свойства должно быть установлено в уже существующий объект. Или может понадобиться установить значение свойства динамически, привязывая его к свойству в другом элементе управления. В обоих таких случаях необходимо использовать расширение разметки (markup extension) — специализированный синтаксис, устанавливающий свойство нестандартным образом.

Расширения разметки позволяют анализатору XAML получать значение свойства из выделенного внешнего класса. Это может быть очень выгодно, учитывая, что некоторые значения свойств требуют выполнения множества операторов кода для поиска значения.

Расширения разметки предлагают способ ясного расширения грамматики XAML новой функциональностью. Расширение разметки внутренне представлено как класс, унаследованный от MarkupExtension. Следует подчеркнуть: шансы, что когда-либо придется строить специальное расширение разметки, невелики. Тем не менее, подмножество ключевых слов XAML (таких как х:Array, x:Null, x:Static, х:Type) — это именно расширения разметки.

Расширение разметки заключается в фигурные скобки, как показано ниже:

<Элемент УстанавливаемоеСвойство = "{РасширениеРазметки}"/>

Расширения разметки используют синтаксис {КлассРасширенияРазметки Аргумент}. В этом случае расширением разметки служит класс StaticExtension. (По соглашению при ссылке на класс расширения последнее слово Extension можете опустить.)

Префикс х указывает на то, что StaticExtension находится в одном из пространств имен XAML. Также вы встретите расширения разметки, являющиеся частью пространств имен WPF, но не имеющие префикса х.

Все расширения разметки реализованы классами, производными от System.Windows.Markup.MarkupExtension. Базовый класс MarkupExtension чрезвычайно прост — он включает единственный метод ProvideValue(), получающий необходимое значение. Другими словами, когда анализатор XAML встречает предыдущий оператор, он создает экземпляр класса StaticExtension, а затем вызывает ProvideValue(), чтобы получить объект, возвращенный статическим свойством. Ниже представлен пример использования расширений разметки:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:CorLib="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="MyGrid">
        <TextBox Name="txt1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
                 FontFamily="Arial" FontSize="20" Foreground="Blue">
            <TextBox.Background>
                <!-- Задаем градиентную заливку -->
                <LinearGradientBrush>
                    <LinearGradientBrush.GradientStops>
                        <GradientStop Offset="0.00" Color="White" />
                        <GradientStop Offset="0.30" Color="Red" />
                        <GradientStop Offset="1.00" Color="Violet" />
                    </LinearGradientBrush.GradientStops>
                </LinearGradientBrush>
            </TextBox.Background>
        </TextBox>
        <StackPanel>
            <!-- Используем расширение разметки для получения значения статического члена класса -->
            <Label Content="{x:Static CorLib:Environment.OSVersion}"></Label>
            <Label Content="{x:Static CorLib:Environment.ProcessorCount}"></Label>
            <!-- Оператор typeof на XAML -->
            <Label Content="{x:Type BulletDecorator}"></Label>
            <Label Content="{x:Type CorLib:Int32}"></Label>
            <!-- Наполнение элемента ListBox массивом строк -->
            <ListBox Width="200" Height="50">
                <ListBox.ItemsSource>
                    <x:Array Type="CorLib:String">
                        <CorLib:String>Элемент 1</CorLib:String>
                        <CorLib:String>Элемент 2</CorLib:String>
                        <CorLib:String>Элемент 3</CorLib:String>
                    </x:Array>
                </ListBox.ItemsSource>
            </ListBox>
        </StackPanel>
    </Grid>
</Window>
Расширения разметки XAML

Прежде всего, обратите внимание, что определение <Window> имеет новое объявление пространства имен XML, что позволяет получать доступ к пространству имен System сборки mscorlib.dll. Имея это пространство имен, сначала с помощью расширения разметки x:Static извлекаются значения OSVersion и ProcessorCount класса System.Environment.

Расширение разметки х:Type позволяет получить доступ к описанию метаданных указанного элемента. Здесь просто назначаются полностью квалифицированные имена типов WPF BulletDecorator и System.Int32.

Наиболее интересная часть показанной выше разметки связана с элементом ListBox. Его свойство ItemSource устанавливается в массив строк, полностью объявленный в разметке. Обратите внимание, что расширение разметки х:Array позволяет указывать набор подэлементов внутри своего контекста.

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