Compartir vía


Consumo de extensiones de marcado XAML

Browse sample.Examen de la muestra

Las extensiones de marcado XAML de la interfaz de usuario de aplicaciones multiplataforma de .NET (.NET MAUI) ayudan a mejorar la eficacia y flexibilidad de XAML al permitir que los atributos de elemento se establezcan desde una variedad de orígenes.

Por ejemplo, normalmente se establece la propiedad Color de BoxView así:

<BoxView Color="Blue" />

Sin embargo, es posible que prefieras establecer el atributo Color a partir de un valor almacenado en un diccionario de recursos, o desde el valor de una propiedad estática de una clase que hayas creado, o desde una propiedad de tipo Color de otro elemento de la página, o construido a partir de valores separados de matiz, saturación y luminosidad. Todas estas opciones son posibles con extensiones de marcado XAML.

Una extensión de marcado es una manera diferente de expresar el atributo de un elemento. Las extensiones de marcado XAML de .NET MAUI suelen poderse identificar gracias a un valor de atributo que se incluye entre llaves:

<BoxView Color="{StaticResource themeColor}" />

Cualquier valor de atributo entre llaves es siempre una extensión de marcado XAML. Sin embargo, también se puede hacer referencia a las extensiones de marcado XAML sin el uso de llaves.

Nota:

Varias extensiones de marcado XAML forman parte de la especificación XAML 2009. Estos aparecen en archivos XAML con el prefijo de espacio de nombres habitual x y se denominan normalmente con este prefijo.

Además de las extensiones de marcado que se describen en este artículo, las siguientes extensiones de marcado se incluyen en .NET MAUI y se analizan en otros artículos:

Extensión de marcado x:Static

La extensión de marcado x:Static es compatible con la clase StaticExtension. La clase tiene una sola propiedad denominada Member de tipo string que se establece en el nombre de una constante pública, una propiedad estática, un campo estático o un miembro de enumeración.

Una manera de usar x:Static es definir primero una clase con algunas constantes o variables estáticas, como esta clase AppConstants:

static class AppConstants
{
    public static double NormalFontSize = 18;
}

El código XAML siguiente muestra el enfoque más detallado para crear instancias de la clase StaticExtension entre etiquetas de elemento de propiedad Label.FontSize:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:sys="clr-namespace:System;assembly=netstandard"
             xmlns:local="clr-namespace:MarkupExtensions"
             x:Class="MarkupExtensions.StaticDemoPage"
             Title="x:Static Demo">
    <StackLayout Margin="10, 0">
        <Label Text="Label No. 1">
            <Label.FontSize>
                <x:StaticExtension Member="local:AppConstants.NormalFontSize" />
            </Label.FontSize>
        </Label>
        ···
    </StackLayout>
</ContentPage>

El analizador XAML también permite abreviar la clase StaticExtension como x:Static:

<Label Text="Label No. 2">
    <Label.FontSize>
        <x:Static Member="local:AppConstants.NormalFontSize" />
    </Label.FontSize>
</Label>

Esta sintaxis se puede simplificar aún más colocando la clase StaticExtension y el valor de miembro entre llaves. La expresión resultante se establece directamente en el atributo FontSize:

<Label Text="Label No. 3"
       FontSize="{x:StaticExtension Member=local:AppConstants.NormalFontSize}" />

En este ejemplo, no hay comillas entre las llaves. La propiedad Member de StaticExtension ya no es un atributo XML. En su lugar, forma parte de la expresión de la extensión de marcado.

Del mismo modo que puedes abreviar x:StaticExtension a x:Static cuando lo usas como elemento de objeto, también puedes abreviarlo en la expresión entre llaves:

<Label Text="Label No. 4"
       FontSize="{x:Static Member=local:AppConstants.NormalFontSize}" />

La clase StaticExtension tiene un atributo ContentProperty que hace referencia a la propiedad Member, que marca esta propiedad como la propiedad de contenido predeterminada de la clase. Para las extensiones de marcado XAML expresadas con llaves, puedes eliminar la parte Member= de la expresión:

<Label Text="Label No. 5"
       FontSize="{x:Static local:AppConstants.NormalFontSize}" />

Esta es la forma más común de la extensión de marcado x:Static.

La etiqueta raíz del ejemplo XAML también contiene una declaración de espacio de nombres XML para el espacio de nombres .NET System. Esto permite establecer el tamaño de fuente Label en el campo estático Math.PI. El resultado es un texto bastante pequeño, por lo que la propiedad Scale se establece en Math.E:

<Label Text="&#x03C0; &#x00D7; E sized text"
       FontSize="{x:Static sys:Math.PI}"
       Scale="{x:Static sys:Math.E}"
       HorizontalOptions="Center" />

La siguiente captura de pantalla muestra el resultado de XAML:

x:Static demo.

Extensión de marcado x:Reference

La extensión de marcado x:Reference es compatible con la clase ReferenceExtension. La clase tiene una sola propiedad denominada Name de tipo string que se establece en el nombre de un elemento de la página a la que se le ha asignado un nombre con x:Name. Esta propiedad Name es la propiedad de contenido de ReferenceExtension, por lo que Name= no es obligatorio cuando x:Reference aparece entre llaves. La extensión de marcado x:Reference se usa exclusivamente con enlaces de datos. Para más información sobre el enlace de datos, consulta Enlace de datos.

En el siguiente ejemplo de XAML se muestran dos usos de x:Reference con enlaces de datos, el primero se usa para establecer la propiedad Source del objeto Binding y el segundo se usa para establecer la propiedad BindingContext de dos enlaces de datos:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MarkupExtensions.ReferenceDemoPage"
             x:Name="page"
             Title="x:Reference Demo">    
    <StackLayout Margin="10, 0">        
        <Label Text="{Binding Source={x:Reference page},
                              StringFormat='The type of this page is {0}'}"
               FontSize="18"
               VerticalOptions="Center"
               HorizontalTextAlignment="Center" />
        <Slider x:Name="slider"
                Maximum="360"
                VerticalOptions="Center" />
        <Label BindingContext="{x:Reference slider}"
               Text="{Binding Value, StringFormat='{0:F0}&#x00B0; rotation'}"
               Rotation="{Binding Value}"
               FontSize="24"
               HorizontalOptions="Center"
               VerticalOptions="Center" />        
    </StackLayout>
</ContentPage>

En este ejemplo, ambas expresiones x:Reference usan la versión abreviada del nombre de clase ReferenceExtension y eliminan la parte Name= de la expresión. En el primer ejemplo, la extensión de marcado x:Reference se inserta en la extensión de marcado Binding, y las propiedades Source y StringFormat están separadas por comas.

La siguiente captura de pantalla muestra el resultado de XAML:

x:Reference demo.

Extensión de marcado x:Type

La extensión de marcado x:Type es el equivalente en XAML de la palabra clave de C# typeof. Es compatible con la clase TypeExtension, que define una propiedad denominada TypeName de tipo string que debe establecerse en un nombre de clase o estructura. La extensión de marcado x:Type devuelve el objeto Type de esa clase o estructura. TypeName es la propiedad de contenido de TypeExtension, por lo que TypeName= no es obligatorio cuando x:Type aparece con llaves.

La extensión de marcado x:Type se usa normalmente con la extensión de marcado x:Array. Para más información, consulta Extensión de marcado x:Array.

En el este ejemplo de XAML se muestra cómo usar la extensión de marcado x:Type para crear instancias de objetos .NET MAUI y agregarlos a StackLayout. El XAML consta de tres elementos Button con sus propiedades Command establecidas en un elemento Binding y las propiedades CommandParameter establecidas en tipos de tres vistas .NET MAUI:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MarkupExtensions.TypeDemoPage"
             Title="x:Type Demo">    
    <StackLayout x:Name="stackLayout"
                 Padding="10, 0">        
        <Button Text="Create a Slider"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Command="{Binding CreateCommand}"
                CommandParameter="{x:Type Slider}" />
        <Button Text="Create a Stepper"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Command="{Binding CreateCommand}"
                CommandParameter="{x:Type Stepper}" />
        <Button Text="Create a Switch"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Command="{Binding CreateCommand}"
                CommandParameter="{x:Type Switch}" />
    </StackLayout>
</ContentPage>

El archivo de código subyacente define e inicializa la propiedad CreateCommand:

public partial class TypeDemoPage : ContentPage
{
    public ICommand CreateCommand { get; private set; }

    public TypeDemoPage()
    {
        InitializeComponent();

        CreateCommand = new Command<Type>((Type viewType) =>
        {
            View view = (View)Activator.CreateInstance(viewType);
            view.VerticalOptions = LayoutOptions.Center;
            stackLayout.Add(view);
        });

        BindingContext = this;
    }
}

Cuando se presiona un objeto Button, se crea una nueva instancia del argumento CommandParameter y se agrega a StackLayout. Después, los tres objetos Button comparten la página con vistas creadas de forma dinámica:

x:Type demo.

Extensión de marcado x:Array

La extensión de marcado x:Array permite definir una matriz en el marcado. Es compatible con la clase ArrayExtension, que define dos propiedades:

  • Type de tipo Type, que indica el tipo de los elementos de la matriz. Esta propiedad debe establecerse en una extensión de marcado x:Type.
  • Items de tipo IList, que es una colección de los elementos por sí solos. Es la propiedad de contenido de ArrayExtension.

La propia extensión de marcado x:Array nunca aparece entre llaves. En su lugar, las etiquetas start y end x:Array delimitan la lista de elementos.

En el ejemplo de XAML siguiente se muestra cómo usar x:Array para agregar elementos a un objeto ListView estableciendo la propiedad ItemsSource en una matriz:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MarkupExtensions.ArrayDemoPage"
             Title="x:Array Demo Page">
    <ListView Margin="10">
        <ListView.ItemsSource>
            <x:Array Type="{x:Type Color}">
                <Color>Aqua</Color>
                <Color>Black</Color>
                <Color>Blue</Color>
                <Color>Fuchsia</Color>
                <Color>Gray</Color>
                <Color>Green</Color>
                <Color>Lime</Color>
                <Color>Maroon</Color>
                <Color>Navy</Color>
                <Color>Olive</Color>
                <Color>Pink</Color>
                <Color>Purple</Color>
                <Color>Red</Color>
                <Color>Silver</Color>
                <Color>Teal</Color>
                <Color>White</Color>
                <Color>Yellow</Color>
            </x:Array>
        </ListView.ItemsSource>
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <BoxView Color="{Binding}"
                             Margin="3" />
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>     

En este ejemplo, ViewCell crea un objeto BoxView simple para cada entrada de color:

x:Array demo.

Nota:

Al definir matrices de tipos comunes como cadenas o números, usa las etiquetas primitivas del lenguaje XAML enumeradas en Pasar argumentos.

Extensión de marcado x:Null

La clase de marcado x:Null es compatible con la clase NullExtension. No tiene propiedades y es simplemente el equivalente en XAML de la palabra clave de C# null.

En el ejemplo siguiente se muestra cómo usar la extensión de marcado x:Null:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MarkupExtensions.NullDemoPage"
             Title="x:Null Demo">
    <ContentPage.Resources>
        <Style TargetType="Label">
            <Setter Property="FontSize" Value="48" />
            <Setter Property="FontFamily" Value="OpenSansRegular" />
        </Style>
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">
        <Label Text="Text 1" />
        <Label Text="Text 2" />
        <Label Text="Text 3"
               FontFamily="{x:Null}" />
        <Label Text="Text 4" />
        <Label Text="Text 5" />
    </StackLayout>
</ContentPage>      

En este ejemplo, se define un objeto Style implícito para Label que incluye un objeto Setter que establece la propiedad FontFamily en una fuente específica. Sin embargo, el tercer objeto Label evita el uso de la fuente definida en el estilo implícito, estableciendo su FontFamily en x:Null:

x:Null demo.

Extensión de marcado DataTemplate

La extensión de marcado DataTemplate te permite convertir un tipo en DataTemplate. Es compatible con la clase DataTemplateExtension, que define una propiedad TypeName, de tipo string, que se establece en el nombre del tipo que se va a convertir en DataTemplate. La propiedad TypeName es la propiedad de contenido de DataTemplateExtension. Por lo tanto, para las expresiones de marcado XAML expresadas con llaves, puede eliminar la parte TypeName= de la expresión.

Nota:

El analizador de XAML permite abreviar la clase DataTemplateExtension como DataTemplate.

Una utilización típica de esta extensión de marcado se encuentra en una aplicación de Shell, como se muestra en el ejemplo siguiente:

<ShellContent Title="Monkeys"
              Icon="monkey.png"
              ContentTemplate="{DataTemplate views:MonkeysPage}" />

En este ejemplo, MonkeysPage se convierte de ContentPage a DataTemplate, que se establece como el valor de la propiedad ShellContent.ContentTemplate. Esto garantiza que MonkeysPage solo se crea cuando se navega a la página, no al iniciar la aplicación.

Para más información sobre las aplicaciones de Shell, consulta Shell.