Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tej części samouczka przedstawiono pojęcia dotyczące widoków i modeli danych.
W poprzednich krokach samouczka dodano nową stronę do projektu, która umożliwia użytkownikowi zapisywanie, edytowanie lub usuwanie pojedynczej notatki. Jednak ponieważ aplikacja musi obsługiwać więcej niż jedną notatkę, musisz dodać kolejną stronę, która wyświetla wszystkie notatki (wywołaj ją AllNotesPage). Na tej stronie użytkownik wybierze notatkę, która ma zostać otwarta na stronie edytora, aby mogła wyświetlać, edytować lub usuwać. Powinno również umożliwić użytkownikowi utworzenie nowej notatki.
Aby to osiągnąć, AllNotesPage musi mieć kolekcję notatek i sposób wyświetlania kolekcji. W tym miejscu aplikacja ma problemy, ponieważ dane notatek są ściśle powiązane z plikiem NotePage . W AllNotesPageprogramie po prostu chcesz wyświetlić wszystkie notatki na liście lub w innym widoku kolekcji z informacjami o każdej notatce, na przykład datą utworzenia i podglądem tekstu. Ze względu na to, że tekst notatek jest ściśle powiązany z kontrolką TextBox , nie ma możliwości wykonania tej czynności.
Przed dodaniem strony w celu wyświetlenia wszystkich notatek wprowadźmy pewne zmiany, aby oddzielić dane notatki od prezentacji notatki.
Widoki i modele
Zazwyczaj aplikacja WinUI ma co najmniej warstwę widoku i warstwę danych.
Warstwa widoku definiuje interfejs użytkownika przy użyciu znaczników XAML. Znacznik zawiera wyrażenia powiązania danych (takie jak x:Bind), które definiują połączenie między określonymi składnikami interfejsu użytkownika i elementami członkowskimi danych. Pliki związane z kodem są czasami używane jako część warstwy widoku, aby zawierać dodatkowy kod potrzebny do dostosowania interfejsu użytkownika lub manipulowania nim albo wyodrębniania danych z argumentów procedury obsługi zdarzeń przed wywołaniem metody wykonującej pracę nad danymi.
Warstwa danych lub model definiuje typy reprezentujące dane aplikacji i powiązaną logikę. Ta warstwa jest niezależna od warstwy widoku i można utworzyć wiele różnych widoków, które współdziałają z danymi.
Obecnie obiekt NotePage reprezentuje widok danych (tekst notatki). Jednak po odczytaniu danych do aplikacji z pliku systemowego istnieje tylko we Text właściwości TextBox w pliku w NotePagepliku . Nie jest ona reprezentowana w aplikacji w sposób umożliwiający prezentowanie danych na różne sposoby lub w różnych miejscach; oznacza to, że aplikacja nie ma warstwy danych. Teraz przekonstruujesz projekt w celu utworzenia warstwy danych.
Oddzielanie widoku i modelu
Wskazówka
Możesz pobrać lub wyświetlić kod tego samouczka z repozytorium GitHub. Aby zobaczyć kod, który znajduje się w tym kroku, zobacz to zatwierdzenie: strona notatek — view-model.
Refaktoryzuj istniejący kod, aby oddzielić model od widoku. W następnych kilku krokach zostanie zorganizowany kod, tak aby widoki i modele zostały zdefiniowane oddzielnie od siebie.
W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy WinUINotes projekt i wybierz polecenie Dodaj>nowy folder. Nadaj folderowi Modelsnazwę .
Ponownie kliknij prawym przyciskiem myszy WinUINotes projekt i wybierz polecenie Dodaj>nowy folder. Nadaj folderowi Viewsnazwę .
NotePage.xaml Znajdź element i przeciągnij go do Views folderu. Plik powinien zostać przeniesiony NotePage.xaml.cs z nim.
Uwaga / Notatka
Podczas przenoszenia pliku program Visual Studio zwykle wyświetla ostrzeżenie o tym, jak operacja przenoszenia może zająć dużo czasu. Nie powinno to być problemem w tym miejscu, naciśnij przycisk OK , jeśli widzisz to ostrzeżenie.
Program Visual Studio może również zapytać, czy chcesz dostosować przestrzeń nazw przeniesionego pliku. Wybierz pozycję Nie. Przestrzeń nazw zmienisz w następnych krokach.
Aktualizowanie przestrzeni nazw widoku
Teraz, gdy widok został przeniesiony do Views folderu, musisz zaktualizować przestrzenie nazw, aby były zgodne. Przestrzeń nazw dla plików XAML i code-behind stron jest ustawiona na WinUINoteswartość . Należy to zaktualizować do WinUINotes.Views.
W okienku Eksplorator rozwiązań rozwiń węzeł NotePage.xaml , aby wyświetlić plik za kodem.
Kliknij dwukrotnie element, NotePage.xaml.cs aby otworzyć edytor kodu, jeśli nie jest jeszcze otwarty. Zmień przestrzeń nazw na
WinUINotes.Views:namespace WinUINotes.ViewsKliknij dwukrotnie element, NotePage.xaml aby otworzyć edytor XAML, jeśli nie jest jeszcze otwarty. Stara przestrzeń nazw jest przywoływana za pomocą atrybutu
x:Class, który definiuje typ klasy jest kodem za pomocą języka XAML. Ten wpis nie jest tylko przestrzenią nazw, ale przestrzenią nazw o typie. Zmień wartość nax:ClassWinUINotes.Views.NotePage:x:Class="WinUINotes.Views.NotePage"
Naprawianie odwołania do przestrzeni nazw w systemie MainWindow
W poprzednim kroku utworzono stronę notatek i zaktualizowano MainWindow.xaml ją, aby przejść do niej. Pamiętaj, że został on zamapowany na local: mapowanie przestrzeni nazw. Typowym rozwiązaniem jest mapowania nazwy local na przestrzeń nazw głównego projektu, a szablon projektu programu Visual Studio już to robi (xmlns:local="using:WinUINotes"). Teraz, gdy strona została przeniesiona do nowej przestrzeni nazw, mapowanie typów w języku XAML jest teraz nieprawidłowe.
Na szczęście możesz w razie potrzeby dodać własne mapowania przestrzeni nazw. Należy to zrobić, aby uzyskać dostęp do elementów w różnych folderach tworzonych w projekcie. Ta nowa przestrzeń nazw XAML będzie mapować na przestrzeń nazw , WinUINotes.Viewswięc nadaj jej viewsnazwę . Deklaracja powinna wyglądać podobnie do następującego atrybutu: xmlns:views="using:WinUINotes.Views".
W okienku Eksplorator rozwiązań kliknij dwukrotnie wpis MainWindow.xaml , aby otworzyć go w edytorze XAML.
Dodaj to nowe mapowanie przestrzeni nazw w wierszu poniżej mapowania elementu
local:xmlns:views="using:WinUINotes.Views"localPrzestrzeń nazw XAML została użyta do ustawieniaFrame.SourcePageTypewłaściwości, więc zmień ją naviews. Kod XAML powinien teraz wyglądać następująco:<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>Skompiluj i uruchom aplikację. Aplikacja powinna działać bez żadnych błędów kompilatora, a wszystko powinno nadal działać tak jak wcześniej.
Definiowanie modelu
Obecnie model (dane) jest osadzony w widoku notatek. Utworzysz nową klasę reprezentującą dane strony notatek:
W okienku Eksplorator rozwiązań kliknij prawym przyciskiem myszy Models folder i wybierz polecenie Dodaj>klasę....
Nadaj klasie Note.cs nazwę i naciśnij przycisk Dodaj. Plik Note.cs zostanie otwarty w edytorze kodu.
Zastąp kod w Note.cs pliku tym kodem, który sprawia, że klasa
publici dodaje właściwości i metody do obsługi notatki: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(); } } } }Zapisz plik.
Zauważysz, że ten kod jest bardzo podobny do kodu w NotePage.xaml.cspliku z kilkoma zmianami i dodatkami.
Filename i Text zostały zmienione na public właściwości, a nowa Date właściwość została dodana.
Kod do zapisania i usunięcia plików został umieszczony w public metodach. Jest on w większości identyczny z kodem używanym w programach obsługi zdarzeń przycisku Click w programie NotePage, ale dodatkowy kod służący do aktualizowania widoku po usunięciu pliku został usunięty. Nie jest to potrzebne w tym miejscu, ponieważ będziesz używać powiązania danych, aby zachować synchronizację modelu i widoku.
Te sygnatury metody asynchronicznej zwracają zadanie zamiast void. Klasa Task reprezentuje pojedynczą operację asynchroniczną, która nie zwraca wartości. Jeśli podpis metody nie wymaga voidmetody , podobnie jak w przypadku Click procedur obsługi zdarzeń, async metody powinny zwrócić wartość Task.
Nie będziesz już przechowywać odwołania do StorageFile notatek. Po prostu spróbuj pobrać plik, gdy będzie potrzebny do zapisania lub usunięcia.
W NotePagepliku użyto symbolu zastępczego dla nazwy pliku: note.txt. Teraz, gdy aplikacja obsługuje więcej niż jedną notatkę, nazwy plików dla zapisanych notatek muszą być różne i unikatowe. W tym celu ustaw Filename właściwość w konstruktorze. Możesz użyć metody DateTime.ToBinary , aby utworzyć część nazwy pliku na podstawie bieżącej godziny i ustawić unikatowe nazwy plików. Wygenerowana nazwa pliku wygląda następująco: notes-8584626598945870392.txt.
Aktualizowanie strony notatki
Teraz możesz zaktualizować widok, NotePage aby użyć Note modelu danych i usunąć kod przeniesiony do Note modelu.
Otwórz plik Views\NotePage.xaml.cs , jeśli nie jest jeszcze otwarty w edytorze.
Po ostatniej
usinginstrukcji w górnej części strony dodaj nowąusinginstrukcję, aby nadać kodowi dostęp do klas wModelsfolderze i przestrzeni nazw.using WinUINotes.Models;Usuń następujące wiersze z klasy:
private StorageFolder storageFolder = ApplicationData.Current.LocalFolder; private StorageFile? noteFile = null; private string fileName = "note.txt";Zamiast tego dodaj
Noteobiekt o nazwienoteModelw swoim miejscu. Reprezentuje to dane notatek, któreNotePageudostępniają widok.private Note? noteModel;Program obsługi zdarzeń nie jest już potrzebny
NotePage_Loaded. Nie będziesz odczytywać tekstu bezpośrednio z pliku tekstowego do kontrolki TextBox. Zamiast tego tekst notatki będzie odczytywany doNoteobiektów. Po dodaniuAllNotesPagekodu w późniejszym kroku dodasz kod. Usuń te wiersze.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); } }Zastąp kod w metodzie
SaveButton_Clicknastępującym kodem:if (noteModel is not null) { await noteModel.SaveAsync(); }Zastąp kod w metodzie
DeleteButton_Clicknastępującym kodem:if (noteModel is not null) { await noteModel.DeleteAsync(); }
Teraz możesz zaktualizować plik XAML, aby użyć Note modelu. Wcześniej odczytano tekst bezpośrednio z pliku tekstowego do TextBox.Text właściwości w pliku za pomocą kodu. Teraz używasz powiązania danych dla Text właściwości .
Otwórz plik Views\NotePage.xaml , jeśli nie jest jeszcze otwarty w edytorze.
TextDodaj atrybut do kontrolkiTextBox. Powiąż ją z właściwościąText:noteModelText="{x:Bind noteModel.Text, Mode=TwoWay}".Zaktualizuj element
Header, aby powiązać z właściwościąDatenoteModel: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"/>
Powiązanie danych to sposób, aby interfejs użytkownika aplikacji wyświetlał dane i opcjonalnie pozostaje zsynchronizowany z danymi. Ustawienie Mode=TwoWay w powiązaniu oznacza, że TextBox.Text właściwości i noteModel.Text są automatycznie synchronizowane. Gdy tekst zostanie zaktualizowany w TextBoxobiekcie , zmiany zostaną odzwierciedlone we Text właściwości noteModel, a jeśli noteModel.Text zostaną zmienione, aktualizacje zostaną odzwierciedlone w obiekcie TextBox.
Właściwość Header używa wartości domyślnej Mode , OneTime ponieważ noteModel.Date właściwość nie zmienia się po utworzeniu pliku. Ten kod demonstruje również zaawansowaną funkcję x:Bind o nazwie powiązanie funkcji, która umożliwia użycie funkcji podobnej ToString do kroku w ścieżce powiązania.
Ważne
Ważne jest, aby wybrać prawidłowy tryb BindingMode; w przeciwnym razie powiązanie danych może nie działać zgodnie z oczekiwaniami. (Typowym błędem jest {x:Bind} zapominanie o zmianie wartości domyślnejBindingMode, gdy OneWayTwoWay jest to konieczne).
| Name | Description |
|---|---|
OneTime |
Aktualizuje właściwość docelową tylko po utworzeniu powiązania. Wartość domyślna dla .{x:Bind} |
OneWay |
Aktualizuje właściwość docelową podczas tworzenia powiązania. Zmiany obiektu źródłowego mogą również być propagowane do obiektu docelowego. Wartość domyślna dla .{Binding} |
TwoWay |
Aktualizuje obiekt docelowy lub obiekt źródłowy po zmianie. Po utworzeniu powiązania właściwość docelowa zostanie zaktualizowana ze źródła. |
Powiązanie danych obsługuje rozdzielenie danych i interfejsu użytkownika oraz zapewnia prostszy model koncepcyjny, a także lepszą czytelność, możliwość testowania i konserwację aplikacji.
W systemie WinUI istnieją dwa rodzaje powiązań, spośród których można wybrać:
-
{x:Bind}Rozszerzenie znaczników jest przetwarzane w czasie kompilacji. Niektóre z jego zalet są ulepszone wydajność i sprawdzanie poprawności w czasie kompilacji wyrażeń powiązań. Zalecane jest powiązanie w aplikacjach WinUI. - Rozszerzenie
{Binding}znaczników jest przetwarzane w czasie wykonywania i używa inspekcji obiektów środowiska uruchomieniowego ogólnego przeznaczenia.
Dowiedz się więcej w dokumentacji:
Powiązanie danych i MVVM
Model-View-ViewModel (MVVM) to wzorzec projektowania architektury interfejsu użytkownika interfejsu użytkownika i kodu innego niż interfejs użytkownika, który jest popularny dla deweloperów platformy .NET. Prawdopodobnie zobaczysz ją i usłyszysz, gdy dowiesz się więcej o tworzeniu aplikacji WinUI. Oddzielenie widoków i modeli, jak już to zrobiono, jest pierwszym krokiem w kierunku pełnej implementacji MVVM aplikacji, ale tak daleko, jak to zrobisz w tym samouczku.
Uwaga / Notatka
Użyliśmy terminu "model" do odwoływania się do modelu danych w tym samouczku, ale należy pamiętać, że ten model jest ściślej dopasowany do modelu ViewModel w pełnej implementacji MVVM, a także uwzględnia aspekty modelu.
Aby dowiedzieć się więcej o maszynie MVVM, zobacz następujące zasoby:
Windows developer