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

Последнее обновление: 08.01.2021

Расширения разметки (Markup extensions) дают большую гибкость над тем, как устанавливать значения атрибутов в XAML.

Все классы расширений должны реализовать интерфейс IMarkupExtension. Он имеет две версии:

public interface IMarkupExtension
{
	object ProvideValue(IServiceProvider serviceProvider);
}
public interface IMarkupExtension<out T> : IMarkupExtension
{
    new T ProvideValue(IServiceProvider serviceProvider);
}

Метод ProvideValue() вызывается во время загрузки кода xaml и возвращает собственно то значение, которое присваивается атрибуту элемента.

В Xamarin Forms есть ряд встроенных расширений:

  • x:Static

  • x:Type

  • x:Array

  • x:Null

  • x:Reference

  • StaticResource

  • DynamicResource

  • Binding

  • ConstraintExpression

Расмотрим некоторые из них. А в последующих темах так или иначе затронем и остальные.

x:Static

x:Static позволяет привязать к атрибуту значение константы, статической переменной, статического свойства или значения перечисления. Например, в коде C# у страницы определим константу или статическую переменную:

using Xamarin.Forms;

namespace HelloApp
{
    public partial class MainPage : ContentPage
    {
        public const string HEADER = "Xamarin";

        public static double staticVar = 28;

        public MainPage()
        {
            InitializeComponent();
        }
    }
}

Тогда мы сможем использовать их значения следующим образом:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
			 xmlns:local="clr-namespace:HelloApp"
             x:Class="HelloApp.MainPage">

    <Label Text="{x:Static local:MainPage.HEADER}"
         FontSize="{x:Static local:MainPage.staticVar}"
         VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

Чтобы ссылаться на типы и их члены, которые определены в текущем проекте в коде C#, нам надо подключить пространство имен текущего проекта:

xmlns:local="clr-namespace:HelloApp"

В данном случае весь функционал, который определен в коде C# в текущем проекте, будет сопоставляться с префиксом local. После параметра clr-namespace указывается пространство имен текущего проекта. Обычно оно совпадает с названием проекта (в моем случае HelloApp). После этого в коде XAML мы можем через префикс local ссылаться на типы и их доступные переменные и свойства:

Text="{x:Static local:MainPage.HEADER}"
x:Static расширение в Xamarin Forms

x:Array и x:Type

Расширение разметки x:Array позволяет определить массив данных. А расширение x:Type позволяет указать тип данных. Например, воспользуемся элементом ListView для вывода содержимого массива:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HelloApp.MainPage">
    <ListView>
        <ListView.ItemsSource>
            <x:Array Type="{x:Type x:String}">
                <x:String>iPhone 12 Pro</x:String>
                <x:String>Samsung Galaxy S20</x:String>
                <x:String>Nokia 9</x:String>
            </x:Array>
        </ListView.ItemsSource>
    </ListView>
</ContentPage>

Сложное свойство ListView.ItemsSource в качестве значения принимает массив. В данном случае в определении массива атрибут Type="{x:Type x:String}" указывает, что массив будет содержать данные типа String.

x:Array и x:Type в Xamarin Forms

Создание расширений XAML

Иногда может возникнуть необходимость создать какое-то свое расширение для XAML. В этом случае нам надо создать класс, который будет реализовать интерфейс IMarkupExtension.

К примеру, мы хотим чтобы через XAML можно было установить для фона элемента цвет из четырех компонент - ARGB. В этом случае мы можем создать следующий класс:

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace HelloApp
{
    public class ARGBColor : IMarkupExtension
    {
        public int Alpha { get; set; }
        public int Red { get; set; }
        public int Green { get; set; }
        public int Blue { get; set; }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            return Color.FromRgba(Red, Green, Blue, Alpha);
        }
    }
}

Затем используем этот класс в XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:HelloApp"
             x:Class="HelloApp.MainPage">
    <StackLayout>
        <Label Text="Welcome to Xamarin.Forms"
			   FontSize="24"
               TextColor="{local:ARGBColor Alpha=255, Red=0, Green=77, Blue=64}"
               BackgroundColor="{local:ARGBColor Alpha=255, Red=128, Green=203, Blue=196}"
        />
    </StackLayout>
</ContentPage>

Свойства TextColor и BackgroundColor в качестве значения принимают объект Color. И именно подобный объект генерируется методом ProvideValue() из класса ARGBColor. То есть значение "{local:ARGBColor Alpha=255, Red=0, Green77, Blue=64}" по сути будет возвращать должным образом инициализованный объект Color.

В результате мы увидим на странице метку, к которой применены цвета по настройкам ARGB:

XAML Markup Extensions in Xamarin Forms
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850