Introducción a XAML

Examinar ejemplo. Examinar el ejemplo

En una aplicación de interfaz de usuario de aplicaciones multiplataforma de .NET (.NET MAUI), XAML se usa principalmente para definir el contenido visual de una página y funciona junto con un archivo de código subyacente de C#. El archivo de código subyacente proporciona compatibilidad con el código para el marcado. Juntos, estos dos archivos contribuyen a una nueva definición de clase que incluye vistas secundarias e inicialización de propiedades. Dentro del archivo XAML, se hace referencia a clases y propiedades con elementos y atributos XML, y se establecen vínculos entre el marcado y el código.

Anatomía de un archivo XAML

Una nueva aplicación MAUI de .NET contiene tres archivos XAML y sus archivos de código subyacente asociados:

Captura de pantalla de la estructura de una nueva aplicación MAUI de .NET.

El primer emparejamiento de archivos es App.xaml, un archivo XAML y App.xaml.cs, un archivo de código subyacente de C# asociado al archivo XAML. Tanto App.xaml como App.xaml.cs contribuyen a una clase denominada App que deriva de Application. El segundo emparejamiento de archivos es AppShell.xaml y AppShell.xaml.cs, que contribuyen a una clase denominada AppShell que deriva de Shell. La mayoría de las demás clases con archivos XAML contribuyen a una clase que deriva de ContentPagey definen la interfaz de usuario de una página. Esto es cierto en los archivos MainPage.xaml y MainPage.xaml.cs .

El archivo MainPage.xaml tiene la estructura siguiente:

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

Las dos declaraciones de espacio de nombres XML (xmlns) hacen referencia a URI en microsoft.com. Sin embargo, no hay contenido en estos URI y básicamente funcionan como identificadores de versión.

La primera declaración de espacio de nombres XML significa que las etiquetas definidas en el archivo XAML sin prefijo hacen referencia a las clases de .NET MAUI, por ejemplo ContentPage. La segunda declaración de espacio de nombres define un prefijo de x. Se usa para varios elementos y atributos que son intrínsecos a XAML y que son compatibles con otras implementaciones de XAML. Sin embargo, estos elementos y atributos son ligeramente diferentes en función del año incrustado en el URI. .NET MAUI admite la especificación XAML 2009.

Al final de la primera etiqueta, el x prefijo se usa para un atributo denominado Class. Dado que el uso de este x prefijo es prácticamente universal para el espacio de nombres XAML, los atributos XAML como Class casi siempre se conocen como x:Class. El x:Class atributo especifica un nombre de clase de .NET completo: la MainPage clase del MyMauiApp espacio de nombres . Esto significa que este archivo XAML define una nueva clase denominada MainPage en el MyMauiApp espacio de nombres que deriva de ContentPage (la etiqueta en la que aparece el x:Class atributo).

El x:Class atributo solo puede aparecer en el elemento raíz de un archivo XAML para definir una clase de C# derivada. Esta es la única clase nueva definida en el archivo XAML. En su lugar, todo lo demás que aparece en un archivo XAML se crea una instancia simplemente de las clases existentes y se inicializa.

El archivo MainPage.xaml.cs tiene un aspecto similar al siguiente:

namespace MyMauiApp;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }
}

La MainPage clase se deriva de y es una definición de ContentPageclase parcial.

Cuando Visual Studio compila el proyecto, un generador de origen genera un nuevo origen de C# que contiene la definición del InitializeComponent método al que se llama desde el MainPage constructor y lo agrega al objeto de compilación.

En tiempo de ejecución, el código de la MauiProgram clase arranca la aplicación y ejecuta el App constructor de clase, que crea AppShelluna instancia de . La AppShell clase crea una instancia de la primera página de la aplicación que se va a mostrar, que es MainPage. El MainPage constructor llama a InitializeComponent, que inicializa todos los objetos definidos en el archivo XAML, los conecta todos juntos en relaciones de elementos primarios y secundarios, adjunta controladores de eventos definidos en el código a eventos establecidos en el archivo XAML y establece el árbol resultante de objetos como el contenido de la página.

Nota:

La AppShell clase usa .NET MAUI Shell para establecer la primera página de la aplicación que se va a mostrar. Sin embargo, Shell está fuera del ámbito de esta introducción a XAML. Para obtener más información, vea Shell de MAUI de .NET.

Establecer contenido de página

Un ContentPage debe contener un solo elemento secundario, que puede ser una vista o un diseño con vistas secundarias. El elemento secundario de ContentPage se establece automáticamente como el valor de la ContentPage.Content propiedad .

En el ejemplo siguiente se muestra un ContentPage objeto que contiene :Label

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.HelloXamlPage"
             Title="Hello XAML Page">
    <Label Text="Hello, XAML!"
           VerticalOptions="Center"
           HorizontalTextAlignment="Center"
           Rotation="-15"
           FontSize="18"
           FontAttributes="Bold"
           TextColor="Blue" />
</ContentPage>

En el ejemplo anterior, la relación entre clases, propiedades y XML debe ser evidente. Una clase MAUI de .NET (como ContentPage o Label) aparece en el archivo XAML como un elemento XML. Las propiedades de esa clase, incluidas Title las propiedades en ContentPage y siete de Label normalmente aparecen como atributos XML.

Existen muchos métodos abreviados para establecer los valores de estas propiedades. Algunas propiedades son tipos de datos básicos. Por ejemplo, las Title propiedades y Text son de tipo stringy Rotation es de tipo double. La HorizontalTextAlignment propiedad es de tipo TextAlignment, que es una enumeración. Para una propiedad de cualquier tipo de enumeración, todo lo que necesita proporcionar es un nombre de miembro.

Sin embargo, para las propiedades de tipos más complejos, se usan convertidores para analizar el XAML. Estas son clases de .NET MAUI que derivan de TypeConverter. En el ejemplo anterior, se aplican automáticamente varios convertidores MAUI de .NET para convertir valores de cadena en su tipo correcto:

  • LayoutOptionsConverter para la VerticalOptions propiedad . Este convertidor convierte los nombres de los campos estáticos públicos de la LayoutOptions estructura en valores de tipo LayoutOptions.
  • ColorTypeConverter para la TextColor propiedad . Este convertidor convierte los nombres de los campos estáticos públicos de la Colors clase o valores RGB hexadecimales, con o sin un canal alfa.

Al ejecutar una aplicación MAUI de .NET, MainPage normalmente se muestra . Para ver otra página, puedes establecerla como la nueva página de inicio en el archivo AppShell.xaml o navegar a la nueva página desde MainPage.

Para implementar la navegación, en el constructor MainPage.xaml.cs , puedes crear un sencillo Button y usar el controlador de eventos para navegar a HelloXamlPage:

public MainPage()
{
    InitializeComponent();

    Button button = new Button
    {
        Text = "Navigate!",
        HorizontalOptions = LayoutOptions.Center,
        VerticalOptions = LayoutOptions.Center
    };

    button.Clicked += async (sender, args) =>
    {
        await Navigation.PushAsync(new HelloXamlPage());
    };

    Content = button;
}

Al compilar e implementar la nueva versión de esta aplicación, aparece un botón en la pantalla. Al presionarlo, se desplaza a HelloXamlPage:

Captura de pantalla del texto de la etiqueta girada.

Puede volver a MainPage usar la barra de navegación que aparece en cada plataforma.

Nota:

Una alternativa a este modelo de navegación es usar el shell MAUI de .NET. Para obtener más información, consulte Introducción al shell maui de .NET.

Interacciones de código y XAML

El elemento secundario de la mayoría ContentPage de los derivados es un diseño, como o StackLayout , Gridy el diseño puede contener varios elementos secundarios. En XAML, estas relaciones de elementos primarios y secundarios se establecen con la jerarquía XML normal:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.XamlPlusCodePage"
             Title="XAML + Code Page">
    <StackLayout>
        <Slider VerticalOptions="Center" />
        <Label Text="A simple Label"
               FontSize="18"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <Button Text="Click Me!"
                HorizontalOptions="Center"
                VerticalOptions="Center" />
    </StackLayout>
</ContentPage>

Este archivo XAML se completa sintácticamente y genera la siguiente interfaz de usuario:

Captura de pantalla de varios controles en una página.

Sin embargo, aunque puede interactuar con y SliderButton, la interfaz de usuario no se actualiza. Slider debe hacer que Label muestre el valor actual y debe Button hacer algo.

Mostrar un Slider valor mediante un Label se puede lograr completamente en XAML con un enlace de datos. Sin embargo, es útil ver primero la solución de código. Incluso así, controlar el Button clic definitivamente requiere código. Esto significa que el archivo de código subyacente para XamlPlusCodePage debe contener controladores para el ValueChanged evento de Slider y el Clicked evento de Button:

namespace XamlSamples
{
    public partial class XamlPlusCodePage
    {
        public XamlPlusCodePage()
        {
            InitializeComponent();
        }

        void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
        {
            valueLabel.Text = args.NewValue.ToString("F3");
        }

        async void OnButtonClicked(object sender, EventArgs args)
        {
            Button button = (Button)sender;
            await DisplayAlert("Clicked!", "The button labeled '" + button.Text + "' has been clicked", "OK");
        }
    }
}

De nuevo en el archivo XAML, las Slider etiquetas y Button deben incluir atributos para los ValueChanged eventos y Clicked que hacen referencia a estos controladores:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.XamlPlusCodePage"
             Title="XAML + Code Page">
    <StackLayout>
        <Slider VerticalOptions="Center"
                ValueChanged="OnSliderValueChanged" />
        <Label x:Name="valueLabel"
               Text="A simple Label"
               FontSize="18"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <Button Text="Click Me!"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Clicked="OnButtonClicked" />
    </StackLayout>
</ContentPage>

Observe que la asignación de un controlador a un evento tiene la misma sintaxis que asignar un valor a una propiedad. Además, para que el ValueChanged controlador de eventos de Slider use para Label mostrar el valor actual, el controlador debe hacer referencia a ese objeto desde el código. Por lo tanto, Label necesita un nombre, que se especifica con el x:Name atributo . El x prefijo del x:Name atributo indica que este atributo es intrínseco a XAML. El nombre que asigne al x:Name atributo tiene las mismas reglas que los nombres de variable de C#. Por ejemplo, debe comenzar con una letra o un carácter de subrayado y no contener espacios incrustados.

El ValueChanged controlador de eventos ahora puede establecer para Label mostrar el nuevo Slider valor, que está disponible en los argumentos del evento:

void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
    valueLabel.Text = args.NewValue.ToString("F3");
}

Como alternativa, el controlador podría obtener el Slider objeto que genera este evento a partir del sender argumento y obtener la Value propiedad de esa:

void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
    valueLabel.Text = ((Slider)sender).Value.ToString("F3");
}

El resultado es que cualquier manipulación de Slider hace que su valor se muestre en :Label

Captura de pantalla de varios controles en una página, con el valor slider mostrado.

En el ejemplo anterior, Button simula una respuesta a un Clicked evento mostrando una alerta con el Text del botón . Por lo tanto, el controlador de eventos puede convertir el sender argumento en y Button , a continuación, obtener acceso a sus propiedades:

async void OnButtonClicked(object sender, EventArgs args)
{
    Button button = (Button)sender;
    await DisplayAlert("Clicked!", "The button labeled '" + button.Text + "' has been clicked", "OK");
}

El OnButtonClicked método se define como async porque el DisplayAlert método es asincrónico y debe estar precedido del await operador , que devuelve cuando se completa el método. Dado que este método obtiene el Button desencadenamiento del evento del sender argumento , se podría usar el mismo controlador para varios botones.

Pasos siguientes

XAML está diseñado principalmente para crear instancias e inicializar objetos. Pero a menudo, las propiedades deben establecerse en objetos complejos que no se pueden representar fácilmente como cadenas XML y, a veces, las propiedades definidas por una clase deben establecerse en una clase secundaria. Estas dos necesidades requieren las características de sintaxis XAML esenciales de los elementos de propiedad y las propiedades adjuntas.