Compartilhar via


Comece com XAML

Procurar amostra. Procurar no exemplo

Em um aplicativo .NET MAUI (.NET Multi-platform App UI), o XAML é usado principalmente para definir o conteúdo visual de uma página e funciona com um arquivo code-behind. O arquivo code-behind fornece suporte de código para a marcação. Juntos, esses dois arquivos contribuem para uma nova definição de classe que inclui exibições filho e inicialização de propriedade. No arquivo XAML, as classes e propriedades são referenciadas com elementos e atributos XML, e os links entre a marcação e o código são estabelecidos.

Anatomia de um arquivo XAML

Um novo aplicativo .NET MAUI contém três arquivos XAML e os respectivos arquivos code-behind associados:

Captura de tela da estrutura de um novo aplicativo .NET MAUI.

O primeiro emparelhamento de arquivos é App.xaml, um arquivo XAML e App.xaml.cs, um arquivo code-behind C# associado ao arquivo XAML. App.xaml e App.xaml.cs contribuem para uma classe chamada App que deriva de Application. O segundo emparelhamento de arquivos é AppShell.xaml e AppShell.xaml.cs, que contribuem para uma classe chamada AppShell que deriva de Shell. A maioria das outras classes com arquivos XAML contribui para uma classe que deriva de ContentPage e define a interface do usuário de uma página. Isso vale para os arquivos MainPage.xaml e MainPage.xaml.cs.

O arquivo MainPage.xaml tem a seguinte estrutura:

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

As duas declarações de namespace XML (xmlns) referem-se a URIs em microsoft.com. No entanto, não há conteúdo nesses URIs e eles basicamente funcionam como identificadores de versão.

A primeira declaração de namespace XML significa que as marcas definidas no arquivo XAML sem prefixo se referem a classes no .NET MAUI, por exemplo, ContentPage. A segunda declaração de namespace usa o prefixo x. Ele é usado para vários elementos e atributos que são intrínsecos ao próprio XAML e que são aceitos por outras implementações de XAML. No entanto, esses elementos e atributos são um pouco diferentes dependendo do ano inserido no URI. O .NET MAUI aceita a especificação XAML 2009.

No final da primeira marca, o prefixo x é usado para um atributo chamado Class. Como o uso desse prefixo x é praticamente universal para o namespace XAML, os atributos XAML, como Class, são quase sempre chamados de x:Class. O atributo x:Class especifica um nome de classe .NET totalmente qualificado: a classe MainPage no namespace MyMauiApp. Isso significa que esse arquivo XAML define uma nova classe nomeada MainPage no namespace MyMauiApp que deriva de ContentPage (a marca na qual o atributo x:Class aparece).

O atributo x:Class só pode aparecer no elemento raiz de um arquivo XAML para definir uma classe C# derivada. Essa é a única nova classe definida no arquivo XAML. Todo o resto que aparece em um arquivo XAML é simplesmente instanciado a partir de classes existentes e inicializado.

O arquivo MainPage.xaml.cs é semelhante a este:

namespace MyMauiApp;

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

A classe MainPage deriva de ContentPage e é uma definição de classe parcial.

Quando o Visual Studio cria um projeto, um gerador de origem gera uma nova fonte C# que contém a definição do método InitializeComponent que é chamado a partir do construtor MainPage e o adiciona ao objeto de compilação.

No runtime, o código na classe MauiProgram inicializa o aplicativo e executa o construtor da classe App, que instancia AppShell. A classe AppShell instancia a primeira página do aplicativo a ser exibida, que é MainPage. O construtor MainPage chama InitializeComponent, que inicializa todos os objetos definidos no XAML, conecta-os todos juntos em relações pai-filho, anexa manipuladores de eventos definidos no código a eventos definidos no arquivo XAML e define a árvore resultante de objetos como o conteúdo da página.

Observação

A classe AppShell usa o Shell do .NET MAUI para definir a primeira página do aplicativo a ser exibida. No entanto, o Shell está além do escopo desta introdução ao XAML. Para mais informações, confira Shell do .NET MAUI.

Definir o conteúdo da página

Uma ContentPage deve conter um único filho, que pode ser uma exibição ou um layout com exibições filho. O filho da ContentPage é definido automaticamente como o valor da propriedade ContentPage.Content.

O exemplo a seguir mostra uma ContentPage que contém um 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>

A partir do exemplo acima, a relação entre classes, propriedades e XML deve ser evidente. Uma classe do .NET MAUI (como ContentPage ou Label) aparece no arquivo XAML como um elemento XML. As propriedades dessa classe, incluindo Title em ContentPage e sete propriedades de Label , geralmente aparecem como atributos XML.

Existem muitos atalhos para definir os valores dessas propriedades. Algumas propriedades são do tipo de dados básicos. Por exemplo, as propriedades Title e Text são do tipo string, e Rotation é do tipo double. A propriedade HorizontalTextAlignment é do tipo TextAlignment, que é uma enumeração. Para uma propriedade de qualquer tipo de enumeração, tudo o que você precisa fornecer é um nome de membro.

No entanto, para propriedades de tipos mais complexos, os conversores são usados para analisar o XAML. Essas são classes no .NET MAUI que derivam do TypeConverter. Para o exemplo acima, vários conversores .NET MAUI são aplicados automaticamente para converter valores de cadeia de caracteres em seu tipo correto:

  • LayoutOptionsConverter para a propriedade VerticalOptions. Este conversor converte os nomes dos campos estáticos públicos da estrutura LayoutOptions em valores do tipo LayoutOptions.
  • ColorTypeConverter para a propriedade TextColor. Este conversor converte os nomes dos campos estáticos públicos da classe Colors ou valores RGB hexadecimais, com ou sem um canal alfa.

Quando você executa um aplicativo .NET MAUI, o MainPage normalmente é exibido. Para ver uma página diferente, você pode defini-la como a nova página de inicialização no arquivo AppShell.xaml ou navegar até a nova página de MainPage.

Para implementar a navegação, no construtor MainPage.xaml.cs, você pode criar um simples Button e usar o manipulador de eventos para navegar até 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;
}

Quando você compila e implanta a nova versão deste aplicativo, um botão aparece na tela. Pressioná-lo navega até HelloXamlPage:

Captura de tela do texto do rótulo girado.

Você pode navegar de volta para MainPage ao usar a barra de navegação que aparece em cada plataforma.

Observação

Uma alternativa a esse modelo de navegação é usar o Shell do .NET MAUI. Para obter mais informações, consulte Visão geral do Shell do .NET MAUI.

XAML e interações de código

O filho da maioria dos derivados ContentPage é um layout, como o StackLayout ou o Grid, e o layout pode conter vários filhos. No XAML, essas relações pai-filho são estabelecidas com hierarquia 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>

Esse arquivo XAML é sintaticamente completo e produz a seguinte interface do usuário:

Captura de tela de vários controles em uma página.

No entanto, embora você possa interagir com o Slider e Button, a interface do usuário não é atualizada. O Slider deve fazer com que o Label exiba o valor atual e o Button deve fazer alguma coisa.

A exibição de um valor Slider usando um Label pode ser obtida inteiramente em XAML com uma associação de dados. No entanto, é útil ver a solução de código primeiro. Mesmo assim, lidar com o clique Button definitivamente requer código. Isso significa que o arquivo code-behind for XamlPlusCodePage deve conter manipuladores para o evento ValueChanged do Slider e o evento Clicked do 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 volta ao arquivo XAML, as marcas Slider e Button precisam incluir atributos para os eventos ValueChanged e Clicked que fazem referência a esses manipuladores:

<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 atribuir um manipulador a um evento tem a mesma sintaxe que atribuir um valor a uma propriedade. Além disso, para que o manipulador de eventos ValueChanged do Slider use o Label para exibir o valor atual, o manipulador precisa fazer referência a esse objeto do código. Portanto, o Label precisa de um nome, que é especificado com o atributo x:Name. O prefixo x do atributo x:Name indica que esse atributo é intrínseco ao XAML. O nome que você atribui ao atributo x:Name tem as mesmas regras que os nomes de variáveis C#. Por exemplo, ele deve começar com uma letra ou sublinhado e não conter espaços incorporados.

O manipulador de eventos ValueChanged agora pode definir o Label para exibir o novo valor Slider, que está disponível nos argumentos do evento:

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

Como alternativa, o manipulador pode obter o objeto Slider que está gerando esse evento do argumento sender e obter a propriedade Value dele:

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

O resultado é que qualquer manipulação do Slider faz com que seu valor seja exibido no Label:

Captura de tela de vários controles em uma página, com o valor do controle deslizante exibido.

No exemplo acima, o Button simula uma resposta a um evento Clicked exibindo um alerta com o Text do botão. Portanto, o manipulador de eventos pode converter o argumento sender em um Button e, em seguida, acessar suas propriedades:

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

O método OnButtonClicked é definido como async porque o método DisplayAlert é assíncrono e deve ser precedido pelo operador await, que retorna quando o método é concluído. Como esse método obtém o acionamento Button do evento do argumento sender, o mesmo manipulador pode ser usado para vários botões.

Próximas etapas

O XAML foi projetado principalmente para instanciar e inicializar objetos. Mas, muitas vezes, as propriedades devem ser definidas como objetos complexos que não podem ser facilmente representados como cadeias de caracteres XML e, às vezes, as propriedades definidas por uma classe devem ser definidas em uma classe filho. Essas duas necessidades exigem os recursos essenciais de sintaxe XAML de elementos de propriedade e propriedades anexadas.