Comece com XAML
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:
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 propriedadeVerticalOptions
. Este conversor converte os nomes dos campos estáticos públicos da estruturaLayoutOptions
em valores do tipoLayoutOptions
.ColorTypeConverter
para a propriedadeTextColor
. Este conversor converte os nomes dos campos estáticos públicos da classe Colors ou valores RGB hexadecimais, com ou sem um canal alfa.
Navegação da página
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
:
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:
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:
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.