ObservableObject
ObservableObject
adalah kelas dasar untuk objek yang dapat diamati dengan mengimplementasikan INotifyPropertyChanged
antarmuka dan INotifyPropertyChanging
. Ini dapat digunakan sebagai titik awal untuk semua jenis objek yang perlu mendukung pemberitahuan perubahan properti.
API Platform:
ObservableObject
,TaskNotifier
,TaskNotifier<T>
Cara kerjanya
ObservableObject
memiliki fitur utama berikut:
- Ini menyediakan implementasi dasar untuk
INotifyPropertyChanged
danINotifyPropertyChanging
, mengeksposPropertyChanged
peristiwa danPropertyChanging
. - Ini menyediakan serangkaian
SetProperty
metode yang dapat digunakan untuk dengan mudah mengatur nilai properti dari jenis yang diwarisi dariObservableObject
, dan untuk secara otomatis meningkatkan peristiwa yang sesuai. - Ini menyediakan
SetPropertyAndNotifyOnCompletion
metode , yang dianalogikan tetapiSetProperty
dengan kemampuan untuk mengaturTask
properti dan menaikkan peristiwa pemberitahuan secara otomatis ketika tugas yang ditetapkan selesai. - Ini mengekspos
OnPropertyChanged
metode danOnPropertyChanging
, yang dapat ditimpa dalam jenis turunan untuk menyesuaikan bagaimana peristiwa pemberitahuan dinaikkan.
Properti sederhana
Berikut adalah contoh cara menerapkan dukungan pemberitahuan ke properti kustom:
public class User : ObservableObject
{
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
}
Metode yang disediakan SetProperty<T>(ref T, T, string)
memeriksa nilai properti saat ini, dan memperbaruinya jika berbeda, lalu juga menaikkan peristiwa yang relevan secara otomatis. Nama properti secara otomatis diambil melalui penggunaan [CallerMemberName]
atribut, jadi tidak perlu menentukan properti mana yang sedang diperbarui secara manual.
Membungkus model yang tidak dapat diamati
Skenario umum, misalnya, saat bekerja dengan item database, adalah membuat model "dapat diikat" pembungkusan yang menyampaikan properti model database, dan menaikkan pemberitahuan yang diubah properti saat diperlukan. Ini juga diperlukan ketika ingin menyuntikkan dukungan pemberitahuan ke model, yang tidak mengimplementasikan INotifyPropertyChanged
antarmuka. ObservableObject
menyediakan metode khusus untuk membuat proses ini lebih sederhana. Untuk contoh berikut, User
adalah model yang langsung memetakan tabel database, tanpa mewarisi dari ObservableObject
:
public class ObservableUser : ObservableObject
{
private readonly User user;
public ObservableUser(User user) => this.user = user;
public string Name
{
get => user.Name;
set => SetProperty(user.Name, value, user, (u, n) => u.Name = n);
}
}
Dalam hal ini kita menggunakan SetProperty<TModel, T>(T, T, TModel, Action<TModel, T>, string)
kelebihan beban. Tanda tangan sedikit lebih kompleks daripada yang sebelumnya - ini perlu untuk membiarkan kode masih sangat efisien bahkan jika kita tidak memiliki akses ke bidang dukungan seperti dalam skenario sebelumnya. Kita dapat melalui setiap bagian dari tanda tangan metode ini secara rinci untuk memahami peran komponen yang berbeda:
TModel
adalah argumen jenis, menunjukkan jenis model yang kita bungkus. Dalam hal ini, itu akan menjadi kelas kitaUser
. Perhatikan bahwa kita tidak perlu menentukan ini secara eksplisit - pengkompilasi C# akan menyimpulkan ini secara otomatis dengan cara kita memanggil metode .SetProperty
T
adalah jenis properti yang ingin kita tetapkan. DemikianTModel
pula dengan , ini disimpulkan secara otomatis.T oldValue
adalah parameter pertama, dan dalam hal ini kita menggunakanuser.Name
untuk meneruskan nilai saat ini dari properti yang sedang kita bungkus.T newValue
adalah nilai baru untuk diatur ke properti, dan di sini kita meneruskanvalue
, yang merupakan nilai input dalam setter properti.TModel model
adalah model target yang kita bungkus, dalam hal ini kita meneruskan instans yang disimpan diuser
bidang .Action<TModel, T> callback
adalah fungsi yang akan dipanggil jika nilai baru properti berbeda dari yang saat ini, dan properti perlu diatur. Ini akan dilakukan oleh fungsi panggilan balik ini, yang menerima sebagai input model target dan nilai properti baru yang akan ditetapkan. Dalam hal ini kami hanya menetapkan nilai input (yang kami panggiln
) keName
properti (dengan melakukanu.Name = n
). Penting di sini untuk menghindari pengambilan nilai dari cakupan saat ini dan hanya berinteraksi dengan yang diberikan sebagai input ke panggilan balik, karena ini memungkinkan pengkompilasi C# untuk menyimpan fungsi panggilan balik dan melakukan sejumlah peningkatan performa. Karena inilah kita tidak hanya langsung mengaksesuser
bidang di sini atauvalue
parameter di setter, tetapi sebaliknya kita hanya menggunakan parameter input untuk ekspresi lambda.
Metode ini SetProperty<TModel, T>(T, T, TModel, Action<TModel, T>, string)
membuat pembuatan properti pembungkusan ini sangat sederhana, karena mengurus pengambilan dan pengaturan properti target sambil menyediakan API yang sangat ringkas.
Catatan
Dibandingkan dengan implementasi metode ini menggunakan ekspresi LINQ, khususnya melalui parameter jenis Expression<Func<T>>
alih-alih parameter status dan panggilan balik, peningkatan performa yang dapat dicapai dengan cara ini benar-benar signifikan. Secara khusus, versi ini ~ 200x lebih cepat daripada yang menggunakan ekspresi LINQ, dan tidak membuat alokasi memori sama sekali.
Menangani Task<T>
properti
Jika properti adalah Task
penting untuk juga menaikkan peristiwa pemberitahuan setelah tugas selesai, sehingga pengikatan diperbarui pada waktu yang tepat. misalnya untuk menampilkan indikator pemuatan atau info status lainnya pada operasi yang diwakili oleh tugas. ObservableObject
memiliki API untuk skenario ini:
public class MyModel : ObservableObject
{
private TaskNotifier<int>? requestTask;
public Task<int>? RequestTask
{
get => requestTask;
set => SetPropertyAndNotifyOnCompletion(ref requestTask, value);
}
public void RequestValue()
{
RequestTask = WebService.LoadMyValueAsync();
}
}
SetPropertyAndNotifyOnCompletion<T>(ref TaskNotifier<T>, Task<T>, string)
Di sini metode akan mengurus pembaruan bidang target, memantau tugas baru, jika ada, dan menaikkan peristiwa pemberitahuan ketika tugas tersebut selesai. Dengan cara ini, dimungkinkan untuk hanya mengikat ke properti tugas dan diberi tahu ketika statusnya berubah. TaskNotifier<T>
adalah jenis khusus yang diekspos oleh ObservableObject
yang membungkus instans target Task<T>
dan memungkinkan logika pemberitahuan yang diperlukan untuk metode ini. Jenis TaskNotifier
ini juga tersedia untuk digunakan secara langsung jika Anda hanya memiliki umum Task
.
Catatan
Metode SetPropertyAndNotifyOnCompletion
ini dimaksudkan untuk mengganti penggunaan jenis NotifyTaskCompletion<T>
dari Microsoft.Toolkit
paket. Jika jenis ini sedang digunakan, jenis ini dapat diganti hanya dengan properti dalam Task
(atau Task<TResult>
) , dan kemudian SetPropertyAndNotifyOnCompletion
metode dapat digunakan untuk mengatur nilainya dan menaikkan perubahan pemberitahuan. Semua properti yang diekspos oleh NotifyTaskCompletion<T>
jenis tersedia langsung pada Task
instans.
Contoh
- Lihat contoh aplikasi (untuk beberapa kerangka kerja UI) untuk melihat Toolkit MVVM beraksi.
- Anda juga dapat menemukan lebih banyak contoh dalam pengujian unit.
MVVM Toolkit