Extensões de marcação XAML

Concluído

Grande parte da sua definição XAML será liquidada em tempo de compilação. Muitas vezes, você sabe onde os elementos devem ser posicionados, quais cores e fontes serão usadas e quais valores literais devem ser atribuídos às propriedades.

No entanto, às vezes você precisa definir um valor de propriedade para um valor que não pode ser determinado em tempo de compilação. Esses valores só são conhecidos quando o programa está em execução. Nessas situações, você pode criar um objeto que forneça um valor para XAML em tempo de execução. O XAML oferece suporte a Extensões de Marcação para essa finalidade.

Nesta unidade, você aprenderá a criar e usar extensões de marcação.

O que é uma extensão de marcação?

Uma extensão de marcação é uma classe que você usa em XAML para acessar valores de tempo de execução. Suponha que você tenha muitos rótulos definidos em sua interface do usuário XAML e queira definir a FontSize propriedade com o mesmo valor em todo o aplicativo para garantir que todo o estilo de rótulo seja consistente. Você pode definir a propriedade usando XAML como mostrado no exemplo a FontSize seguir:

<Label Text="Hello, World!"
            Grid.Row="0"
            SemanticProperties.HeadingLevel="Level1"
            FontSize="28"
            HorizontalOptions="CenterAndExpand"/>

Você pode repetir essa mesma configuração para todos os rótulos, mas e se mais tarde quiser alterar esse valor? Você precisa encontrar todas as instâncias dessa propriedade e fazer a alteração. Além disso, suponha que você não sabe qual valor usar; Ele pode ser calculado em tempo de execução com base em fatores, como orientação do dispositivo, resolução da tela ou outras considerações. Nesses casos, você precisa de algo mais sofisticado do que um literal codificado. É aqui que uma extensão de marcação é útil. As extensões de marcação oferecem flexibilidade na forma como você obtém um valor que é usado em XAML.

Criando uma extensão de marcação

Uma extensão de marcação é uma classe que implementa a interface Microsoft.Maui.Controls.Xaml.IMarkupExtension . Essa interface define um método, chamado ProvideValue, com a seguinte assinatura:

public object ProvideValue(IServiceProvider serviceProvider)
{
    ...
}

A finalidade desse método é fornecer um valor para sua marcação XAML. Observe que o tipo de retorno é object, portanto, o valor pode ser de qualquer tipo, desde que seja apropriado para o local em que está sendo usado. Por exemplo, em uma extensão de marcação que calcula e retorna um tamanho de fonte, o tipo de retorno deve ser um doublearquivo .

O parâmetro serviceProvider contém informações contextuais sobre onde a extensão de marcação está sendo usada em seu código XAML, entre outras informações, ele identifica o controle ao qual a extensão está sendo aplicada.

Você pode manter a extensão de marcação para a FontSize propriedade simples. No exemplo a seguir, a classe MainPage expõe um double campo chamado MyFontSize. A classe GlobalFontSizeExtension implementa a interface IMarkupExtension e o método ProvideValue retorna o valor da variável MyFontSize:

namespace MyMauiApp;

public partial class MainPage : ContentPage
{
    public const double MyFontSize = 28;

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

public class GlobalFontSizeExtension : IMarkupExtension
{
    public object ProvideValue(IServiceProvider serviceProvider)
    {
        return MainPage.MyFontSize;
    }
}

Nota

O campo MyFontSize deve ser um static membro da classe MainPage para permitir que ele seja referenciado no método ProvideValue dessa maneira. As boas práticas implicam que, neste caso, a variável também deve ser uma constante. Um const valor é static.

O método ProvideValue também pode fazer ajustes no valor retornado, dependendo da orientação e do fator de forma do dispositivo.

Aplicando a extensão de marcação a um controle em XAML

Para usar a extensão de marcação em seu código XAML, adicione o namespace que contém a classe GlobalFontSizeExtension à lista de namespaces na ContentPage tag . No exemplo a seguir, esse namespace recebe o alias mycode:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:mycode="clr-namespace:MyMauiApp"
             x:Class="MyMauiApp.MainPage">

Você pode usar a extensão de marcação para definir a FontSize propriedade assim. Observe que a convenção é que uma extensão de marcação tem o sufixo Extension em seu nome. O XAML reconhece esse sufixo e você não precisa incluí-lo quando chamar a extensão do seu código XAML. No exemplo a seguir, a classe GlobalFontSizeExtension é referenciada simplesmente como GlobalFontSize:

<Label Text="Hello, World!"
            Grid.Row="0"
            SemanticProperties.HeadingLevel="Level1"
            FontSize="{mycode:GlobalFontSize}"
            HorizontalOptions="CenterAndExpand"/>

Você pode aplicar a mesma extensão de marcação em todo o código XAML para qualquer controle que precise especificar o tamanho da fonte. Mais tarde, se você decidir alterar o tamanho da fonte, você só precisa modificar a definição da variável MyFontSize na classe MainPage .

A classe StaticExtension

Por mais útil que seja a extensão de marcação GlobalFontSize , é improvável que você crie tal extensão. A razão para isso é simples: o .NET MAUI já fornece uma extensão mais generalizada que permite fazer referência a qualquer valor estático em seu código. Esta extensão é chamada StaticExtension, ou Static para abreviar. O código a seguir mostra o esboço básico dessa classe de extensão:

[ContentProperty ("Member")]
public class StaticExtension : IMarkupExtension
{
    public string Member {get; set;}
    public object ProvideValue (IServiceProvider serviceProvider)
    {
        ...
    }
}

Nota

O objetivo das extensões de marcação personalizadas é permitir que você lide com situações mais complexas em vez de um simples caso estático. Por exemplo, talvez seja necessário alterar dinamicamente o tamanho da fonte com base no fator forma do dispositivo.

Para usar essa classe em seu código XAML, forneça o nome da variável estática que você deseja referenciar na propriedade Member e o método ProvideValue retorna o valor nessa variável. O exemplo a seguir ilustra como usá-lo:

<Label Text="Hello, World!"
            Grid.Row="0"
            SemanticProperties.HeadingLevel="Level1"
            FontSize="{x:Static Member=mycode:MainPage.MyFontSize}"
            HorizontalOptions="CenterAndExpand"/>

O .NET MAUI fornece um conjunto de outras classes de extensão de marcação, que você pode usar para cenários como vinculação de dados, referência a recursos e estilos dinâmicos e manipulação de matrizes de dados.

Verificação de conhecimento

1.

Qual extensão de marcação permite definir uma propriedade XAML como um valor estático definido em uma classe code-behind?

2.

Qual interface você usa para criar uma extensão de marcação personalizada?