Tipi e proprietà in XAML per .NET MAUI

Completato

XAML è un linguaggio di markup dichiarativo. Questo linguaggio è stato progettato allo scopo di semplificare il processo di creazione dell'interfaccia utente. Gli elementi della sintassi XAML rappresentano direttamente le istanze degli oggetti a cui si accede nei file code-behind.

In questa unità verranno fornite informazioni su come usare i tipi disponibili in XAML e come impostare e leggere le loro proprietà.

Dove vengono definiti i tipi?

.NET MAUI implementa un parser XAML che analizza gli elementi XAML dichiarati e crea un'istanza di ogni elemento come tipo .NET. Il dialetto XAML compreso dal parser di .NET MAUI è specifico di .NET MAUI, anche se è simile al codice XAML usato da altri framework come Windows Presentation Foundation.

I tipi .NET che implementano gli elementi identificati dal codice XAML vengono implementati dal codice in diversi assembly .NET. Molti di questi assembly sono inclusi nei modelli di .NET MAUI. È anche possibile utilizzare altri tipi personalizzati caricando gli assembly appropriati come parte del progetto. Molti assembly sono disponibili come pacchetti NuGet. La maggior parte dei tipi comuni che usa un'app MAUI sono inclusi nei pacchetti Microsoft.Maui.Dependencies e Microsoft.Maui.Extensions.

Ogni tipo è definito in uno spazio dei nomi. Nel codice XAML vengono specificati gli spazi dei nomi per i tipi di riferimento. La maggior parte dei controlli MAUI si trova nello spazio dei nomi Microsoft.Maui.Controls, mentre lo spazio dei nomi Microsoft.Maui definisce tipi di utilità come Thickness, mentre lo spazio dei nomi Microsoft.Maui.Graphics include tipi generalizzati come Color. La possibilità di introdurre tipi in questo modo è una prova evidente dell'estendibilità del linguaggio XAML. XAML consente di creare l'interfaccia utente dell'app con la libertà di includere elementi .NET MAUI XAML, tipi .NET e tipi personalizzati. Nella maggior parte dei casi non è necessario preoccuparsi di questi spazi dei nomi in quanto vengono introdotti utilizzando la funzionalità usings implicita di C#, che li aggiunge automaticamente a livello di app.

Come creare istanze dei tipi in XAML

La prima operazione da eseguire quando si usa XAML per creare un'interfaccia utente è quella di creare istanze per i tipi di controllo dell'interfaccia utente. In XAML, è possibile creare un oggetto di un tipo specificato utilizzando la sintassi degli elementi oggetto. È una sintassi XML ben formata standard, che viene usata per dichiarare un elemento. Ad esempio, se si desidera creare un'etichetta con un colore specifico, l'elemento XAML è simile al codice seguente:

<Label TextColor="AntiqueWhite"/>

Il parser XAML di .NET MAUI analizza questo elemento XAML per creare un'istanza dell'oggetto in memoria. In effetti, l'etichetta di XAML analizzata equivale al codice C# seguente:

var myLabel = new Label
{
  TextColor = Color.FromRgb(255, 255, 100)
};

Che cos'è uno spazio dei nomi XAML?

Tenere presente che per analizzare correttamente la definizione XAML di un controllo in una pagina, il parser XAML deve avere accesso al codice che implementa il controllo e ne definisce le proprietà. I controlli disponibili per una pagina .NET MAUI vengono implementati in una raccolta di assembly installati come parte del pacchetto di NuGet Microsoft.Maui. I controlli si trovano in uno spazio dei nomi .NET in questi assembly. Nel codice C# viene inserito uno spazio dei nomi nell'ambito con la direttiva using. In una pagina XAML fare riferimento a uno spazio dei nomi con l'attributo xmlns della pagina. Il codice seguente mostra gli spazi dei nomi usati dalla pagina XAML creata nell'unità precedente:

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

    ...
</ContentPage>

Il primo spazio dei nomi http://schemas.microsoft.com/dotnet/2021/maui è lo spazio dei nomi predefinito della pagina. Questo formato URI dello spazio dei nomi è tipico di XML e ha un aspetto leggermente diverso da quello che probabilmente si conosce in C#. Tuttavia, questo URI è semplicemente un alias per uno o più spazi dei nomi definiti dagli assembly nel pacchetto di NuGet Microsoft.Maui, quindi se questo spazio dei nomi viene specificato all'inizio della pagina, tutti i tipi e i controlli .NET MAUI vengono inseriti nell'ambito. Se si omette questo spazio dei nomi, non sarà possibile usare controlli come Button, Label, Entry o StackLayout.

Il secondo spazio dei nomi, http://schemas.microsoft.com/winfx/2009/xaml, fa riferimento agli assembly che contengono i vari tipi intrinseci di .NET, ad esempio stringhe, numeri e proprietà. Nel codice XAML precedente, a questo spazio dei nomi è assegnato l'alias x. Nel codice XAML per questa pagina fare riferimento ai tipi in questo spazio dei nomi con il prefisso x:. Ad esempio ogni pagina XAML viene compilata in una classe e viene specificato il nome della classe generata con l'attributo della pagina x:Class:

<ContentPage ...
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiXaml.Page1"
            ...>

    ...
</ContentPage>

È possibile fare riferimento ai tipi negli assembly nel codice XAML tramite uno spazio dei nomi XAML. Ad esempio, se si vogliono usare tipi e metodi nel codice XAML definito in uno spazio dei nomi nel progetto denominato Utils, è possibile aggiungere lo spazio dei nomi Utils alla pagina come illustrato nel codice che segue. In questo esempio è possibile accedere ai tipi in questo spazio dei nomi anteponendo loro il prefisso alias mycode.

