Consumo de extensiones de marcado XAML
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:
AppThemeBinding
: especifica un recurso que se va a consumir en función del tema del sistema actual. Para obtener más información, consulta Extensión de marcadoAppThemeBinding.Binding
: establece un vínculo entre las propiedades de dos objetos. Para obtener más información, consulta Enlace de datos.DynamicResource
: responde a los cambios en los objetos de un diccionario de recursos. Para obtener más información, consulta Estilos dinámicos.FontImage
: muestra un icono de fuente en cualquier vista que pueda mostrar ImageSource. Para obtener más información, consulta Cargar un icono de fuente.OnIdiom
: personalización de la apariencia de la interfaz de usuario en función de la expresión del dispositivo en el que se ejecuta la aplicación. Para obtener más información, consulta Personalización de la apariencia de la interfaz de usuario en función de la expresión del dispositivo.OnPlatform
: personaliza la apariencia de la interfaz de usuario por plataforma. Para obtener más información, consulta Personalización de la apariencia de la interfaz de usuario en función de la plataforma.RelativeSource
: establece el origen del enlace en relación con la posición del destino de enlace. Para obtener más información, consulta Enlaces relativos.StaticResource
: hace referencia a objetos de un diccionario de recursos. Para obtener más información, consulta Diccionarios de recursos.TemplateBinding
: realiza el enlace de datos desde una plantilla de control. Para obtener más información, consulta Plantillas de control.
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="π × 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:
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}° 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:
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:
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 tipoType
, que indica el tipo de los elementos de la matriz. Esta propiedad debe establecerse en una extensión de marcadox:Type
.Items
de tipoIList
, 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:
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
:
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.