Menggunakan viewmodel

Selesai

Setelah mempelajari tentang komponen yang membentuk pola MVVM, Anda mungkin menemukan bahwa model dan tampilan mudah didefinisikan. Mari kita jelajahi cara menggunakan viewmodel, untuk menentukan perannya dengan lebih baik dalam pola.

Mengekspos properti ke antarmuka pengguna

Seperti dalam contoh sebelumnya, viewmodel biasanya mengandalkan model untuk sebagian besar data mereka dan logika bisnis apa pun. Tapi itu adalah viewmodel yang memformat, mengonversi, dan memperkaya data dengan cara apa pun yang diperlukan tampilan saat ini.

Memformat dengan menggunakan viewmodel

Anda sudah melihat contoh pemformatan dengan waktu liburan. Pemformatan tanggal, pengodean karakter, dan serialisasi adalah semua contoh bagaimana viewmodel mungkin memformat data dari model.

Mengonversi dengan menggunakan viewmodel

Seringkali, model menyediakan informasi dengan cara yang tidak langsung. Tapi viewmodel bisa memperbaikinya. Misalnya, Anda ingin menampilkan di layar apakah karyawan adalah supervisor. Tapi model kita Employee tidak memberitahu kita secara langsung. Sebaliknya, Anda harus menyimpulkan fakta ini berdasarkan apakah orang tersebut memiliki orang lain yang melaporkan kepada mereka. Asumsikan bahwa model memiliki properti ini:

public IList<Employee> DirectReports
{
    get
    {
        ...
    }
}

Jika daftar kosong, Anda dapat menyimpulkan bahwa ini Employee bukan supervisor. Dalam hal ini, EmployeeViewModel sertakan properti IsSupervisor yang menyediakan logika tersebut:

public bool IsSupervisor => _model.DirectReports.Any();

Memperkaya dengan menggunakan viewmodel

Terkadang model mungkin hanya memberikan ID untuk data terkait. Atau Anda mungkin perlu membuka beberapa kelas model untuk menghubungkan data yang diperlukan untuk satu layar. Viewmodel juga menyediakan tempat yang ideal untuk melakukan tugas-tugas ini. Misalkan Anda ingin menunjukkan semua proyek yang saat ini dikelola karyawan. Data ini bukan bagian Employee dari kelas model. Ini dapat diakses dengan melihat CompanyProjects kelas model. Kami EmployeeViewModel, seperti biasa, mengekspos pekerjaannya sebagai properti publik:

public IEnumerable<string> ActiveProjects => CompanyProjects.All
    .Where(p => p.Owner == _model.Id && p.IsActive)
    .Select(p => p.Name);

Menggunakan properti pass-through dengan viewmodel

Seringkali viewmodel membutuhkan properti yang disediakan model. Untuk properti tersebut, viewmodel hanya meneruskan data melalui:

public string Name
{
    get => _model.Name;
    set => _model.Name = value;
}

Mengatur cakupan untuk viewmodel

Anda dapat menggunakan viewmodel di tingkat mana pun di mana ada tampilan. Halaman biasanya memiliki viewmodel, tetapi mungkin subview halaman. Salah satu alasan umum untuk viewmodel berlapis adalah ketika halaman ditampilkan ListView di halaman. Daftar memiliki viewmodel yang mewakili koleksi, seperti EmployeeListViewModel. Setiap elemen dalam daftar adalah EmployeeViewModel.

Diagram EmployeeListViewModel dengan beberapa subobjek EmployeeViewModel.

Biasanya juga memiliki viewmodel tingkat atas yang menyimpan data dan status untuk seluruh aplikasi tetapi tidak terkait dengan halaman tertentu. Viewmodel seperti itu biasanya digunakan untuk mempertahankan item "aktif". Pertimbangkan contoh yang ListView baru saja dijelaskan. Saat pengguna memilih baris karyawan, karyawan tersebut mewakili item saat ini. Jika pengguna menavigasi ke halaman detail atau memilih tombol toolbar saat baris tersebut dipilih, tindakan atau tampilan harus untuk karyawan tersebut. Cara elegan untuk menangani skenario ini adalah dengan memiliki ListView.SelectItem data yang terikat ke properti yang juga dapat diakses oleh toolbar atau halaman detail. Menempatkan properti itu pada viewmodel pusat bekerja dengan baik.

Mengidentifikasi kapan menggunakan kembali viewmodel dengan tampilan

Bagaimana Anda menentukan hubungan antara viewmodel dan model dan antara viewmodel dan tampilan ditentukan lebih banyak berdasarkan persyaratan aplikasi daripada berdasarkan aturan. Tujuan viewmodel adalah untuk menyediakan tampilan struktur dan data yang dibutuhkannya. Itu harus memandu keputusan tentang "seberapa besar" untuk mencakup viewmodel.

Viewmodel sering mencerminkan struktur kelas model, dan mereka memiliki hubungan satu-ke-satu dengan kelas tersebut. Anda melihat contoh sebelumnya dengan EmployeeViewModel yang membungkus dan menambah satu Employee instans. Tapi itu tidak selalu hubungan satu-ke-satu. Jika viewmodel dirancang untuk menyediakan apa yang dibutuhkan tampilan, Anda mungkin berakhir dengan sesuatu seperti HRDashboardViewModel untuk memberikan gambaran umum tentang departemen SDM, yang tidak memiliki hubungan eksplisit dengan model apa pun tetapi dapat menggunakan data dari kelas model apa pun .

Demikian pula, Anda mungkin menemukan bahwa viewmodel dan tampilan sering memiliki hubungan satu-ke-satu. Tapi ini juga belum tentu terjadi. Mari kita pikirkan lagi ListView yang menunjukkan baris untuk setiap karyawan. Saat Anda memilih salah satu baris, Anda masuk ke halaman detail karyawan.

Halaman daftar memiliki viewmodel-nya dengan koleksi. Seperti yang disarankan sebelumnya, koleksi itu bisa menjadi kumpulan EmployeeViewModel objek. Dan ketika pengguna memilih baris, EmployeeViewModel instans dapat diteruskan ke EmployeeDetailPage. Dan halaman detail dapat menggunakannya EmployeeViewModel sebagai BindingContext.

Skenario ini mungkin merupakan kesempatan yang sangat baik untuk penggunaan kembali viewmodel. Tetapi perlu diingat bahwa viewmodel dimaksudkan untuk memberikan apa yang dibutuhkan tampilan. Dalam beberapa kasus, Anda mungkin ingin viewmodel terpisah, bahkan jika semuanya didasarkan pada kelas model yang sama. Dalam contoh ini, ListView baris cenderung membutuhkan informasi yang jauh lebih sedikit daripada halaman detail lengkap. Jika mengambil data, halaman detail perlu menambahkan banyak jika overhead, Anda mungkin ingin memiliki model EmployeeListRowViewModel dan EmployeeDetailViewModel yang melayani tampilan masing-masing.

Model objek Viewmodel

Menggunakan kelas dasar yang mengimplementasikan INotifyPropertyChanged berarti Anda tidak perlu mengisi ulang antarmuka pada setiap viewmodel. Pertimbangkan aplikasi HR seperti yang dijelaskan di bagian sebelumnya dari modul pelatihan ini. Kelas EmployeeViewModel menerapkan antarmuka dan menyediakan metode pembantu INotifyPropertyChangedPropertyChanged bernama OnPropertyChanged untuk meningkatkan peristiwa. Viewmodel lain dalam proyek, seperti yang menjelaskan sumber daya yang ditetapkan untuk karyawan, juga harus INotifyPropertyChanged sepenuhnya berintegrasi dengan tampilan.

Pustaka Toolkit MVVM, bagian dari .NET Community Toolkit, adalah kumpulan jenis standar, mandiri, ringan yang menyediakan implementasi awal untuk membangun aplikasi modern menggunakan pola MVVM.

Alih-alih menulis kelas dasar viewmodel Anda sendiri, Anda mewarisi dari kelas toolkit ObservableObject , yang menyediakan semua yang Anda butuhkan untuk kelas dasar viewmodel. EmployeeViewModel dapat disederhanakan dari:

using System.ComponentModel;

public class EmployeeViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    private Employee _model;

    public string Name
    {
        get {...}
        set
        {
            _model.Name = value;
            OnPropertyChanged(nameof(Name))
        }
    }

    protected void OnPropertyChanged(string propertyName) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Ke kode berikut:

using Microsoft.Toolkit.Mvvm.ComponentModel;

public class EmployeeViewModel : ObservableObject
{
    private string _name;

    public string Name
    {
        get => _name;
        set => SetProperty(ref _name, value);
    }
}

Toolkit MVVM didistribusikan melalui CommunityToolkit.Mvvm paket NuGet.

Uji pengetahuan Anda

1.

Saat menggunakan pola MVVM dengan .NET MAUI, model, tampilan, dan viewmodel Anda tidak sepenuhnya dipisahkan satu sama lain. Pilihan mana yang menjelaskan satu dependensi umum antara potongan MVVM?

2.

Mana yang kemungkinan besar akan digabungkan erat dengan platform dan sulit untuk membuat pengujian unit untuk: model, tampilan, atau viewmodel?