<ContentPage ...
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:mycode="clr-namespace:Utils"
            ...>

    ...
</ContentPage>

Nota

Sarà possibile vedere altri esempi di questa tecnica più avanti in questo modulo.

Come specificare i valori delle proprietà in XAML

In XML gli attributi vengono usati per descrivere o fornire informazioni su un elemento. In XAML, gli attributi vengono usati per impostare le proprietà nel tipo sottostante. Si prenda ad esempio il codice C# seguente:

var label = new Label { Text = "Username", TextColor = Color.Black };

Questa istruzione crea un nuovo oggetto Label e imposta le proprietà Text e TextColor. Per impostare le proprietà in XAML, vengono usati gli attributi. Il codice XAML corrispondente è simile al seguente:

<Label Text="Username" TextColor="Black" />

Una delle differenze che si potrebbero notare tra il codice XAML e il codice C# è costituita dai valori delle proprietà. Ad esempio, nel codice C# per la proprietà TextColor viene usato il tipo Color. Tuttavia, nella definizione XAML, viene impostato TextColor con un valore stringa. Questo perché una stringa è l'unico elemento valido che è possibile usare per un valore di attributo XML. Pertanto è necessario un modo per convertire ogni valore stringa nel tipo corretto. In XAML si può eseguire questa conversione usando un convertitore di tipi.

Che cos'è un convertitore di tipi?

Un convertitore di tipi converte il valore di un attributo XML specificato come valore stringa nel tipo corretto corrispondente. Per comprendere meglio questo concetto, considerare l'esempio seguente:

<Label Text="Username" TextColor="Black" FontSize="42" FontAttributes="Bold,Italic" />

Questo codice crea Label e imposta le proprietà Text, TextColor, FontSize e FontAttributes.

Si esamini innanzitutto la prima proprietà, Text. Il testo è già una stringa, ciò significa che la pagina XAML non ha bisogno di un convertitore di tipi. Successivamente, TextColor usa il tipo Color, quindi XAML richiede un convertitore di tipi per tradurre la stringa nel valore corrispondente Color. La proprietà FontSize è un tipo integer, quindi XAML richiede un convertitore di tipi per analizzare la stringa e convertirla in un integer. Infine, FontAttributes è un esempio di oggetto complesso. È possibile combinare i valori dell'oggetto sotto forma di stringa delimitata da virgole: "Bold,Italic". La stringa delimitata da virgole viene considerata come un'enumerazione basata su [Flags] e il convertitore di tipi appropriato applicherà l'operazione bit per bit OR del valore alla proprietà.

.NET MAUI include convertitori di tipi per la maggior parte delle classi predefinite e li usa automaticamente. Se tuttavia uno specifico convertitore di tipi non esiste, è possibile scriverne uno e associarlo al tipo per renderlo utilizzabile in XAML.

Assegnazione di tipi complessi

I convertitori di tipi sono ideali per le impostazioni delle proprietà semplici. In alcuni casi, tuttavia, è necessario creare un oggetto completo con specifici valori di proprietà. Per risolvere questo problema è necessario modificare l'assegnazione delle proprietà in modo da usare una sintassi basata su elementi. Questa sintassi è definita formato Proprietà Elemento. Si tratta di una sintassi che implica la suddivisione del setter della proprietà in un formato padre-figlio, in cui la proprietà viene espressa in un tag di elemento del modulo Type.PropertyName. Si supponga di voler assegnare un riconoscimento movimenti a un'etichetta in modo che l'utente dell'app possa toccare l'etichetta. Il riconoscitore di movimento è un oggetto complesso con proprietà specifiche. Per garantire il corretto funzionamento, in genere queste proprietà devono essere assegnate:

<TapGestureRecognizer NumberOfTapsRequired="2" />

Se devi assegnare questo valore a Label, puoi scrivere il codice XAML in questo modo:

<Label Text="Username" TextColor="Black" FontSize="42" FontAttributes="Bold,Italic">
    <Label.GestureRecognizers>
        <TapGestureRecognizer NumberOfTapsRequired="2" />
    </Label.GestureRecognizers>
</Label>

Il tipo Label dispone di una proprietà denominata GestureRecognizers. Usando la maschera Elemento proprietà, è possibile aggiungere un TapGestureRecognizer all'elenco di movimenti per Label.

Proprietà di contenuto predefinita

Alcuni controlli .NET MAUI hanno una proprietà di contenuto predefinita. La proprietà di contenuto consente di specificare il valore di una proprietà su un controllo senza specificarlo esplicitamente in XAML. Si esamini il frammento di codice XAML seguente:

<VerticalStackLayout>
    <VerticalStackLayout.Children>
        <Label Text="Please log in" />
    </VerticalStackLayout.Children>
</VerticalStackLayout>

Questo codice crea VerticalStackLayout e aggiunge Label come elemento figlio. Poiché all'elemento VerticalStackLayout vengono aggiunti di frequente elementi figlio, la relativa proprietà Children è la proprietà di contenuto predefinita. Ciò significa che è possibile aggiungere un elemento figlio senza specificare Childrenesplicitamente, come indicato di seguito:

<VerticalStackLayout>
    <Label Text="Please log in" />
</VerticalStackLayout>

Verifica delle conoscenze

1.

Che cosa fa un convertitore di tipi?

2.

Come trasferisci i tuoi tipi personalizzati nell'ambito in un file XAML?