Bagikan melalui


Menambahkan tampilan dan model untuk catatan

Bagian tutorial ini memperkenalkan konsep tampilan dan model data.

Dalam langkah tutorial sebelumnya, Anda menambahkan halaman baru ke proyek yang memungkinkan pengguna menyimpan, mengedit, atau menghapus satu catatan. Namun, karena aplikasi perlu menangani lebih dari satu catatan, Anda perlu menambahkan halaman lain yang menampilkan semua catatan (sebut saja AllNotesPage). Halaman ini memungkinkan pengguna memilih catatan untuk dibuka di halaman editor sehingga mereka dapat melihat, mengedit, atau menghapusnya. Ini juga harus memungkinkan pengguna membuat catatan baru.

Untuk mencapai hal ini, AllNotesPage perlu memiliki koleksi catatan, dan cara untuk menampilkan koleksi. Di sinilah aplikasi mengalami masalah karena data catatan terikat erat ke NotePage file. Di AllNotesPage, Anda hanya ingin menampilkan semua catatan dalam daftar atau tampilan koleksi lainnya, dengan informasi tentang setiap catatan, seperti tanggal dibuat dan pratinjau teks. Dengan teks catatan yang terikat erat ke TextBox kontrol, tidak ada cara untuk melakukan ini.

Sebelum Anda menambahkan halaman untuk memperlihatkan semua catatan, mari kita buat beberapa perubahan untuk memisahkan data catatan dari presentasi catatan.

Tampilan dan model

Biasanya, aplikasi WinUI memiliki setidaknya lapisan tampilan dan lapisan data.

Lapisan tampilan mendefinisikan UI menggunakan markup XAML. Markup mencakup ekspresi pengikatan data (seperti x:Bind) yang menentukan koneksi antara komponen UI tertentu dan anggota data. File code-behind terkadang digunakan sebagai bagian dari lapisan tampilan untuk berisi kode tambahan yang diperlukan untuk menyesuaikan atau memanipulasi UI, atau untuk mengekstrak data dari argumen penanganan aktivitas sebelum memanggil metode yang melakukan pekerjaan pada data.

Lapisan data, atau model, menentukan jenis yang mewakili data aplikasi Anda dan logika terkait. Lapisan ini tidak bergantung pada lapisan tampilan, dan Anda dapat membuat beberapa tampilan berbeda yang berinteraksi dengan data.

Saat ini, NotePage mewakili tampilan data (teks catatan). Namun, setelah data dibaca ke dalam aplikasi dari file sistem, data hanya ada di Text properti TextBox di NotePage. Ini tidak diwakili dalam aplikasi dengan cara yang memungkinkan Anda menyajikan data dengan cara yang berbeda atau di tempat yang berbeda; artinya, aplikasi tidak memiliki lapisan data. Anda akan merestrukturisasi proyek sekarang untuk membuat lapisan data.

Pisahkan tampilan dan model

Tip

Anda dapat mengunduh atau melihat kode untuk tutorial ini dari repositori GitHub. Untuk melihat kode apa adanya dalam langkah ini, lihat halaman penerapan ini: catatan - view-model.

Refaktor kode yang ada untuk memisahkan model dari tampilan. Beberapa langkah berikutnya akan mengatur kode sehingga tampilan dan model didefinisikan secara terpisah satu sama lain.

  1. Di Penjelajah Solusi, klik kanan pada WinUINotes proyek dan pilih Tambahkan>Folder Baru. Beri nama folder Models.

  2. Klik kanan proyek WinUINotes lagi dan pilih Tambahkan>Folder Baru. Beri nama folder Views.

  3. NotePage.xaml Temukan item dan seret ke Views folder. File harus dipindahkan dengan file tersebut NotePage.xaml.cs .

    Nota

    Saat Anda memindahkan file, Visual Studio biasanya meminta Anda dengan peringatan tentang bagaimana operasi pemindahan mungkin memakan waktu lama. Ini seharusnya tidak menjadi masalah di sini, tekan OK jika Anda melihat peringatan ini.

    Visual Studio mungkin juga menanyakan apakah Anda ingin menyesuaikan namespace file yang dipindahkan. Pilih Tidak. Anda akan mengubah namespace layanan di langkah berikutnya.

Memperbarui namespace tampilan

Sekarang setelah tampilan dipindahkan ke Views folder, Anda harus memperbarui namespace agar cocok. Namespace layanan untuk file XAML dan code-behind halaman diatur ke WinUINotes. Ini perlu diperbarui ke WinUINotes.Views.

  1. Di panel Penjelajah Solusi , perluas NotePage.xaml untuk mengungkapkan file code-behind.

  2. Klik dua kali pada NotePage.xaml.cs item untuk membuka editor kode jika belum dibuka. Ubah namespace menjadi WinUINotes.Views:

    namespace WinUINotes.Views
    
  3. Klik dua kali pada NotePage.xaml item untuk membuka editor XAML jika belum dibuka. Namespace lama dirujuk melalui x:Class atribut , yang menentukan jenis kelas mana yang di belakang kode untuk XAML. Entri ini bukan hanya namespace, tetapi namespace layanan dengan jenis . Ubah nilai menjadi x:ClassWinUINotes.Views.NotePage:

    x:Class="WinUINotes.Views.NotePage"
    

