Nézet és modell hozzáadása a jegyzethez

Az oktatóanyag ezen része bemutatja az adatnézetek és modellek fogalmait.

Az oktatóanyag előző lépéseiben hozzáadott egy új lapot a project, amely lehetővé teszi a felhasználó számára egyetlen jegyzet mentését, szerkesztését vagy törlését. Mivel azonban az alkalmazásnak több megjegyzést kell kezelnie, hozzá kell adnia egy másik lapot, amely megjeleníti az összes jegyzetet (hívja meg AllNotesPage). Ezen a lapon a felhasználó kiválaszthatja a szerkesztőlapon megnyitni kívánt jegyzetet, hogy megtekinthesse, szerkessze vagy törölje azt. Azt is lehetővé kell tenni, hogy a felhasználó hozzon létre egy új megjegyzést.

Ehhez AllNotesPage rendelkeznie kell egy jegyzetgyűjteménysel, és meg kell jelenítenie a gyűjteményt. Az alkalmazás itt ütközik bajba, mert a jegyzetadatok szorosan kötődnek a NotePage fájlhoz. Ebben AllNotesPagea fájlban csak az összes jegyzetet szeretné megjeleníteni egy listában vagy más gyűjteménynézetben, az egyes jegyzetekkel kapcsolatos információkkal, például a létrehozás dátumával és a szöveg előnézetével. Mivel a jegyzetszöveg szorosan kötődik a TextBox vezérlőelemhez, ezt nem lehet megvalósítani.

Mielőtt hozzáad egy lapot az összes jegyzet megjelenítéséhez, hajtsunk végre néhány módosítást, hogy elkülönítsük a jegyzetadatokat a jegyzetbemutatótól.

Nézetek és modellek

Egy WinUI 3-alkalmazás általában legalább egy nézetréteggel és egy adatréteggel rendelkezik.

A nézetréteg a felhasználói felületet XAML-jelölésnyelv használatával határozza meg. A korrektúra adatkötési kifejezéseket (például x:Bind) tartalmaz, amelyek meghatározzák az adott felhasználói felület összetevői és az adattagok közötti kapcsolatot. A kód mögötti fájlokat néha a nézetréteg részeként használják a felhasználói felület testreszabásához vagy módosításához, illetve az eseménykezelő argumentumok adatainak kinyeréséhez, mielőtt meghívna egy metódust, amely elvégzi az adatokon végzett munkát.

Az adatréteg vagy modell határozza meg az alkalmazás adatait és a kapcsolódó logikát képviselő típusokat. Ez a réteg független a nézetrétegétől, és több különböző nézetet is létrehozhat, amelyek interakcióba lépnek az adatokkal.

Jelenleg az NotePage adatok nézetét (a jegyzetszöveget) jelöli. Miután azonban beolvassa az adatokat az alkalmazásba a rendszerfájlból, az csak az Text in TextBoxtulajdonságában NotePage létezik. Nem úgy jelenik meg az alkalmazásban, hogy az adatokat különböző módokon vagy különböző helyeken jelenítse meg; vagyis az alkalmazás nem rendelkezik adatréteggel. Most át fogja alakítani a projektet az adatréteg létrehozása érdekében.

A nézet és a modell elkülönítése

Jótanács

Az oktatóanyag kódját a GitHub adattárból töltheti le vagy tekintheti meg. A jelen lépésben szereplő kód megtekintéséhez tekintse meg a következő véglegesítést: note page - view-model.

A meglévő kód újrabontásával válassza el a modellt a nézettől. A következő néhány lépés a kód rendszerezését fogja elvégezni, hogy a nézetek és modellek egymástól külön legyenek definiálva.

  1. A Megoldáskezelő kattintson a jobb gombbal a WinUINotes project elemre, és válassza a Add>Új mappa lehetőséget. Nevezze el a mappát Models.

  2. Kattintson ismét a jobb gombbal a WinUINotes project elemre, és válassza a Add>Új mappa lehetőséget. Nevezze el a mappát Views.

  3. Keresse meg az NotePage.xaml elemet, és húzza a Views mappába. A NotePage.xaml.cs fájlnak vele együtt kell mozognia.

    Megjegyzés:

    Amikor áthelyez egy fájlt, Visual Studio általában figyelmeztetést kap arról, hogy az áthelyezési művelet mennyi ideig tarthat. Ez itt nem jelenthet problémát, ha ezt a figyelmeztetést látja, nyomja le OK.

    Visual Studio azt is megkérdezheti, hogy szeretné-e módosítani az áthelyezett fájl névterét. Válassza a Nem lehetőséget. A névteret a következő lépésekben módosíthatja.

A nézet névterének frissítése

Most, hogy a nézet át lett helyezve a Views mappába, frissítenie kell a névtereket az egyezéshez. A lapok XAML-fájljainak és kód mögötti fájljainak névtere WinUINotes. Ezt frissíteni kell a WinUINotes.Views.

  1. A Megoldáskezelő panelen bontsa ki a NotePage.xaml elemet a kód mögötti fájl megjelenítéséhez.

  2. Kattintson duplán az elemre a NotePage.xaml.cs kódszerkesztő megnyitásához, ha még nincs megnyitva. Módosítsa a névteret WinUINotes.Views:

    namespace WinUINotes.Views
    
  3. Kattintson duplán az elemre az NotePage.xaml XAML-szerkesztő megnyitásához, ha még nincs megnyitva. A régi névtérre a x:Class attribútum hivatkozik, amely meghatározza, hogy az XAML kód mögött melyik osztálytípus szerepel. Ez a bejegyzés nem csak a névtér, hanem a típussal rendelkező névtér is. Módosítsa a x:Class értékét WinUINotes.Views.NotePage:

    x:Class="WinUINotes.Views.NotePage"
    

A névtérhivatkozás javítása a MainWindow-ban

Az előző lépésben létrehozta a jegyzetoldalt, és frissítette MainWindow.xaml a lapra való navigáláshoz. Ne feledje, hogy a local: névtérleképezéssel van megfeleltetve. A local nevét gyakran a projekt gyökérnévterére képezik le, és a Visual Studio projekt sablon ezt már elvégzi ön helyett (xmlns:local="using:WinUINotes"). Most, hogy a lap új névtérbe került, az XAML típusleképezése érvénytelen.

Szerencsére igény szerint hozzáadhat saját névtér-leképezéseket. Ezt kell tenned, hogy hozzáférj az elemekhez a projektedben létrehozott különböző mappákban. Ez az új XAML-névtér a WinUINotes.Views névtérhez lesz társítva, ezért nevezze el views. A deklarációnak a következő attribútumhoz hasonlóan kell kinéznie: xmlns:views="using:WinUINotes.Views".

  1. A Megoldáskezelő panelen kattintson duplán a MainWindow.xaml bejegyzésre az XAML-szerkesztő megnyitásához.

  2. Adja hozzá ezt az új névtérleképezést ahhoz a sorhoz, amelyik alatta van local leképezésnek:

    xmlns:views="using:WinUINotes.Views"
    
  3. A local XAML névteret használták a Frame.SourcePageType tulajdonság beállításához, ezért ott módosítsa a views-re. Az XAML-nek így kell kinéznie:

    <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>
    
  4. Hozza létre és futtassa az alkalmazást. Az alkalmazásnak fordítói hibák nélkül kell futnia, és mindennek a korábbiakhoz hasonlóan kell működnie.

A modell definiálása

A modell (az adatok) jelenleg a jegyzetnézetben lesznek beágyazva. Létre fog hozni egy új osztályt a jegyzetoldal adatainak megjelenítéséhez:

  1. A Megoldáskezelő ablaktáblán kattintson a jobb gombbal a Models mappára, és válassza a Add>Class... .

  2. Nevezze el az osztályt Note.cs , és nyomja le a Hozzáadás billentyűt. A Note.cs fájl megnyílik a kódszerkesztőben.

  3. Cserélje le a fájlban lévő kódot erre a Note.cs kódra, amely az osztályt public hozza létre, és tulajdonságokat és metódusokat ad hozzá a megjegyzés kezeléséhez:

    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();
                }
            }
        }
    }
    
  4. Mentse a fájlt.

Megfigyelheti, hogy ez a kód nagyon hasonlít a benne lévő NotePage.xaml.cskódhoz, néhány módosítással és kiegészítéssel.

Filename és Text tulajdonságokra public módosult, és új Date tulajdonság lett hozzáadva.

A fájlok mentésére és törlésére vonatkozó kód metódusokban public lett elhelyezve. Ez többnyire megegyezik a ClickNotePage gombesemény-kezelőkben használt kóddal, de eltávolítottuk a fájl törlése utáni nézetfrissítéshez szükséges további kódot. Erre nincs szükség, mert adatkötést fog használni a modell szinkronizálásának és megtekintésének megőrzéséhez.

Ezek az aszinkron metódus-aláírások Task-t adnak vissza a void helyett. Az Task osztály egyetlen aszinkron műveletet jelöl, amely nem ad vissza értéket. Kivéve, ha a metódus aláírása megköveteli a(z) `void`-t, az `Click` eseménykezelők esetében, a `async` metódusoknak egy `Task`-t kell visszaadniuk.

Többé nem fogja megtartani a StorageFile hivatkozást, amely a jegyzetet tartalmazza. Csak akkor próbálja lekérni a fájlt, ha szüksége van rá a mentéshez vagy a törléshez.

Ebben a dokumentumban a fájlnévhez egy helyőrzőt használtál: NotePage. Most, hogy az alkalmazás több megjegyzést is támogat, a mentett jegyzetek fájlneveinek eltérőnek és egyedinek kell lenniük. A konstruktorban állítsa be a Filename tulajdonságot e célból. A DateTime.ToBinary metódussal létrehozhatja a fájlnév egy részét az aktuális idő alapján, és egyedivé teheti a fájlneveket. A létrehozott fájlnév így néz ki: notes-8584626598945870392.txt.

A jegyzetoldal frissítése

Most frissítheti a nézetet az NotePageNote adatmodell használatára, és törölheti a Note modellbe áthelyezett kódot.

  1. Nyissa meg a Nézetek\NotePage.xaml.cs fájlt, ha még nincs megnyitva a szerkesztőben.

  2. A lap tetején található utolsó using utasítás után adjon hozzá egy új using utasítást, amely hozzáférést biztosít a kódnak a Models mappa és névtér osztályaihoz.

    using WinUINotes.Models;
    
  3. Törölje ezeket a sorokat az osztályból:

    private StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
    private StorageFile? noteFile = null;
    private string fileName = "note.txt";
    
  4. Ehelyett adjon hozzá egy Note objektumot, amelyet noteModel-nek neveztek el helyettük. Ez azokat a jegyzetadatokat jelöli, amelyekre a NotePage nézetet biztosít.

    private Note? noteModel;
    
  5. Már nincs szüksége az NotePage_Loaded eseménykezelőre. Nem fogja közvetlenül a szövegfájlból a Szövegdobozba beolvasni a szöveget. Ehelyett a jegyzet szövege objektumokba Note lesz beolvasva. Ön hozzáadja a kódot, amikor hozzáadja a AllNotesPage egy későbbi lépés során. Törölje ezeket a sorokat.

    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);
        }
    }
    
  6. Cserélje le a metódusban szereplő kódot a SaveButton_Click következőre:

    if (noteModel is not null)
    {
        await noteModel.SaveAsync();
    }
    
  7. Cserélje le a metódusban szereplő kódot a DeleteButton_Click következőre:

    if (noteModel is not null)
    {
        await noteModel.DeleteAsync();
    }
    

Mostantól frissítheti az XAML-fájlt a Note modell használatára. Korábban közvetlenül a szövegfájlból olvasta be a szöveget a TextBox.Text tulajdonságba, amely a háttérkódfájlban található. Most adatkötést használ a Text tulajdonsághoz.

  1. Nyissa meg a Nézetek\NotePage.xaml fájlt, ha még nincs megnyitva a szerkesztőben.

  2. Adjon hozzá egy Text attribútumot a TextBox vezérlőhöz. Kösse a(z) Text tulajdonságot a(z) noteModel-be: Text="{x:Bind noteModel.Text, Mode=TwoWay}".

  3. Frissítse a Header-t, hogy kösse hozzá a Date tulajdonságát a noteModel: 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"/>
    

Az adatkötéssel az alkalmazás felhasználói felülete megjelenítheti az adatokat, és igény szerint szinkronban maradhat az adatokkal. A Mode=TwoWay kötés beállítása azt jelenti, hogy a rendszer automatikusan szinkronizálja a TextBox.TextnoteModel.Text tulajdonságokat. Amikor a szöveg frissül a TextBoxfájlban, a módosítások megjelennek a Text tulajdonságban noteModel, és ha noteModel.Text módosul, a frissítések megjelennek a TextBox.

A Header tulajdonság az alapértelmezett ModeOneTime értéket használja, mert a noteModel.Date tulajdonság nem változik a fájl létrehozása után. Ez a kód bemutatja a x:Bind egy erőteljes funkcióját, az úgynevezett függvény-kötéseket, amelyek lehetővé teszik, hogy egy olyan függvényt, mint ToString, a kötési útvonal egyik lépéseként használjon.

Fontos

Fontos a megfelelő BindingMode kiválasztása; ellenkező esetben előfordulhat, hogy az adatkötés nem a várt módon működik. (Gyakori hiba {x:Bind} esetén, ha elfelejtjük módosítani az alapértelmezett BindingMode-t, amikor OneWay vagy TwoWay szükséges.)

Név Description
OneTime A céltulajdonság csak a kötés létrehozásakor frissül. Alapértelmezett beállítás a következőhöz {x:Bind}: .
OneWay Frissíti a céltulajdonságot a kötés létrehozásakor. A forrásobjektum módosításai a célra is terjedhetnek. Alapértelmezett beállítás a következőhöz {Binding}: .
TwoWay Bármelyik módosításkor frissíti a célt vagy a forrásobjektumot. A kötés létrehozásakor a céltulajdonság frissül a forrásból.

Az adatkötés támogatja az adatok és a felhasználói felület elkülönítését, és ez egyszerűbb elméleti modellt, valamint az alkalmazás jobb olvashatóságát, tesztelhetőségét és karbantarthatóságát eredményezi.

A WinUI-ban kétféle kötés közül választhat:

  • A {x:Bind} korrektúrabővítmény fordítási időben lesz feldolgozva. Ennek néhány előnye a kötési kifejezések teljesítményének javítása és a fordítási idő ellenőrzése. A WinUI-alkalmazások kötéséhez ajánlott.
  • A {Binding} korrektúrabővítmény futásidőben lesz feldolgozva, és általános célú futtatókörnyezeti objektumvizsgálatot használ.

További információ a dokumentumokban:

Adatkötés és MVVM

Model-View-ViewModel (MVVM) egy felhasználói felületi architekturális tervezési minta a felhasználói felület és a nem felhasználói felületi kód leválasztása érdekében, amely népszerű .NET fejlesztők számára. A WinUI-alkalmazások létrehozásának tanulása során valószínűleg látni és hallani fog róla. A nézetek és modellek elkülönítése, ahogyan itt tette, az első lépés az alkalmazás teljes MVVM-implementációja felé, de ennél tovább az oktatóanyag során nem fogunk jutni.

Megjegyzés:

Ebben az oktatóanyagban a "modell" kifejezéssel hivatkoztunk az adatmodellre, de fontos megjegyezni, hogy ez a modell jobban igazodik a ViewModelhez egy teljes MVVM-implementációban, miközben a modell szempontjait is magában foglalja.

Az MVVM-ről az alábbi forrásokból tudhat meg többet: