Xamarin.Forms Approfondimento della guida introduttiva

Nella guida introduttiva è Xamarin.Forms stata compilata l'applicazione Notes. Questo articolo esamina ciò che è stato creato per comprendere i concetti fondamentali del funzionamento Xamarin.Forms delle applicazioni Shell.

Introduzione a Visual Studio

Visual Studio consente di organizzare il codice in soluzioni e progetti. Una soluzione è un contenitore per uno o più progetti. Un progetto può essere un'applicazione, una libreria di supporto, un'applicazione di test e altro ancora. L'applicazione Notes è costituita da una soluzione contenente tre progetti, come illustra lo screenshot seguente:

Visual Studio Solution Explorer

I progetti sono:

  • Notes: progetto di libreria .NET Standard che contiene tutto il codice condiviso e l'interfaccia utente condivisa.
  • Notes.Android: progetto che contiene il codice specifico di Android ed è il punto di ingresso per l'applicazione Android.
  • Notes.iOS: progetto che contiene il codice specifico di iOS ed è il punto di ingresso per l'applicazione iOS.

Anatomia di un'applicazione Xamarin.Forms

Lo screenshot seguente illustra il contenuto del progetto di libreria .NET Standard Notes in Visual Studio:

Phoneword .NET Standard Project Contents

Il progetto ha un nodo Dipendenze contenente i nodi NuGet e SDK:

  • NuGet: i Xamarin.Formspacchetti NuGet , Newtonsoft.Json Xamarin.Essentialse sqlite-net-pcl aggiunti al progetto.
  • SDK : NETStandard.Library metapacchetto che fa riferimento al set completo di pacchetti NuGet che definiscono .NET Standard.

Introduzione a Visual Studio per Mac

Visual Studio per Mac segue la prassi di Visual Studio di organizzare il codice in soluzioni e progetti. Una soluzione è un contenitore per uno o più progetti. Un progetto può essere un'applicazione, una libreria di supporto, un'applicazione di test e altro ancora. L'applicazione Notes è costituita da una soluzione contenente tre progetti, come illustra lo screenshot seguente:

Visual Studio for Mac Solution Pane

I progetti sono:

  • Notes: progetto di libreria .NET Standard che contiene tutto il codice condiviso e l'interfaccia utente condivisa.
  • Notes.Android: progetto che contiene il codice specifico di Android ed è il punto di ingresso per le applicazioni Android.
  • Notes.iOS: progetto che contiene il codice specifico di iOS ed è il punto di ingresso per le applicazioni iOS.

Anatomia di un'applicazione Xamarin.Forms

Lo screenshot seguente illustra il contenuto del progetto di libreria .NET Standard Notes in Visual Studio per Mac:

Phoneword .NET Standard Library Project Contents

Il progetto ha un nodo Dipendenze contenente i nodi NuGet e SDK:

  • NuGet: i Xamarin.Formspacchetti NuGet , Newtonsoft.Json Xamarin.Essentialse sqlite-net-pcl aggiunti al progetto.
  • SDK : NETStandard.Library metapacchetto che fa riferimento al set completo di pacchetti NuGet che definiscono .NET Standard.

Il progetto è costituito anche da più file:

  • Data\NoteDatabase.cs: questa classe contiene il codice per creare il database, leggere i dati dal database, scrivere i dati in esso ed eliminarli.
  • Models\Note.cs: questa classe definisce un modello Note le cui istanze archiviano i dati relativi a ogni nota nell'applicazione.
  • Views\AboutPage.xaml : markup XAML per la AboutPage classe , che definisce l'interfaccia utente per la pagina about.
  • Views\AboutPage.xaml.cs : code-behind per la AboutPage classe , che contiene la logica di business eseguita quando l'utente interagisce con la pagina.
  • Views\NotesPage.xaml : markup XAML per la NotesPage classe , che definisce l'interfaccia utente per la pagina visualizzata all'avvio dell'applicazione.
  • Views\NotesPage.xaml.cs : code-behind per la NotesPage classe , che contiene la logica di business eseguita quando l'utente interagisce con la pagina.
  • Views\NoteEntryPage.xaml : markup XAML per la NoteEntryPage classe , che definisce l'interfaccia utente per la pagina visualizzata quando l'utente immette una nota.
  • Views\NoteEntryPage.xaml.cs : code-behind per la NoteEntryPage classe , che contiene la logica di business eseguita quando l'utente interagisce con la pagina.
  • App.xaml: markup XAML per la classe App, che definisce un dizionario risorse per l'applicazione.
  • App.xaml.cs: code-behind per la App classe , responsabile della creazione di un'istanza dell'applicazione Shell e della gestione degli eventi del ciclo di vita dell'applicazione.
  • AppShell.xaml : markup XAML per la AppShell classe , che definisce la gerarchia visiva dell'applicazione.
  • AppShell.xaml.cs: code-behind per la AppShell classe , che crea una route per in NoteEntryPage modo che possa essere spostata a livello di codice.
  • AssemblyInfo.cs: questo file contiene un attributo dell'applicazione relativo al progetto, applicato a livello di assembly.

Per altre informazioni sull'anatomia di un'applicazione Xamarin.iOS, vedere l'analisi dettagliata di un'applicazione Xamarin.iOS. Per altre informazioni sull'anatomia di un'applicazione Xamarin.Android, vedere l'analisi dettagliata di un'applicazione Xamarin.Android.

Architettura e concetti fondamentali dell'applicazione

Un'applicazione Xamarin.Forms è progettata nello stesso modo di un'applicazione multipiattaforma tradizionale. Il codice condiviso in genere viene inserito in una libreria .NET Standard e le applicazioni specifiche della piattaforma usano il codice condiviso. Il diagramma seguente illustra una panoramica di questa relazione per l'applicazione Notes:

Notes Architecture

Per ottimizzare il riutilizzo del codice di avvio, Xamarin.Forms le applicazioni hanno una singola classe denominata App responsabile della creazione di un'istanza dell'applicazione in ogni piattaforma, come illustrato nell'esempio di codice seguente:

using Xamarin.Forms;

namespace Notes
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new AppShell();
        }
        // ...
    }
}

Questo codice imposta la MainPage proprietà della App classe sull'oggetto AppShell . La AppShell classe definisce la gerarchia visiva dell'applicazione. Shell accetta questa gerarchia visiva e produce l'interfaccia utente. Per altre informazioni sulla definizione della gerarchia visiva dell'applicazione, vedere Gerarchia visiva dell'applicazione.

Il file AssemblyInfo.cs contiene inoltre un singolo attributo dell'applicazione, applicato a livello di assembly:

using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]

L'attributo XamlCompilation attiva il compilatore XAML, in modo che il codice XAML venga compilato direttamente in linguaggio intermedio. Per altre informazioni, vedere XAML Compilation (Compilazione XAML).

Avviare l'applicazione in ogni piattaforma

La modalità di avvio dell'applicazione in ogni piattaforma è specifica per la piattaforma.

iOS

Per avviare la pagina iniziale Xamarin.Forms in iOS, il progetto Notes.iOS definisce la AppDelegate classe che eredita dalla FormsApplicationDelegate classe :

namespace Notes.iOS
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App());
            return base.FinishedLaunching(app, options);
        }
    }
}

L'override FinishedLaunching inizializza il Xamarin.Forms framework chiamando il Init metodo . In questo modo l'implementazione specifica di iOS di Xamarin.Forms deve essere caricata nell'applicazione prima che il controller di visualizzazione radice venga impostato dalla chiamata al LoadApplication metodo .

Android

Per avviare la pagina iniziale Xamarin.Forms in Android, il progetto Notes.Android include il codice che crea un Activity oggetto con l'attributo , con l'attività MainLauncher che eredita dalla FormsAppCompatActivity classe :

namespace Notes.Droid
{
    [Activity(Label = "Notes",
              Icon = "@mipmap/icon",
              Theme = "@style/MainTheme",
              MainLauncher = true,
              ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
        }
    }
}

L'override OnCreate inizializza il Xamarin.Forms framework chiamando il Init metodo . In questo modo, l'implementazione specifica di Android di Xamarin.Forms deve essere caricata nell'applicazione prima del caricamento dell'applicazione Xamarin.Forms .

Gerarchia visiva dell'applicazione

Xamarin.Forms Le applicazioni shell definiscono la gerarchia visiva dell'applicazione in una classe che sottoclassa la Shell classe . Nell'applicazione Notes si tratta della Appshell classe :

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:views="clr-namespace:Notes.Views"
       x:Class="Notes.AppShell">
    <TabBar>
        <ShellContent Title="Notes"
                      Icon="icon_feed.png"
                      ContentTemplate="{DataTemplate views:NotesPage}" />
        <ShellContent Title="About"
                      Icon="icon_about.png"
                      ContentTemplate="{DataTemplate views:AboutPage}" />
    </TabBar>
</Shell>

Questo codice XAML è costituito da due oggetti principali:

  • TabBar. TabBar Rappresenta la barra delle schede inferiore e deve essere usata quando il modello di spostamento per l'applicazione usa schede inferiori. L'oggetto TabBar è un elemento figlio dell'oggetto Shell.
  • ShellContent, che rappresenta gli ContentPage oggetti per ogni scheda dell'oggetto TabBar. Ogni ShellContent oggetto è un elemento figlio dell'oggetto TabBar .

Questi oggetti non rappresentano alcuna interfaccia utente, ma piuttosto l'organizzazione della gerarchia visiva dell'applicazione. Shell prenderà questi oggetti e genererà l'interfaccia utente di spostamento per il contenuto. Pertanto, la AppShell classe definisce due pagine navigabili dalle schede inferiori. Le pagine vengono create su richiesta, in risposta alla navigazione.

Per altre informazioni sulle applicazioni Shell, vedere Xamarin.Forms Shell.

Interfaccia utente

Esistono diversi gruppi di controllo usati per creare l'interfaccia utente di un'applicazione Xamarin.Forms :

  1. Pagine : Xamarin.Forms le pagine rappresentano schermate dell'applicazione per dispositivi mobili multipiattaforma. L'applicazione Notes usa la classe ContentPage per visualizzare una singola schermata. Per altre informazioni sulle pagine, vedere Xamarin.Forms Pagine.
  2. Visualizzazioni : Xamarin.Forms le visualizzazioni sono i controlli visualizzati nell'interfaccia utente, ad esempio etichette, pulsanti e caselle di immissione di testo. L'applicazione Notes completata usa le visualizzazioni CollectionView, Editor e Button. Per altre informazioni sulle visualizzazioni, vedere Xamarin.Forms Viste.
  3. Layout: iXamarin.Forms layout sono contenitori usati per comporre visualizzazioni in strutture logiche. L'applicazione Notes usa la classe StackLayout per disporre le visualizzazioni in uno stack verticale e la classe Grid per disporre i pulsanti orizzontalmente. Per altre informazioni sui layout, vedere Xamarin.Forms Layout.

In fase di runtime ogni controllo viene mappato al controllo nativo equivalente, che viene restituito nel rendering.

Layout

L'applicazione Notes usa la classe StackLayout per semplificare lo sviluppo di applicazioni multipiattaforma disponendo automaticamente le visualizzazioni nella schermata, indipendentemente dalle dimensioni della schermata. Gli elementi figlio vengono posizionati uno dopo l'altro, orizzontalmente o verticalmente, nell'ordine in cui sono stati aggiunti. La quantità di spazio usata dall'elemento StackLayout dipende dall'impostazione delle proprietà HorizontalOptions e VerticalOptions, ma per impostazione predefinita StackLayout prova a usare l'intero schermo.

Il codice XAML seguente mostra un esempio dell'uso di una classe StackLayout per il layout di NoteEntryPage:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Notes.Views.NoteEntryPage"
             Title="Note Entry">
    ...    
    <StackLayout Margin="{StaticResource PageMargin}">
        <Editor Placeholder="Enter your note"
                Text="{Binding Text}"
                HeightRequest="100" />
        <Grid>
            ...
        </Grid>
    </StackLayout>    
</ContentPage>

Per impostazione predefinita, la classe StackLayout presuppone un orientamento verticale, che può tuttavia essere sostituito da un orientamento orizzontale impostando la proprietà StackLayout.Orientation sul membro dell'enumerazione StackOrientation.Horizontal.

Nota

Le dimensioni delle visualizzazioni possono essere impostate tramite le proprietà HeightRequest e WidthRequest.

Per altre informazioni sulla StackLayout classe, vedere Xamarin.Forms StackLayout.

Risposta all'interazione dell'utente

Un oggetto definito in XAML può generare un evento che viene gestito nel file code-behind. L'esempio di codice seguente illustra il metodo OnSaveButtonClicked nel code-behind per la classe NoteEntryPage, eseguito in risposta alla generazione dell'evento Clicked per il pulsante Save.

async void OnSaveButtonClicked(object sender, EventArgs e)
{
    var note = (Note)BindingContext;
    note.Date = DateTime.UtcNow;
    if (!string.IsNullOrWhiteSpace(note.Text))
    {
        await App.Database.SaveNoteAsync(note);
    }
    await Shell.Current.GoToAsync("..");
}

Il metodo OnSaveButtonClicked salva la nota nel database e torna alla pagina precedente. Per altre informazioni sulla navigazione, vedere Navigazione.

Nota

Il file code-behind per una classe XAML è in grado di accedere a un oggetto definito in XAML usando il nome assegnato con l'attributo x:Name. Il valore assegnato a questo attributo ha le stesse regole delle variabili di C#, poiché deve iniziare con una lettera o un carattere di sottolineatura e non contenere spazi incorporati.

L'associazione del pulsante di salvataggio al metodo OnSaveButtonClicked si verifica nel markup XAML per la classe NoteEntryPage:

<Button Text="Save"
        Clicked="OnSaveButtonClicked" />

Elenchi

È CollectionView responsabile della visualizzazione di una raccolta di elementi in un elenco. Per impostazione predefinita, gli elementi dell'elenco vengono visualizzati verticalmente e ogni elemento viene visualizzato in una singola riga.

L'esempio di codice seguente visualizza la classe CollectionView da NotesPage:

<CollectionView x:Name="collectionView"
                Margin="{StaticResource PageMargin}"
                SelectionMode="Single"
                SelectionChanged="OnSelectionChanged">
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Vertical"
                           ItemSpacing="10" />
    </CollectionView.ItemsLayout>
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <StackLayout>
                <Label Text="{Binding Text}"
                       FontSize="Medium" />
                <Label Text="{Binding Date}"
                       TextColor="{StaticResource TertiaryColor}"
                       FontSize="Small" />
            </StackLayout>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Il layout di ogni riga in CollectionView viene definito all'interno dell'elemento CollectionView.ItemTemplate e usa il data binding per visualizzare le note recuperate dall'applicazione. La CollectionView.ItemsSource proprietà è impostata sull'origine dati, in NotesPage.xaml.cs:

protected override async void OnAppearing()
{
    base.OnAppearing();

    collectionView.ItemsSource = await App.Database.GetNotesAsync();
}

Questo codice popola con CollectionView tutte le note archiviate nel database e viene eseguito quando viene visualizzata la pagina.

Quando un elemento viene selezionato in CollectionView, l'evento SelectionChanged viene generato. Un gestore eventi, denominato OnSelectionChanged, viene eseguito quando viene generato l'evento:

async void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.CurrentSelection != null)
    {
        // ...
    }
}

L'evento SelectionChanged può accedere all'oggetto associato all'elemento tramite la e.CurrentSelection proprietà .

Per altre informazioni sulla CollectionView classe, vedere Xamarin.Forms CollectionView.

La navigazione in un'applicazione shell avviene specificando un URI a cui passare. Gli URI di spostamento hanno tre componenti:

  • Una route, che definisce il percorso del contenuto esistente nell'ambito della gerarchia visiva di Shell.
  • Una pagina. Se le pagine non sono presenti nella gerarchia visiva della shell, è possibile eseguirne il push nello stack di navigazione da qualsiasi posizione all'interno di un'applicazione shell. Ad esempio, NoteEntryPage non è definito nella gerarchia visiva della shell, ma può essere inserito nello stack di navigazione in base alle esigenze.
  • Uno o più parametri di query. I parametri di query possono essere passati alla pagina di destinazione durante lo spostamento.

Un URI di spostamento non deve includere tutti e tre i componenti, ma quando la struttura è: //route/page?queryParameters

Nota

Le route possono essere definite sugli elementi nella gerarchia visiva della shell tramite la Route proprietà . Tuttavia, se la Route proprietà non è impostata, ad esempio nell'applicazione Notes, viene generata una route in fase di esecuzione.

Per altre informazioni sullo spostamento nella shell, vedere Xamarin.Forms Navigazione nella shell.

Registrare le route

Per passare a una pagina che non esiste nella gerarchia di oggetti visivi della shell, è necessario che venga registrata prima con il sistema di routing shell. utilizzando il Routing.RegisterRoute metodo . Nell'applicazione Notes questo si verifica nel AppShell costruttore:

public partial class AppShell : Shell
{
    public AppShell()
    {
        // ...
        Routing.RegisterRoute(nameof(NoteEntryPage), typeof(NoteEntryPage));
    }
}

In questo esempio una route denominata NoteEntryPage viene registrata sul NoteEntryPage tipo . È quindi possibile passare a questa pagina usando lo spostamento basato su URI, da qualsiasi punto dell'applicazione.

Eseguire la navigazione

La navigazione viene eseguita dal GoToAsync metodo , che accetta un argomento che rappresenta la route a cui passare:

await Shell.Current.GoToAsync("NoteEntryPage");

In questo esempio si NoteEntryPage passa a .

Importante

Uno stack di spostamento viene creato quando si passa a una pagina che non si trova nella gerarchia visiva della shell.

Quando si passa a una pagina, i dati possono essere passati alla pagina come parametro di query:

async void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.CurrentSelection != null)
    {
        // Navigate to the NoteEntryPage, passing the ID as a query parameter.
        Note note = (Note)e.CurrentSelection.FirstOrDefault();
        await Shell.Current.GoToAsync($"{nameof(NoteEntryPage)}?{nameof(NoteEntryPage.ItemId)}={note.ID.ToString()}");
    }
}

Questo esempio recupera l'elemento attualmente selezionato in CollectionView e passa a NoteEntryPage, con il valore della proprietà dell'oggetto IDNote passato come parametro di query alla NoteEntryPage.ItemId proprietà .

Per ricevere i dati passati, la NoteEntryPage classe viene decorata con QueryPropertyAttribute

[QueryProperty(nameof(ItemId), nameof(ItemId))]
public partial class NoteEntryPage : ContentPage
{
    public string ItemId
    {
        set
        {
            LoadNote(value);
        }
    }
    // ...
}

Il primo argomento per l'oggetto QueryPropertyAttribute specifica che la ItemId proprietà riceverà i dati passati, con il secondo argomento che specifica l'ID del parametro di query. Pertanto, QueryPropertyAttribute nell'esempio precedente viene specificato che la ItemId proprietà riceverà i dati passati nel ItemId parametro di query dall'URI nella chiamata al GoToAsync metodo. La ItemId proprietà chiama quindi il LoadNote metodo per recuperare la nota dal dispositivo.

Lo spostamento all'indietro viene eseguito specificando ".." come argomento del GoToAsync metodo :

await Shell.Current.GoToAsync("..");

Per altre informazioni sulla navigazione all'indietro, vedere Spostamento indietro.

Data binding

Il data binding viene usato per semplificare la visualizzazione e l'interazione di un'applicazione Xamarin.Forms con i relativi dati. Stabilisce una connessione tra l'interfaccia utente e l'applicazione sottostante. La classe BindableObject contiene la maggior parte dell'infrastruttura per supportare il data binding.

Il data binding (o associazione di dati) consente di connettere due oggetti, detti oggetti di origine e di destinazione. L'oggetto di origine visualizza i dati. L'oggetto di destinazione usa (e spesso visualizza) i dati dall'oggetto di origine. Ad esempio un Editor (oggetto di destinazione) associa comunemente la proprietà Text a una proprietà string pubblica in un oggetto di origine. Il diagramma che segue illustra la relazione di associazione:

Data Binding

Il vantaggio principale del data binding sta nel fatto che non è più necessario preoccuparsi della sincronizzazione tra le visualizzazioni e l'origine dati. Le modifiche apportate all'oggetto di origine vengono trasmesse automaticamente in background all'oggetto di destinazione dal framework di associazione. Facoltativamente, le modifiche all'oggetto di destinazione possono anche essere respinte all'oggetto di origine.

La definizione del data binding è un processo in due fasi:

  • La proprietà BindingContext dell'oggetto di destinazione deve essere impostata sull'origine.
  • È necessario stabilire un'associazione tra la destinazione e l'origine. In XAML questo si ottiene usando l'estensione di markup Binding.

Nell'applicazione Notes la destinazione del binding è l'Editor che visualizza una nota, mentre l'istanza di Note impostata come BindingContext di NoteEntryPage è l'origine del binding. Inizialmente, l'oggetto BindingContextNoteEntryPage di viene impostato quando viene eseguito il costruttore della pagina:

public NoteEntryPage()
{
    // ...
    BindingContext = new Note();
}

In questo esempio, la pagina BindingContext viene impostata su un nuovo Note oggetto quando NoteEntryPage viene creato . In questo modo viene gestito lo scenario di aggiunta di una nuova nota all'applicazione.

Inoltre, la pagina BindingContext può anche essere impostata quando si sposta su NoteEntryPage , purché sia stata selezionata una nota esistente in NotesPage:

[QueryProperty(nameof(ItemId), nameof(ItemId))]
public partial class NoteEntryPage : ContentPage
{
    public string ItemId
    {
        set
        {
            LoadNote(value);
        }

        async void LoadNote(string itemId)
        {
            try
            {
                int id = Convert.ToInt32(itemId);
                // Retrieve the note and set it as the BindingContext of the page.
                Note note = await App.Database.GetNoteAsync(id);
                BindingContext = note;
            }
            catch (Exception)
            {
                Console.WriteLine("Failed to load note.");
            }
        }    
        // ...    
    }
}

In questo esempio, quando si verifica lo spostamento della pagina, la pagina viene impostata sull'oggetto BindingContext selezionato Note dopo che è stato recuperato dal database.

Importante

È possibile impostare individualmente la proprietà BindingContext di ogni oggetto di destinazione, ma questa operazione non è necessaria. BindingContext è una proprietà speciale che viene ereditata da tutti gli elementi figlio. Pertanto quando la proprietà BindingContext in ContentPage è impostata su un'istanza di Note, tutti gli elementi figlio di ContentPage hanno la stessa proprietà BindingContext e possono eseguire il binding alle proprietà pubbliche dell'oggetto Note.

L'Editor in NoteEntryPage esegue quindi il binding alla proprietà Text dell'oggetto Note:

<Editor Placeholder="Enter your note"
        Text="{Binding Text}" />

Viene definita un'associazione tra la proprietà Editor.Text e la proprietà Text dell'oggetto di origine. Le modifiche apportate nell'Editor vengono propagate automaticamente all'oggetto Note. Analogamente, se vengono apportate modifiche alla Note.Text proprietà , il Xamarin.Forms motore di associazione aggiornerà anche il contenuto di Editor. Questa funzionalità è detta associazione bidirezionale.

Per altre informazioni sul data binding, vedere Xamarin.Forms Data Binding.

Applicazione stile in corso

Xamarin.Forms le applicazioni contengono spesso più elementi visivi che hanno un aspetto identico. L'impostazione dell'aspetto di ogni elemento visivo può essere ripetitiva e soggetta a errori. È invece possibile creare stili che definiscono l'aspetto e applicarli agli elementi visivi necessari.

La classe Style raggruppa una raccolta di valori delle proprietà in un oggetto che può quindi essere applicato a più istanze di un elemento visivo. Gli stili vengono archiviati in una classe ResourceDictionary a livello di applicazione, di pagina o di visualizzazione. Scegliere dove definire un oggetto Style ha effetto su dove può essere usato:

  • Le istanze di Style definite a livello di applicazione possono essere applicate in tutta l'applicazione.
  • Le istanze di Style definite a livello di pagina possono essere applicate alla pagina e agli elementi figlio.
  • Le istanze di Style definite a livello di visualizzazione possono essere applicate alla visualizzazione e agli elementi figlio.

Importante

Tutti gli stili usati nell'applicazione vengono archiviati nel dizionario risorse dell'applicazione per evitare duplicati. Tuttavia, il codice XAML specifico di una pagina non deve essere incluso nel dizionario risorse dell'applicazione per evitare che le risorse vengano analizzate all'avvio dell'applicazione invece che quando richiesto da una pagina. Per altre informazioni, vedere Ridurre le dimensioni del dizionario risorse dell'applicazione.

Ogni istanza di Style contiene una raccolta di uno o più oggetti Setter e ogni Setter ha una proprietà Property e una proprietà Value. Property è il nome della proprietà associabile dell'elemento a cui viene applicato lo stile e Value è il valore applicato alla proprietà. L'esempio di codice seguente illustra uno stile da NoteEntryPage:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Notes.Views.NoteEntryPage"
             Title="Note Entry">
    <ContentPage.Resources>
        <!-- Implicit styles -->
        <Style TargetType="{x:Type Editor}">
            <Setter Property="BackgroundColor"
                    Value="{StaticResource AppBackgroundColor}" />
        </Style>
        ...
    </ContentPage.Resources>
    ...
</ContentPage>

Questo stile viene applicato a qualsiasi istanza di Editor nella pagina.

Quando si crea una classe Style, la proprietà TargetType è sempre obbligatoria.

Nota

Lo stile di un'applicazione Xamarin.Forms viene tradizionalmente eseguito usando gli stili XAML. Tuttavia, Xamarin.Forms supporta anche lo stile degli elementi visivi usando css (Cascading Style Sheets). Per altre informazioni, vedere Applicazione Xamarin.Forms di stili alle app con fogli di stile CSS (Cascading Style Sheets).

Per altre informazioni sugli stili XAML, vedi Applicazione Xamarin.Forms di stili alle app con stili XAML.

Test e distribuzione

Visual Studio per Mac e Visual Studio offrono entrambi numerose opzioni per il test e la distribuzione di un'applicazione. Il debug delle applicazioni fa parte del ciclo di vita dello sviluppo delle applicazioni e consente di diagnosticare i problemi del codice. Per altre informazioni, vedere gli articoli relativi all'impostazione di un punto di interruzione, al passaggio attraverso il codice e all'output di informazioni alla finestra del log.

I simulatori sono un ottimo strumento per iniziare a distribuire e testare e offrono funzionalità utili per testare le applicazioni. Tuttavia, gli utenti non useranno l'applicazione finale in un simulatore, quindi le applicazioni devono essere testate nei dispositivi reali presto e spesso. Per altre informazioni sul provisioning dei dispositivi iOS, vedere Provisioning dei dispositivi. Per altre informazioni sul provisioning dei dispositivi Android, vedere Set Up Device for Development (Configurare il dispositivo per lo sviluppo).

Passaggi successivi

Questo approfondimento ha esaminato i concetti fondamentali dello sviluppo di applicazioni tramite Xamarin.Forms Shell. I passaggi suggeriti che seguono includono informazioni sulle funzionalità seguenti:

  • Xamarin.Forms Shell riduce la complessità dello sviluppo di applicazioni per dispositivi mobili fornendo le funzionalità fondamentali richieste dalla maggior parte delle applicazioni per dispositivi mobili. Per altre informazioni, vedere Xamarin.Forms Shell.
  • Esistono diversi gruppi di controllo usati per creare l'interfaccia utente di un'applicazione Xamarin.Forms . Per altre informazioni, vedere Riferimento per i controlli.
  • Il data binding è una tecnica che consente di collegare le proprietà di due oggetti in modo che le modifiche apportate a una proprietà vengano automaticamente riflesse nell'altra proprietà. Per altre informazioni, vedere Data Binding.
  • Xamarin.Forms offre più esperienze di spostamento delle pagine, a seconda del tipo di pagina in uso. Per altre informazioni, vedere Navigazione.
  • Gli stili consentono di ridurre il markup ripetitivo e di modificare facilmente l'aspetto di un'applicazione. Per altre informazioni, vedere Applicazione di stili Xamarin.Forms alle app.
  • I modelli di dati consentono di definire la presentazione dei dati nelle viste supportate. Per altre informazioni, vedere Data Templates (Modelli di dati).
  • Anche gli effetti consentono la personalizzazione dei controlli nativi in ogni piattaforma. Gli effetti vengono creati in progetti specifici della piattaforma sottoclassando la PlatformEffect classe e vengono utilizzati associandoli a un controllo appropriato Xamarin.Forms . Per altre informazioni, vedere Effects (Effetti).
  • Il rendering di ogni pagina, layout e vista viene eseguito in modo diverso su ogni piattaforma usando una classe Renderer che a sua volta crea un controllo nativo, lo dispone sullo schermo e aggiunge il comportamento specificato nel codice condiviso. Gli sviluppatori possono implementare le proprie classi Renderer per personalizzare l'aspetto e/o il comportamento di un controllo. Per altre informazioni, vedere Custom Renderers (Renderer personalizzati).
  • Il codice condiviso può accedere alle funzionalità native tramite la classe DependencyService. Per altre informazioni, vedere Accessing Native Features with DependencyService (Accesso alle funzionalità native con DependencyService).

Altri video di Xamarin sono disponibili su Channel 9 e YouTube.