Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa parte dell'esercitazione presenta i concetti relativi alle visualizzazioni dati e ai modelli.
Nei passaggi precedenti dell'esercitazione è stata aggiunta una nuova pagina al progetto che consente all'utente di salvare, modificare o eliminare una singola nota. Tuttavia, poiché l'app deve gestire più note, è necessario aggiungere un'altra pagina che visualizza tutte le note (chiamarla AllNotesPage). Questa pagina consente all'utente di scegliere una nota da aprire nella pagina dell'editor in modo che possa visualizzare, modificare o eliminarla. Dovrebbe anche consentire all'utente di creare una nuova nota.
A tale scopo, AllNotesPage deve avere una raccolta di note e un modo per visualizzare la raccolta. Questa è la posizione in cui l'app si verifica in problemi perché i dati delle note sono strettamente associati al NotePage file. In AllNotesPageè sufficiente visualizzare tutte le note in un elenco o in un'altra visualizzazione raccolta, con informazioni su ogni nota, ad esempio la data in cui è stata creata e un'anteprima del testo. Con il testo della nota strettamente associato al TextBox controllo, non è possibile eseguire questa operazione.
Prima di aggiungere una pagina per visualizzare tutte le note, apportare alcune modifiche per separare i dati delle note dalla presentazione della nota.
Visualizzazioni e modelli
In genere, un'app WinUI ha almeno un livello di visualizzazione e un livello dati.
Il livello di visualizzazione definisce l'interfaccia utente usando il markup XAML. Il markup include espressioni di data binding (ad esempio x:Bind) che definiscono la connessione tra componenti dell'interfaccia utente specifici e membri dati. I file code-behind vengono talvolta usati come parte del livello di visualizzazione per contenere codice aggiuntivo necessario per personalizzare o modificare l'interfaccia utente o per estrarre dati dagli argomenti del gestore eventi prima di chiamare un metodo che esegue il lavoro sui dati.
Il livello dati o il modello definisce i tipi che rappresentano i dati dell'app e la logica correlata. Questo livello è indipendente dal livello di visualizzazione ed è possibile creare più visualizzazioni diverse che interagiscono con i dati.
Attualmente, rappresenta NotePage una visualizzazione dei dati (il testo della nota). Tuttavia, dopo aver letto i dati nell'app dal file di sistema, esiste solo nella Text proprietà di TextBox in NotePage. Non è rappresentato nell'app in modo da presentare i dati in modi diversi o in posizioni diverse; ovvero, l'app non ha un livello dati. Il progetto verrà ora ristrutturato per creare il livello dati.
Separare la visualizzazione e il modello
Suggerimento
È possibile scaricare o visualizzare il codice per questa esercitazione dal repository GitHub. Per visualizzare il codice così com'è in questo passaggio, vedere questa pagina commit: nota - view-model.
Effettuare il refactoring del codice esistente per separare il modello dalla vista. I passaggi successivi organizzano il codice in modo che le visualizzazioni e i modelli vengano definiti separatamente l'uno dall'altro.
In Esplora soluzioni fare clic con il pulsante destro del mouse sul WinUINotes progetto e scegliere Aggiungi>nuova cartella. Denominare la cartella Models.
Fare di nuovo clic con il pulsante destro del mouse sul WinUINotes progetto e scegliere Aggiungi>nuova cartella. Denominare la cartella Views.
Trovare l'elemento NotePage.xaml e trascinarlo nella Views cartella . Il NotePage.xaml.cs file deve essere spostato con esso.
Annotazioni
Quando si sposta un file, Visual Studio richiede in genere un avviso su come l'operazione di spostamento potrebbe richiedere molto tempo. Questo non dovrebbe essere un problema qui, premere OK se viene visualizzato questo avviso.
Visual Studio può anche chiedere se si vuole modificare lo spazio dei nomi del file spostato. Selezionare No. Lo spazio dei nomi verrà modificato nei passaggi successivi.
Aggiornare lo spazio dei nomi della visualizzazione
Ora che la vista è stata spostata nella Views cartella, è necessario aggiornare gli spazi dei nomi in modo che corrispondano. Lo spazio dei nomi per i file XAML e code-behind delle pagine è impostato su WinUINotes. Questa operazione deve essere aggiornata a WinUINotes.Views.
Nel riquadro Esplora soluzioni espandere NotePage.xaml per visualizzare il file code-behind.
Fare doppio clic sull'elemento per aprire l'editor NotePage.xaml.cs di codice, se non è già aperto. Modificare lo spazio dei nomi in
WinUINotes.Views:namespace WinUINotes.ViewsFare doppio clic sull'elemento NotePage.xaml per aprire l'editor XAML, se non è già aperto. Viene fatto riferimento allo spazio dei nomi precedente tramite l'attributo
x:Class, che definisce quale tipo di classe è il code-behind per XAML. Questa voce non è solo lo spazio dei nomi, ma lo spazio dei nomi con il tipo . Modificare il valorex:ClassinWinUINotes.Views.NotePage:x:Class="WinUINotes.Views.NotePage"
Correggere il riferimento allo spazio dei nomi in MainWindow
Nel passaggio precedente è stata creata la pagina della nota e aggiornata MainWindow.xaml per spostarsi. Tenere presente che è stato eseguito il mapping dello local: spazio dei nomi. È pratica comune eseguire il mapping del nome local allo spazio dei nomi radice del progetto e il modello di progetto di Visual Studio esegue già questa operazione (xmlns:local="using:WinUINotes"). Ora che la pagina è stata spostata in un nuovo spazio dei nomi, il mapping dei tipi nel codice XAML non è valido.
Fortunatamente, è possibile aggiungere mapping dello spazio dei nomi personalizzati in base alle esigenze. È necessario eseguire questa operazione per accedere agli elementi in cartelle diverse create nel progetto. Questo nuovo spazio dei nomi XAML verrà mappato allo spazio dei nomi di WinUINotes.Views, quindi denominarlo views. La dichiarazione dovrebbe essere simile all'attributo seguente: xmlns:views="using:WinUINotes.Views".
Nel riquadro Esplora soluzioni fare doppio clic sulla voce MainWindow.xaml per aprirla nell'editor XAML.
Aggiungere questo nuovo mapping dello spazio dei nomi nella riga sotto il mapping per
local:xmlns:views="using:WinUINotes.Views"Lo
localspazio dei nomi XAML è stato usato per impostare laFrame.SourcePageTypeproprietà, quindi modificarloviewsin tale spazio. Il codice XAML dovrebbe ora essere simile al seguente:<Window x:Class="WinUINotes.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WinUINotes" xmlns:views="using:WinUINotes.Views" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="WinUI Notes"> <!-- ... Unchanged XAML not shown. --> <Frame x:Name="rootFrame" Grid.Row="1" SourcePageType="views:NotePage"/> <!-- ... Unchanged XAML not shown. --> </Window>Compilare ed eseguire l'app. L'app deve essere eseguita senza errori del compilatore e tutto dovrebbe funzionare come in precedenza.
Definire il modello
Attualmente, il modello (i dati) è incorporato nella visualizzazione note. Si creerà una nuova classe per rappresentare i dati di una pagina delle note:
Nel riquadro Esplora soluzioni fare clic con il pulsante destro del mouse sulla Models cartella e scegliere Aggiungi>classe....
Denominare la classe Note.cs e premere Aggiungi. Il Note.cs file verrà aperto nell'editor di codice.
Sostituire il codice nel Note.cs file con questo codice, che rende la classe
publice aggiunge proprietà e metodi per la gestione di una nota:using System; using System.Threading.Tasks; using Windows.Storage; namespace WinUINotes.Models { public class Note { private StorageFolder storageFolder = ApplicationData.Current.LocalFolder; public string Filename { get; set; } = string.Empty; public string Text { get; set; } = string.Empty; public DateTime Date { get; set; } = DateTime.Now; public Note() { Filename = "notes" + DateTime.Now.ToBinary().ToString() + ".txt"; } public async Task SaveAsync() { // Save the note to a file. StorageFile noteFile = (StorageFile)await storageFolder.TryGetItemAsync(Filename); if (noteFile is null) { noteFile = await storageFolder.CreateFileAsync(Filename, CreationCollisionOption.ReplaceExisting); } await FileIO.WriteTextAsync(noteFile, Text); } public async Task DeleteAsync() { // Delete the note from the file system. StorageFile noteFile = (StorageFile)await storageFolder.TryGetItemAsync(Filename); if (noteFile is not null) { await noteFile.DeleteAsync(); } } } }Salva il file.
Si noterà che questo codice è molto simile al codice in NotePage.xaml.cs, con alcune modifiche e aggiunte.
Filename e Text sono state modificate in public proprietà ed è stata aggiunta una nuova Date proprietà.
Il codice per salvare ed eliminare i file è stato inserito nei public metodi . È principalmente identico al codice usato nei gestori eventi del pulsante Click in NotePage, ma codice aggiuntivo per aggiornare la visualizzazione dopo che il file è stato eliminato. Non è necessario perché si userà il data binding per mantenere sincronizzato il modello e la visualizzazione.
Queste firme del metodo asincrono restituiscono Task anziché void. La Task classe rappresenta una singola operazione asincrona che non restituisce un valore. A meno che la firma del metodo non richieda void, come accade per i Click gestori eventi, async i metodi devono restituire un oggetto Task.
Inoltre, non mantenerai più un riferimento a StorageFile che contiene la nota. È sufficiente provare a ottenere il file quando è necessario per salvare o eliminare.
In NotePageè stato usato un segnaposto per il nome file: note.txt. Ora che l'app supporta più note, i nomi di file per le note salvate devono essere diversi e univoci. A tale scopo, impostare la Filename proprietà nel costruttore . È possibile utilizzare il metodo DateTime.ToBinary per creare una parte del nome file in base all'ora corrente e rendere univoci i nomi di file. Il nome del file generato è simile al seguente: notes-8584626598945870392.txt.
Aggiornare la pagina della nota
È ora possibile aggiornare la NotePage vista per usare il modello di dati ed eliminare il Note codice spostato nel Note modello.
Aprire il file Views\NotePage.xaml.cs se non è già aperto nell'editor.
Dopo l'ultima
usingistruzione nella parte superiore della pagina, aggiungere una nuovausingistruzione per concedere al codice l'accesso alle classi nella cartella e nelloModelsspazio dei nomi.using WinUINotes.Models;Eliminare queste righe dalla classe :
private StorageFolder storageFolder = ApplicationData.Current.LocalFolder; private StorageFile? noteFile = null; private string fileName = "note.txt";Aggiungere invece un
Noteoggetto denominatonoteModelal suo posto. Rappresenta i dati delle note cheNotePageforniscono una visualizzazione di .private Note? noteModel;Non è più necessario il
NotePage_Loadedgestore eventi. Non si leggerà testo direttamente dal file di testo nel controllo TextBox. Il testo della nota verrà invece letto inNoteoggetti. Si aggiungerà il codice per questo quando si aggiungerà inAllNotesPageun passaggio successivo. Eliminare queste righe.Loaded += NotePage_Loaded; ... private async void NotePage_Loaded(object sender, RoutedEventArgs e) { noteFile = (StorageFile)await storageFolder.TryGetItemAsync(fileName); if (noteFile is not null) { NoteEditor.Text = await FileIO.ReadTextAsync(noteFile); } }Sostituire il codice nel
SaveButton_Clickmetodo con questo:if (noteModel is not null) { await noteModel.SaveAsync(); }Sostituire il codice nel
DeleteButton_Clickmetodo con questo:if (noteModel is not null) { await noteModel.DeleteAsync(); }
È ora possibile aggiornare il file XAML per usare il Note modello. In precedenza, il testo viene letto direttamente dal file di testo nella TextBox.Text proprietà nel file code-behind. A questo momento, si usa il data binding per la Text proprietà .
Aprire il file Views\NotePage.xaml se non è già aperto nell'editor.
Aggiungere un
Textattributo alTextBoxcontrollo . Associarlo allaTextproprietà dinoteModel:Text="{x:Bind noteModel.Text, Mode=TwoWay}".Aggiornare per eseguire l'associazione
HeaderDatealla proprietà dinoteModel:Header="{x:Bind noteModel.Date.ToString()}".<TextBox x:Name="NoteEditor" <!-- ↓ Add this line. ↓ --> Text="{x:Bind noteModel.Text, Mode=TwoWay}" AcceptsReturn="True" TextWrapping="Wrap" PlaceholderText="Enter your note" <!-- ↓ Update this line. ↓ --> Header="{x:Bind noteModel.Date.ToString()}" ScrollViewer.VerticalScrollBarVisibility="Auto" Width="400" Grid.Column="1"/>
Il data binding è un modo per consentire all'interfaccia utente dell'app di visualizzare i dati e, facoltativamente, di rimanere sincronizzati con tali dati. L'impostazione Mode=TwoWay dell'associazione indica che le TextBox.Text proprietà e noteModel.Text vengono sincronizzate automaticamente. Quando il testo viene aggiornato in TextBox, le modifiche vengono riflesse nella Text proprietà di noteModele, se noteModel.Text viene modificato, gli aggiornamenti vengono riflessi in TextBox.
La Header proprietà usa l'impostazione predefinita Mode perché OneTime la noteModel.Date proprietà non cambia dopo la creazione del file. Questo codice illustra anche una potente funzionalità dell'associazione x:Bind di funzioni denominata , che consente di usare una funzione come ToString un passaggio nel percorso di associazione.
Importante
È importante scegliere il BindingMode corretto; in caso contrario, il data binding potrebbe non funzionare come previsto. Un errore comune con {x:Bind} è dimenticare di modificare l'impostazione predefinita BindingMode quando OneWay o TwoWay è necessario.
| Nome | Description |
|---|---|
OneTime |
Aggiorna la proprietà di destinazione solo quando viene creata l'associazione. Impostazione predefinita per {x:Bind}. |
OneWay |
Aggiorna la proprietà di destinazione al momento della creazione dell'associazione. Anche le modifiche apportate all'oggetto di origine possono essere propagate alla destinazione. Impostazione predefinita per {Binding}. |
TwoWay |
Aggiorna la destinazione o l'oggetto di origine quando vengono apportate modifiche. Quando viene creata l'associazione, la proprietà di destinazione viene aggiornata dall'origine. |
Il data binding supporta la separazione dei dati e dell'interfaccia utente e ciò comporta un modello concettuale più semplice, nonché una migliore leggibilità, testabilità e manutenibilità dell'app.
In WinUI sono disponibili due tipi di binding tra cui scegliere:
- L'estensione
{x:Bind}di markup viene elaborata in fase di compilazione. Alcuni dei vantaggi sono prestazioni migliorate e la convalida in fase di compilazione delle espressioni di binding. È consigliabile eseguire il binding nelle app WinUI. - L'estensione
{Binding}di markup viene elaborata in fase di esecuzione e usa l'ispezione degli oggetti runtime per utilizzo generico.
Per altre informazioni, vedere la documentazione:
Associazione dei dati e MVVM
Model-View-ViewModel (MVVM) è un modello di progettazione dell'architettura dell'interfaccia utente per disaccoppiare l'interfaccia utente e il codice non dell'interfaccia utente molto diffuso con gli sviluppatori .NET. Probabilmente vedrai e sentirai menzionato come hai altre informazioni sulla creazione di app WinUI. Separare le visualizzazioni e i modelli, come si è fatto qui, è il primo passo verso un'implementazione MVVM completa dell'app, ma è per quanto riguarda l'esercitazione.
Annotazioni
In questa esercitazione è stato usato il termine "modello" per fare riferimento al modello di dati, ma è importante notare che questo modello è più strettamente allineato con ViewModel in un'implementazione MVVM completa, incorporando anche aspetti del modello.
Per altre informazioni su MVVM, vedere queste risorse: