Introduzione a XAML
In un'app .NET Multipiattaforma App UI (.NET MAUI) XAML viene usato principalmente per definire il contenuto visivo di una pagina e funziona insieme a un file code-behind C#. Il file code-behind fornisce il supporto del codice per il markup. Insieme, questi due file contribuiscono a una nuova definizione di classe che include visualizzazioni figlio e inizializzazione delle proprietà. All'interno del file XAML, alle classi e alle proprietà viene fatto riferimento con elementi e attributi XML e vengono stabiliti collegamenti tra markup e codice.
Anatomia di un file XAML
Una nuova app MAUI .NET contiene tre file XAML e i relativi file code-behind associati:
La prima associazione di file è App.xaml, un file XAML e App.xaml.cs, un file code-behind C# associato al file XAML. Sia App.xaml che App.xaml.cs contribuiscono a una classe denominata App
che deriva da Application
. La seconda associazione di file è AppShell.xaml e AppShell.xaml.cs, che contribuiscono a una classe denominata AppShell
che deriva da Shell. La maggior parte delle altre classi con file XAML contribuisce a una classe che deriva da ContentPagee definisce l'interfaccia utente di una pagina. Questo vale per i file MainPage.xaml e MainPage.xaml.cs .
Il file MainPage.xaml ha la struttura seguente:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyMauiApp.MainPage">
...
</ContentPage>
Le due dichiarazioni dello spazio dei nomi XML (xmlns
) fanno riferimento agli URI in microsoft.com. Tuttavia, non sono presenti contenuti in questi URI e funzionano fondamentalmente come identificatori di versione.
La prima dichiarazione dello spazio dei nomi XML indica che i tag definiti all'interno del file XAML senza prefisso fanno riferimento alle classi in .NET MAUI, ad esempio ContentPage. La seconda dichiarazione dello spazio dei nomi definisce un prefisso di x
. Viene usato per diversi elementi e attributi intrinseci di XAML e supportati da altre implementazioni di XAML. Tuttavia, questi elementi e attributi sono leggermente diversi a seconda dell'anno incorporato nell'URI. .NET MAUI supporta la specifica XAML 2009.
Alla fine del primo tag, il x
prefisso viene usato per un attributo denominato Class
. Poiché l'uso di questo x
prefisso è praticamente universale per lo spazio dei nomi XAML, gli attributi XAML come Class
sono quasi sempre definiti .x:Class
L'attributo x:Class
specifica un nome di classe .NET completo: la MainPage
classe nello spazio dei MyMauiApp
nomi . Questo significa che questo file XAML definisce una nuova classe denominata MainPage
nello MyMauiApp
spazio dei nomi che deriva da ContentPage (il tag in cui viene visualizzato l'attributo x:Class
).
L'attributo x:Class
può essere visualizzato solo nell'elemento radice di un file XAML per definire una classe C# derivata. Questa è l'unica nuova classe definita nel file XAML. Tutto il resto visualizzato in un file XAML viene invece semplicemente creata un'istanza da classi esistenti e inizializzata.
Il file MainPage.xaml.cs è simile al seguente:
namespace MyMauiApp;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
La MainPage
classe deriva da ContentPagee è una definizione di classe parziale.
Quando Visual Studio compila il progetto, un generatore di origine genera una nuova origine C# contenente la definizione del InitializeComponent
metodo chiamato dal MainPage
costruttore e lo aggiunge all'oggetto di compilazione.
In fase di esecuzione, il MauiProgram
codice nella classe esegue il bootstrap dell'app ed esegue il costruttore della classe , che crea AppShell
un'istanza App
di . La AppShell
classe crea un'istanza della prima pagina dell'app da visualizzare, ovvero MainPage
. Il MainPage
costruttore chiama InitializeComponent
, che inizializza tutti gli oggetti definiti nel file XAML, li connette tutti insieme nelle relazioni padre-figlio, associa i gestori eventi definiti nel codice agli eventi impostati nel file XAML e imposta l'albero risultante degli oggetti come contenuto della pagina.
Nota
La AppShell
classe usa .NET MAUI Shell per impostare la prima pagina dell'app da visualizzare. Tuttavia, Shell esula dall'ambito di questa introduzione a XAML. Per altre informazioni, vedere Shell MAUI .NET.
Impostare il contenuto della pagina
Un ContentPage oggetto deve contenere un singolo elemento figlio, che può essere una visualizzazione o un layout con visualizzazioni figlio. L'elemento ContentPage figlio di viene impostato automaticamente come valore della ContentPage.Content
proprietà .
Nell'esempio seguente viene illustrato un oggetto ContentPage contenente un oggetto 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>
Nell'esempio precedente la relazione tra classi, proprietà e XML deve essere evidente. Una classe MAUI .NET (ad esempio ContentPage o Label) viene visualizzata nel file XAML come elemento XML. Le proprietà di tale classe, incluse in Title
ContentPage e sette proprietà di Label vengono in genere visualizzate come attributi XML.
Esistono molti collegamenti per impostare i valori di queste proprietà. Alcune proprietà sono tipi di dati di base. Ad esempio, le Title
proprietà e Text
sono di tipo string
e Rotation
è di tipo double
. La HorizontalTextAlignment
proprietà è di tipo TextAlignment, che è un'enumerazione . Per una proprietà di qualsiasi tipo di enumerazione, è sufficiente specificare un nome membro.
Per le proprietà di tipi più complessi, tuttavia, i convertitori vengono usati per l'analisi del codice XAML. Si tratta di classi in .NET MAUI che derivano da TypeConverter
. Per l'esempio precedente, diversi convertitori MAUI .NET vengono applicati automaticamente per convertire i valori stringa nel tipo corretto:
LayoutOptionsConverter
per laVerticalOptions
proprietà . Questo convertitore converte i nomi dei campi statici pubblici dellaLayoutOptions
struttura in valori di tipoLayoutOptions
.ColorTypeConverter
per laTextColor
proprietà . Questo convertitore converte i nomi dei campi statici pubblici della Colors classe o dei valori RGB esadecimali, con o senza un canale alfa.
Spostamento tra le pagine
Quando si esegue un'app MAUI .NET, viene MainPage
in genere visualizzato . Per visualizzare una pagina diversa, è possibile impostarla come nuova pagina di avvio nel file AppShell.xaml oppure passare alla nuova pagina da MainPage
.
Per implementare la navigazione, nel costruttore MainPage.xaml.cs è possibile creare un gestore eventi semplice Button e usare il gestore eventi per passare 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;
}
Quando si compila e si distribuisce la nuova versione di questa app, viene visualizzato un pulsante sullo schermo. Premendo si passa a HelloXamlPage
:
È possibile tornare a MainPage
usando la barra di spostamento visualizzata in ogni piattaforma.
Nota
Un'alternativa a questo modello di navigazione consiste nell'usare .NET MAUI Shell. Per altre informazioni, vedere Panoramica della shell MAUI di .NET.
Interazioni con XAML e codice
L'elemento figlio della maggior parte ContentPage dei derivati è un layout, ad esempio o StackLayout , Gride il layout può contenere più elementi figlio. In XAML queste relazioni padre-figlio vengono stabilite con la normale gerarchia XML:
<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>
Questo file XAML è sintatticamente completo e produce l'interfaccia utente seguente:
Tuttavia, mentre è possibile interagire con Slider e Button, l'interfaccia utente non viene aggiornata. Deve Slider fare in modo che l'oggetto Label visualizzi il valore corrente e deve eseguire un'operazione Button .
La visualizzazione di un Slider valore tramite un Label oggetto può essere ottenuta interamente in XAML con un data binding. Tuttavia, è utile vedere prima la soluzione di codice. Anche in questo caso, la gestione del Button clic richiede sicuramente il codice. Ciò significa che il file code-behind per XamlPlusCodePage
deve contenere gestori per l'evento ValueChanged
di Slider e l'evento Clicked
di 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");
}
}
}
Nel file XAML i Slider tag e Button devono includere attributi per gli ValueChanged
eventi e Clicked
che fanno riferimento a questi gestori:
<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>
Si noti che l'assegnazione di un gestore a un evento ha la stessa sintassi dell'assegnazione di un valore a una proprietà. Inoltre, affinché il ValueChanged
gestore eventi dell'oggetto Slider usi Label per visualizzare il valore corrente, il gestore deve fare riferimento a tale oggetto dal codice. Pertanto, richiede Label un nome, specificato con l'attributo x:Name
. Il x
prefisso dell'attributo x:Name
indica che questo attributo è intrinseco a XAML. Il nome assegnato all'attributo x:Name
ha le stesse regole dei nomi delle variabili C#. Ad esempio, deve iniziare con una lettera o un carattere di sottolineatura e non contenere spazi incorporati.
Il ValueChanged
gestore eventi può ora impostare per Label visualizzare il nuovo Slider valore, disponibile dagli argomenti dell'evento:
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
valueLabel.Text = args.NewValue.ToString("F3");
}
In alternativa, il gestore può ottenere l'oggetto Slider che genera questo evento dall'argomento sender
e ottenere la Value
proprietà da tale oggetto:
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
valueLabel.Text = ((Slider)sender).Value.ToString("F3");
}
Il risultato è che qualsiasi manipolazione dell'oggetto Slider determina la visualizzazione del relativo valore in Label:
Nell'esempio precedente simula Button una risposta a un Clicked
evento visualizzando un avviso con il Text
pulsante . Pertanto, il gestore eventi può eseguire il cast dell'argomento sender
a e Button quindi accedere alle relative proprietà:
async void OnButtonClicked(object sender, EventArgs args)
{
Button button = (Button)sender;
await DisplayAlert("Clicked!", "The button labeled '" + button.Text + "' has been clicked", "OK");
}
Il OnButtonClicked
metodo viene definito come async
perché il DisplayAlert metodo è asincrono e deve essere preceduto dall'operatore await
, che restituisce al termine del metodo . Poiché questo metodo ottiene la generazione dell'evento Button dall'argomento sender
, lo stesso gestore può essere usato per più pulsanti.
Passaggi successivi
XAML è progettato principalmente per la creazione di istanze e l'inizializzazione di oggetti. Spesso, tuttavia, le proprietà devono essere impostate su oggetti complessi che non possono essere facilmente rappresentati come stringhe XML e talvolta le proprietà definite da una classe devono essere impostate su una classe figlio. Queste due esigenze richiedono le funzionalità di sintassi XAML essenziali degli elementi delle proprietà e delle proprietà associate.