Share via


Introdução ao XAML

Browse sample. Navegue pelo exemplo

Em um aplicativo .NET Multi-platform App UI (.NET MAUI), o XAML é usado principalmente para definir o conteúdo visual de uma página e funciona em conjunto com um arquivo code-behind C#. 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, 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 seus arquivos code-behind associados:

Screenshot of the structure of a new .NET MAUI app.

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 contribuem para uma classe que deriva de e definem a interface do usuário de ContentPageuma página. Isso é verdadeiro para os arquivos MainPage.xaml e MainPage.xaml.cs arquivos.

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 funcionam basicamente 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 define um prefixo de x. Isso é usado para vários elementos e atributos que são intrínsecos ao próprio XAML e que são suportados por outras implementações de XAML. No entanto, esses elementos e atributos são ligeiramente diferentes dependendo do ano incorporado no URI. O .NET MAUI oferece suporte à especificação XAML de 2009.

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

O x:Class atributo 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 MainPage classe deriva de , e é uma definição de ContentPageclasse parcial.

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

Em tempo de execução, o código na classe inicializa o aplicativo e executa o MauiProgram construtor de classe, que instancia AppShell.App A AppShell classe instancia a primeira página do aplicativo a ser exibida, que é MainPage. O MainPage construtor chama InitializeComponent, que inicializa todos os objetos definidos no arquivo 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 AppShell classe usa o .NET MAUI Shell 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 obter mais informações, consulte .NET MAUI Shell.

Definir conteúdo da página

Um ContentPage deve conter um único filho, que pode ser um modo de exibição ou um layout com modos de exibição filho. O filho do ContentPage é definido automaticamente como o valor da ContentPage.Content propriedade.

O exemplo a seguir mostra um contendo um ContentPageLabel:

<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>

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

Existem muitos atalhos para definir os valores dessas propriedades. Algumas propriedades são tipos de dados básicos. Por exemplo, as Title propriedades e são do tipo , e RotationText é do tipo doublestring. A HorizontalTextAlignment propriedade é 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.

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

  • LayoutOptionsConverter para o VerticalOptions imóvel. Esse conversor converte os nomes de campos estáticos públicos da LayoutOptions estrutura em valores do tipo LayoutOptions.
  • ColorTypeConverter para o TextColor imóvel. Esse conversor converte os nomes de campos estáticos públicos da Colors classe 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 a partir do 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. Pressionando-o navega para HelloXamlPage:

Screenshot of rotated Label text.

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

Observação

Uma alternativa a esse modelo de navegação é usar o Shell MAUI do .NET. 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 ContentPage dos derivados é um layout, como um ou um StackLayoutGrid, e o layout pode conter vários filhos. Em 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:

Screenshot of multiple controls on a page.

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 exiba o valor atual e o LabelButton deve fazer algo.

A exibição de um valor usando um pode ser obtida inteiramente em XAML com uma associação de SliderLabeldados. No entanto, é útil ver a solução de código primeiro. Mesmo assim, lidar com o Button clique definitivamente requer código. Isso significa que o arquivo code-behind para deve conter manipuladores para XamlPlusCodePage o evento do e o ValueChangedClicked evento do SliderButton:

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

O ValueChanged manipulador de eventos agora pode definir o para exibir o Label novo Slider valor, 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 Slider objeto que está gerando esse evento a sender partir do argumento e obter a propriedade a Value partir 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:

Screenshot of multiple controls on a page, with Slider value displayed.

No exemplo acima, o Button simula uma resposta a um evento exibindo um Clicked alerta com o Text botão do botão. Portanto, o manipulador de eventos pode converter o sender argumento 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 OnButtonClicked método é definido como async porque o método é assíncrono e deve ser precedido com o operador, que retorna quando o DisplayAlertawait método é concluído. Como esse método obtém o disparo do evento do sender argumento, o Button 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 filha. Essas duas necessidades exigem os recursos essenciais de sintaxe XAML de elementos de propriedade e propriedades anexadas.