Extensiones de marcado XAML
Gran parte de la definición de XAML se fija en tiempo de compilación. A menudo sabe dónde deben colocarse los elementos, qué colores y fuentes se van a usar y qué valores literales se deben asignar a las propiedades.
Sin embargo, a veces es necesario establecer un valor de propiedad en un valor que no se puede determinar en tiempo de compilación. Estos valores solo se conocen cuando se ejecuta el programa. En estas situaciones puede crear un objeto que proporcionará un valor a XAML en tiempo de ejecución. XAML admite extensiones de marcado para este propósito.
En esta unidad aprenderá a crear y usar extensiones de marcado.
¿Qué es una extensión de marcado?
Una extensión de marcado es una clase que se usa en XAML para acceder a los valores en tiempo de ejecución. Supongamos que tiene muchas etiquetas definidas en la interfaz de usuario XAML y quiere establecer la propiedad FontSize
en el mismo valor en toda la aplicación para asegurarse de que todos los estilos de etiqueta sean coherentes. Puedes establecer la propiedad FontSize
mediante XAML, como se muestra en el ejemplo siguiente:
<Label Text="Hello, World!"
Grid.Row="0"
SemanticProperties.HeadingLevel="Level1"
FontSize="28"
HorizontalOptions="CenterAndExpand"/>
Puede repetir esta misma configuración para cada etiqueta, pero ¿qué ocurre si desea cambiar este valor más adelante? Debe buscar todas las instancias de esta propiedad y realizar el cambio. Además, supongamos que no sabe qué valor usar; se puede calcular en tiempo de ejecución en función de factores como la orientación del dispositivo, la resolución de pantalla u otras consideraciones. En estos casos, necesita algo más sofisticado que un literal codificado de forma rígida. Aquí es donde una extensión de marcado es útil. Las extensiones de marcado ofrecen flexibilidad sobre cómo se obtiene un valor que se usa en XAML.
Crear una extensión de marcado
Una extensión de marcado es una clase que implementa la interfaz Microsoft.Maui.Controls.Xaml.IMarkupExtension. Esta interfaz define un método denominado ProvideValue
, con la siguiente firma:
public object ProvideValue(IServiceProvider serviceProvider)
{
...
}
El propósito de este método es proporcionar un valor al marcado XAML. Observe que el tipo devuelto es object
, por lo que el valor puede ser de cualquier tipo siempre y cuando sea apropiado para el lugar en el que se está usando. Por ejemplo, en una extensión de marcado que calcula y devuelve un tamaño de fuente, el tipo devuelto debe ser un double
.
El parámetro serviceProvider
contiene información contextual sobre dónde se usa la extensión de marcado en el código XAML; entre otros fragmentos de información, identifica el control al que se aplica la extensión.
Puede mantener la extensión de marcado para la propiedad simple FontSize
. En el ejemplo siguiente, la clase MainPage
expone un campo double
denominado MyFontSize
. La clase GlobalFontSizeExtension
implementa la interfaz IMarkupExtension
y el método ProvideValue
devuelve el valor de MyFontSize
variable:
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:
El campo MyFontSize
debe ser un miembro static
de la clase MainPage
para permitir que se haga referencia a él en el método ProvideValue
de esta manera. La buena práctica implica que, en este caso, la variable también debe ser una constante. Un valor const
es static
.
El método ProvideValue
también podría realizar ajustes en el valor devuelto, según la orientación y el factor de forma del dispositivo.
Aplicar la extensión de marcado a un control en XAML
Para usar la extensión de marcado en el código XAML, agregue el espacio de nombres que contiene la clase GlobalFontSizeExtension
a la lista de espacios de nombres de la etiqueta ContentPage
. En el ejemplo siguiente, este espacio de nombres recibe el 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">
Use la extensión de marcado para establecer la propiedad FontSize
de este modo. Tenga en cuenta que la convención es que una extensión de marcado tenga el sufijo Extension en su nombre. XAML reconoce este sufijo, y no es necesario incluirlo cuando llama a la extensión desde el código XAML. En el ejemplo siguiente, se hace referencia a la clase GlobalFontSizeExtension
simplemente como GlobalFontSize
:
<Label Text="Hello, World!"
Grid.Row="0"
SemanticProperties.HeadingLevel="Level1"
FontSize="{mycode:GlobalFontSize}"
HorizontalOptions="CenterAndExpand"/>
Puedes aplicar la misma extensión de marcado en todo el código XAML para cualquier control para el que necesite especificar el tamaño de fuente. Más adelante, si decide cambiar el tamaño de fuente, solo tiene que modificar la definición de la variable MyFontSize
en la clase MainPage
.
Clase StaticExtension
Tan útil como la extensión de marcado de GlobalFontSize
es, es poco probable que cree dicha extensión. La razón de esto es simple: .NET MAUI ya proporciona una extensión más generalizada que le permite hacer referencia a cualquier valor estático en el código. Esta extensión se denomina StaticExtension
o Static
para abreviar. El código siguiente muestra el esquema básico de esta clase de extensión.
[ContentProperty ("Member")]
public class StaticExtension : IMarkupExtension
{
public string Member {get; set;}
public object ProvideValue (IServiceProvider serviceProvider)
{
...
}
}
Nota:
El propósito de las extensiones de marcado personalizado es permitirle controlar situaciones más complejas en lugar del simple caso estático. Por ejemplo, es posible que tenga que cambiar dinámicamente el tamaño de fuente en función del factor de forma del dispositivo.
Para usar esta clase en el código XAML, proporcione el nombre de la variable estática a la que quiere hacer referencia en la propiedad Member
y el método ProvideValue
devuelve el valor en esta variable. En el ejemplo siguiente se muestra cómo usarlo:
<Label Text="Hello, World!"
Grid.Row="0"
SemanticProperties.HeadingLevel="Level1"
FontSize="{x:Static Member=mycode:MainPage.MyFontSize}"
HorizontalOptions="CenterAndExpand"/>
.NET MAUI proporciona un conjunto de otras clases de extensión de marcado, que puede usar para escenarios como la enlace de datos, hacer referencia a recursos y estilos dinámicos, y manejar matrices de datos.