Memperbaiki referensi namespace di MainWindow

Pada langkah sebelumnya, Anda membuat halaman catatan dan memperbarui MainWindow.xaml untuk menavigasi ke halaman tersebut. Ingatlah bahwa itu dipetakan dengan local: pemetaan namespace layanan. Praktik umum untuk memetakan nama local ke namespace layanan akar proyek Anda, dan templat proyek Visual Studio sudah melakukan ini untuk Anda (xmlns:local="using:WinUINotes"). Sekarang setelah halaman dipindahkan ke namespace baru, pemetaan jenis di XAML sekarang tidak valid.

Untungnya, Anda dapat menambahkan pemetaan namespace Anda sendiri sesuai kebutuhan. Anda perlu melakukan ini untuk mengakses item di folder berbeda yang Anda buat di proyek Anda. Namespace XAML baru ini akan memetakan ke namespace WinUINotes.Views, jadi beri nama views. Deklarasi akan terlihat seperti atribut berikut: xmlns:views="using:WinUINotes.Views".

  1. Di panel Penjelajah Solusi , klik dua kali pada entri MainWindow.xaml untuk membukanya di editor XAML.

  2. Tambahkan pemetaan namespace baru ini pada baris di bawah pemetaan untuk local:

    xmlns:views="using:WinUINotes.Views"
    
  3. Namespace local XAML digunakan untuk mengatur Frame.SourcePageType properti, jadi ubah ke views sana. XAML Anda sekarang akan terlihat seperti ini:

    <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. Buat dan jalankan aplikasi. Aplikasi harus berjalan tanpa kesalahan pengkompilasi, dan semuanya masih harus berfungsi seperti sebelumnya.

Tentukan model

Saat ini, model (data) disematkan dalam tampilan catatan. Anda akan membuat kelas baru untuk mewakili data halaman catatan:

  1. Di panel Penjelajah Solusi, klik kanan folder Models dan pilih >.

  2. Beri nama kelas Note.cs dan tekan Tambahkan. File Note.cs akan terbuka di editor kode.

  3. Ganti kode dalam Note.cs file dengan kode ini, yang membuat kelas public dan menambahkan properti dan metode untuk menangani catatan:

    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. Simpan file tersebut.

Anda akan melihat bahwa kode ini sangat mirip dengan kode di NotePage.xaml.cs, dengan beberapa perubahan dan penambahan.

Filename dan Text telah diubah ke public properti, dan properti baru Date telah ditambahkan.

Kode untuk menyimpan dan menghapus file telah ditempatkan dalam public metode. Sebagian besar identik dengan kode yang Anda gunakan di handler peristiwa tombol Click di NotePage, tetapi kode tambahan untuk memperbarui tampilan setelah file dihapus telah dihapus. Ini tidak diperlukan di sini karena Anda akan menggunakan pengikatan data untuk menjaga model dan melihat disinkronkan.

Tanda tangan metode asinkron ini mengembalikan Tugas alih-alih void. Kelas Task mewakili satu operasi asinkron yang tidak mengembalikan nilai. Kecuali tanda tangan metode memerlukan void, seperti halnya untuk Click penanganan aktivitas, async metode harus mengembalikan Task.

Anda juga tidak akan menyimpan referensi ke StorageFile catatan yang menyimpan catatan lagi. Anda hanya mencoba untuk mendapatkan file ketika Anda membutuhkannya untuk menyimpan atau menghapus.

Di NotePage, Anda menggunakan tempat penampung untuk nama file: note.txt. Sekarang setelah aplikasi mendukung lebih dari satu catatan, nama file untuk catatan yang disimpan harus berbeda dan unik. Untuk melakukan ini, atur Filename properti di konstruktor. Anda dapat menggunakan metode DateTime.ToBinary untuk membuat bagian dari nama file berdasarkan waktu saat ini dan membuat nama file unik. Nama file yang dihasilkan terlihat seperti ini: notes-8584626598945870392.txt.

Memperbarui halaman catatan

Sekarang Anda dapat memperbarui NotePage tampilan untuk menggunakan Note model data dan menghapus kode yang dipindahkan ke Note model.

  1. Buka file Views\NotePage.xaml.cs jika belum dibuka di editor.

  2. Setelah pernyataan terakhir using di bagian atas halaman, tambahkan pernyataan baru using untuk memberi kode Anda akses ke kelas di Models folder dan namespace.

    using WinUINotes.Models;
    
  3. Hapus baris ini dari kelas:

    private StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
    private StorageFile? noteFile = null;
    private string fileName = "note.txt";
    
  4. Sebagai gantinya, tambahkan Note objek bernama noteModel di tempat mereka. Ini mewakili data catatan yang NotePage menyediakan tampilan.

    private Note? noteModel;
    
  5. Anda juga tidak memerlukan penanganan NotePage_Loaded aktivitas lagi. Anda tidak akan membaca teks langsung dari file teks ke Kotak Teks. Sebagai gantinya, teks catatan akan dibaca ke dalam Note objek. Anda akan menambahkan kode untuk ini saat menambahkan AllNotesPage di langkah selanjutnya. Hapus baris ini.

    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. Ganti kode dalam SaveButton_Click metode dengan ini:

    if (noteModel is not null)
    {
        await noteModel.SaveAsync();
    }
    
  7. Ganti kode dalam DeleteButton_Click metode dengan ini:

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

Sekarang Anda dapat memperbarui file XAML untuk menggunakan Note model. Sebelumnya, Anda membaca teks langsung dari file teks ke TextBox.Text properti dalam file code-behind. Sekarang, Anda menggunakan pengikatan data untuk Text properti .

  1. Buka file Views\NotePage.xaml jika belum dibuka di editor.

  2. Text Tambahkan atribut ke TextBox kontrol. Ikat ke Text properti : noteModelText="{x:Bind noteModel.Text, Mode=TwoWay}".

  3. Header Perbarui untuk mengikat ke Date properti : noteModelHeader="{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"/>
    

Pengikatan data adalah cara bagi UI aplikasi Anda untuk menampilkan data, dan secara opsional agar tetap sinkron dengan data tersebut. Pengaturan Mode=TwoWay pada pengikatan berarti bahwa properti dan TextBox.Text secara otomatis disinkronkannoteModel.Text. Ketika teks diperbarui di TextBox, perubahan tercermin dalam Text properti noteModel, dan jika noteModel.Text diubah, pembaruan tercermin dalam TextBox.

Properti Header menggunakan default ModeOneTime karena noteModel.Date properti tidak berubah setelah file dibuat. Kode ini juga menunjukkan fitur canggih yang x:Bind disebut pengikatan fungsi, yang memungkinkan Anda menggunakan fungsi seperti ToString sebagai langkah di jalur pengikatan.

Penting

Penting untuk memilih BindingMode yang benar; jika tidak, pengikatan data Anda mungkin tidak berfungsi seperti yang diharapkan. (Kesalahan umum dengan {x:Bind} adalah lupa mengubah default BindingMode saat OneWay atau TwoWay diperlukan.)

Nama Description
OneTime Memperbarui properti target hanya saat pengikatan dibuat. Default untuk {x:Bind}.
OneWay Memperbarui properti target saat pengikatan dibuat. Perubahan pada objek sumber juga dapat disebarluaskan ke target. Default untuk {Binding}.
TwoWay Memperbarui target atau objek sumber saat berubah. Saat pengikatan dibuat, properti target diperbarui dari sumbernya.

Pengikatan data mendukung pemisahan data dan UI Anda, dan itu menghasilkan model konseptual yang lebih sederhana serta keterbacaan, keterujian, dan pemeliharaan aplikasi Anda yang lebih baik.

Di WinUI, ada dua jenis pengikatan yang dapat Anda pilih:

  • Ekstensi {x:Bind} markup diproses pada waktu kompilasi. Beberapa manfaatnya adalah peningkatan performa dan validasi waktu kompilasi ekspresi pengikatan Anda. Disarankan untuk mengikat di aplikasi WinUI.
  • Ekstensi {Binding} markup diproses pada run-time dan menggunakan pemeriksaan objek runtime tujuan umum.

Pelajari selengkapnya di dokumen:

Pengikatan data dan MVVM

Model-View-ViewModel (MVVM) adalah pola desain arsitektur UI untuk memisahkan UI dan kode non-UI yang populer di kalangan pengembang .NET. Anda mungkin akan melihat dan mendengarnya disebutkan saat Anda mempelajari selengkapnya tentang membuat aplikasi WinUI. Memisahkan tampilan dan model, seperti yang telah Anda lakukan di sini, adalah langkah pertama menuju implementasi MVVM penuh aplikasi, tetapi sejauh Anda akan pergi dalam tutorial ini.

Nota

Kami telah menggunakan istilah "model" untuk merujuk ke model data dalam tutorial ini, tetapi penting untuk dicatat bahwa model ini lebih selaras dengan ViewModel dalam implementasi MVVM lengkap, sambil juga menggabungkan aspek Model.

Untuk mempelajari selengkapnya tentang MVVM, lihat sumber daya berikut: