Memperkenalkan pengikatan data
Dalam pelajaran ini, Anda mempelajari cara membuat aplikasi yang menunjukkan waktu saat ini. Pelajaran ini memperkenalkan dasar-dasar pengikatan data, mendapatkan data dari kode ke UI aplikasi Anda, dan menyegarkannya untuk memperbarui tampilan jam di UI. Pelajaran ini membentuk dasar untuk tugas pengikatan data yang lebih kompleks dalam pelajaran selanjutnya. Jadi, mari kita mulai!
1. Buat proyek
Jika belum berjalan, buka Visual Studio. Buat proyek C# Windows Universal baru dengan menggunakan templat Aplikasi Kosong (Universal Windows). Sebut saja DatabindingSample. Proyek ini adalah proyek yang akan Anda kerjakan selama seluruh UI dan modul Data.
Saat Anda mengklik OK, Visual Studio meminta Anda untuk memasukkan target dan versi Windows minimum. Proyek ini hanyalah proyek latihan, dan Anda tidak berencana untuk menyebarkannya ke komputer yang menjalankan versi Windows yang lebih lama. Oleh karena itu, Anda dapat memilih versi Windows terbaru untuk versi minimum dan target, lalu klik OK.
2. Tambahkan TextBlock untuk tampilan jam
Ketika proyek telah sepenuhnya diinisialisasi dan dimuat, buka MainPage.xaml
dengan mengklik dua kali di Penjelajah Solusi.
Tip
Jika ruang layar hampir habis, gunakan dropdown di sudut kiri atas untuk mengalihkan editor untuk mensimulasikan layar resolusi yang lebih rendah. Sebaiknya gunakan skala 13,3" Desktop (1280x720) 100% untuk modul ini, tetapi pilih yang terasa paling nyaman.
Tambahkan baris berikut antara tag pembuka dan penutup elemen Grid
.
<TextBlock HorizontalAlignment="Right"
Margin="10"
Text="{x:Bind CurrentTime}" />
Ini membuat baru TextBlock
di sisi kanan atas jendela, dengan margin 10 unit dari tepi. Selanjutnya, mari kita atasi Text
dari TextBlock
.
Bagian ini Text={x:Bind CurrentTime}
adalah pertemuan pertama Anda dengan pengikatan data. x:Bind
adalah ekstensi markup XAML yang dikompilasi ke dalam kode C# bersama dengan aplikasi Anda lainnya. Di sini, ia menyambungkan Text
properti ke TextBlock
CurrentTime
properti . Jika Anda mencoba mengkompilasi proyek sekarang, Anda menerima pesan kesalahan berikut:
Kesalahan XamlCompiler WMC1110: Jalur pengikatan 'CurrentTime' tidak valid : Properti 'CurrentTime' tidak dapat ditemukan pada jenis 'MainPage'
Ini menunjukkan bahwa pengkompilasi kehilangan CurrentTime
properti dari MainPage
. Setelah kita membuat properti itu, kontennya ditampilkan di TextBlock
sudut kanan atas.
Catatan
UWP juga mendukung metode pengikatan data yang lebih lama, yang terlihat seperti ini: Text={Bind CurrentTime}
. Metode yang lebih lama ini bekerja agak berbeda dari {x:Bind}
. Terutama, ini tidak menawarkan kesalahan waktu kompilasi jika Anda memiliki kesalahan ketik. Dalam modul ini, kami berfokus secara eksklusif pada cara pengikatan baru {x:Bind}
, yang memberikan pemeriksaan kesalahan waktu kompilasi. Namun, {x:Bind}
kurang matang daripada {Bind}
, dan menerima fitur baru, itulah sebabnya kami memilih untuk menggunakan versi Windows terbaru untuk membuat proyek.
3. Buat CurrentTime
properti
Buka MainPage.xaml.cs, dan tambahkan definisi properti berikut ke MainPage
kelas .
public string CurrentTime => DateTime.Now.ToLongTimeString();
Jika Anda tidak terbiasa dengan sintaks di atas, itu disebut anggota bertubuh ekspresi. Ini diperkenalkan dalam C# 6.0, dan singkatan dari yang berikut:
public string CurrentTime
{
get { return DateTime.Now.ToLongTimeString(); }
}
4. Jalankan aplikasi
Jika Anda meluncurkan aplikasi sekarang (dengan menggunakan kunci F5 atau perintah Debug / Mulai Debugging di menu), aplikasi mengkompilasi dan menjalankan. Apa yang lebih baik adalah bahwa tampaknya bekerja! Waktu saat ini ditampilkan di sudut kanan atas.
Namun, ada sesuatu yang tidak benar karena jam tidak diperbarui. Macet pada saat aplikasi pertama kali diluncurkan. Bagaimana aplikasi tahu kapan harus merefresh nilai di TextBlock
? Kita harus memberi tahu runtime UWP untuk memperbaruinya sekali per detik.
5. Tentukan mode pengikatan
{x:Bind}
pengikatan sangat dioptimalkan untuk performa. Artinya mereka tidak melakukan apa pun yang belum diminta pengembang secara eksplisit. Jadi secara default, pengikatan {x:Bind}
hanya mengevaluasi sumber pengikatan (dalam kasus kami, CurrentTime
properti ) sekali. Pengikatan semacam ini disebut OneTime
pengikatan. Jika kita ingin kerangka kerja UWP terus memperbarui UI, kita harus secara eksplisit menentukan mode pengikatan lain: baik OneWay
atau TwoWay
.
TwoWay
mode pengikatan menunjukkan pengikatan dua arah antara kode C# kami (logika) dan UI. Jenis pengikatan ini akan berguna nanti ketika kita mengikat kontrol yang dapat dimanipulasi pengguna. Tetapi untuk TextBlock
, OneWay
pengikatan lebih disukai karena perubahan data hanya akan berasal dari kode, tidak pernah di UI.
Untuk menentukan OneWay
mode pengikatan untuk , TextBlock
ubah {x:Bind CurrentTime}
ke {x:Bind CurrentTime, Mode=OneWay}
. Seluruh TextBlock
tag dalam Grid
sekarang akan terlihat seperti markup ini.
<TextBlock HorizontalAlignment="Right"
Margin="10"
Text="{x:Bind CurrentTime, Mode=OneWay}" />
Pengikatan menginstruksikan runtime UWP untuk membangun infrastruktur yang diperlukan untuk melacak perubahan pada CurrentTime
properti, dan mencerminkannya di Text
dari TextBlock
. Infrastruktur tambahan ini membutuhkan sedikit memori dan siklus CPU, dan itulah sebabnya itu bukan default.
Jika Anda menjalankan aplikasi sekarang, jam masih tidak akan diperbarui. Kita perlu memberi tahu sistem bahwa CurrentTime
properti telah berubah.
6. Terapkan INotifyPropertyChanged
antarmuka
Pemberitahuan ini terjadi melalui INotifyPropertyChanged
antarmuka. Ini adalah antarmuka sederhana dengan satu peristiwa.
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
Setiap kelas yang memiliki properti C# sederhana sebagai sumber pengikatan data harus mengimplementasikan INotifyPropertyChanged
antarmuka. Kelas harus mengaktifkan PropertyChanged
peristiwa ketika UI harus diperbarui. Mari kita lanjutkan dan tambahkan antarmuka ke MainPage
deklarasi kelas.
public sealed partial class MainPage : Page, INotifyPropertyChanged
Kita juga harus mengimplementasikan antarmuka dengan menambahkan PropertyChanged
peristiwa ke kelas .
public event PropertyChangedEventHandler PropertyChanged;
7. Panggil PropertyChanged
acara setiap detik
Yang tersisa adalah memanggil PropertyChanged
peristiwa setiap kali kita ingin memperbarui jam (yaitu, setiap detik). Untuk memulai, mari kita deklarasikan DispatcherTimer
objek di MainPage
kelas .
private DispatcherTimer _timer;
Sekarang mari kita siapkan di konstruktor (setelah InitializeComponent
panggilan) sehingga diaktifkan setiap detik.
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_timer.Tick += (sender, o) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentTime)));
_timer.Start();
Baris pertama di atas membuat timer dengan interval satu detik, dan baris terakhir memulainya. Mari kita periksa apa yang terjadi ketika timer diaktifkan (di baris kedua).
PropertyChanged?.Invoke
singkatan untuk memeriksa apakah suatu peristiwa null dan, jika tidak, memanggilnya. Seperti kebanyakan peristiwa, argumen pertama adalah pengirim (this
). Argumen kedua untuk PropertyChanged
peristiwa adalah objek yang baru dibuat PropertyChangedEventArgs
, yang memiliki konstruktor yang mengharapkan string sebagai nama properti. Jadi pelanggan peristiwa PropertyChanged
(dalam hal ini, sistem UWP) akan menerima nama properti yang diperbarui, dan dapat bertindak sesuai.
Tip
Jangan gunakan literal string (seperti "CurrentTime"
) untuk nama properti. Menggunakan string itu sendiri rentan terhadap kesalahan ketik, yang dapat mengakibatkan masalah hard-to-debug ketika UI tidak diperbarui. Selain itu, penggantian nama properti yang tidak bersalah juga dapat menimbulkan kesalahan jika konstanta string tidak diperbarui. Ini adalah praktik yang baik untuk selalu menggunakan nameof
ekspresi, yang kebal terhadap kesalahan ketik dan dapat mengikuti penggantian nama.
Seluruh MainPage.xaml.cs akan terlihat seperti berikut ini:
namespace DatabindingSample
{
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private DispatcherTimer _timer;
public MainPage()
{
this.InitializeComponent();
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_timer.Tick += (sender, o) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentTime)));
_timer.Start();
}
public string CurrentTime => DateTime.Now.ToLongTimeString();
public event PropertyChangedEventHandler PropertyChanged;
}
}
8. Jalankan aplikasi
Jika Anda menjalankan aplikasi sekarang, jam akan diperbarui. Selamat, Anda telah membuat pengikatan data pertama Anda!
9. Ringkasan
Anda sekarang tahu cara menggunakan {x:Bind
} untuk membuat cara cepat dan otomatis mendapatkan data dari kode ke UI aplikasi UWP Anda. Teknik ini diperiksa pada saat kompilasi. Anda juga telah terbiasa dengan INotifyPropertyChanged
antarmuka. Antarmuka ini memungkinkan aplikasi Anda memberi tahu kerangka kerja UWP ketika properti terikat data telah berubah dan UI harus diperbarui.
1. Buat proyek
Jika belum berjalan, buka Visual Studio. Buat proyek C# WPF baru dengan menggunakan templat Aplikasi WPF. Sebut saja DatabindingSampleWPF, lalu pilih OK. Proyek ini adalah proyek yang akan Anda kerjakan selama seluruh UI dan modul Data.
2. Buat kelas Jam
Karena tugas kita adalah menampilkan waktu saat ini, masuk akal untuk membuat kelas terlebih Clock
dahulu. DatabindingSampleWPF
Klik kanan proyek di Penjelajah Solusi, pilih Tambahkan / Kelas, dan masukkan Clock
sebagai nama kelas.
Salin kode berikut ke dalam file yang baru dibuat:
using System;
namespace DatabindingSampleWPF
{
public class Clock
{
public string CurrentTime => DateTime.Now.ToLongTimeString();
}
}
Jika Anda tidak terbiasa dengan sintaks di atas untuk CurrentTime
properti , itu disebut anggota bertubuh ekspresi. Ini diperkenalkan dalam C# 6.0, dan singkatan dari yang berikut:
public string CurrentTime
{
get { return DateTime.Now.ToLongTimeString(); }
}
Seperti yang Anda lihat, semua Clock
kelas sejauh ini adalah properti sederhana string
yang mengembalikan waktu saat ini dalam format waktu yang lama. Langkah selanjutnya adalah menampilkan waktu dalam aplikasi itu sendiri.
3. Tambahkan TextBlock untuk tampilan jam
Jika Anda telah MainWindow.xaml
membuka di Visual Studio, pilih tabnya. Jika tidak, Anda dapat membukanya dengan mengklik dua kali di Penjelajah Solusi.
Tambahkan baris berikut antara tag pembuka dan penutup elemen Grid
.
<TextBlock HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="10"
Text="{Binding CurrentTime}">
<TextBlock.DataContext>
<local:Clock/>
</TextBlock.DataContext>
</TextBlock>
Markup ini akan membuat baru TextBlock
di sisi kanan atas jendela, dengan margin 10 unit dari tepi.
Bagian ini Text="{Binding CurrentTime}"
adalah pertemuan pertama Anda dengan pengikatan data. {Binding}
adalah ekstensi markup XAML. Di sini, menyambungkan Text
properti ke TextBlock
CurrentTime
properti - tetapi CurrentTime
properti objek mana?
Objek yang dirujuk oleh pengikatan data diinstansiasi DataContext
di dari TextBlock
. Jadi, kode XAML di atas tidak hanya membuat TextBlock
kontrol, tetapi juga membuat Clock
instans objek. Selanjutnya, kode mengikat Text
properti ke TextBlock
CurrentTime
properti objek yang Clock
dibuatnya. Properti CurrentTime
disebut sumber pengikatan, sementara Text
properti disebut tujuan pengikatan.
4. Jalankan aplikasi
Jika Anda meluncurkan aplikasi sekarang (dengan menggunakan kunci F5 atau perintah Debug / Mulai Debugging di menu), aplikasi mengkompilasi dan menjalankan. Apa yang lebih baik adalah bahwa tampaknya bekerja! Waktu saat ini ditampilkan di sudut kanan atas.
Namun, ada sesuatu yang tidak benar karena jam tidak diperbarui. Macet pada saat aplikasi pertama kali diluncurkan. Bagaimana aplikasi tahu kapan harus merefresh nilai di TextBlock
? Kita harus memberi tahu runtime WPF untuk memperbaruinya sekali per detik.
Dengan kata lain, kita perlu memberi tahu sistem bahwa CurrentTime
properti telah berubah.
5. Terapkan INotifyPropertyChanged
antarmuka
Pemberitahuan ini terjadi melalui INotifyPropertyChanged
antarmuka. Ini adalah antarmuka sederhana dengan satu peristiwa.
public interface INotifyPropertyChanged
{
event PropertyChangedEventHandler PropertyChanged;
}
Setiap kelas yang memiliki properti C# sederhana sebagai sumber pengikatan data harus mengimplementasikan INotifyPropertyChanged
antarmuka. Kelas harus mengaktifkan PropertyChanged
peristiwa ketika UI harus diperbarui. Mari kita lanjutkan dan tambahkan antarmuka ke Clock
deklarasi kelas.
using System.ComponentModel;
public class Clock : INotifyPropertyChanged
{
Kita juga harus mengimplementasikan antarmuka dengan menambahkan PropertyChanged
peristiwa ke kelas .
public event PropertyChangedEventHandler? PropertyChanged;
6. Panggil PropertyChanged
peristiwa setiap detik
Yang tersisa adalah memanggil PropertyChanged
peristiwa setiap kali kita ingin memperbarui jam (yaitu, setiap detik). Untuk memulai, mari kita tambahkan System.Windows.Threading
namespace layanan ke using
s, dan deklarasikan DispatcherTimer
objek di Clock
kelas .
private DispatcherTimer _timer;
Sekarang siapkan di konstruktor, sehingga menembak setiap detik.
public Clock()
{
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_timer.Tick += (sender, o) => PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(CurrentTime)));
_timer.Start();
}
Baris pertama dalam konstruktor membuat timer dengan interval satu detik, dan baris terakhir memulainya. Mari kita periksa apa yang terjadi ketika timer diaktifkan (di baris kedua).
PropertyChanged?.Invoke
singkatan untuk memeriksa apakah suatu peristiwa null dan, jika tidak, memanggilnya. Seperti kebanyakan peristiwa, argumen pertama adalah pengirim (this
). Argumen kedua untuk PropertyChanged
peristiwa adalah objek yang baru dibuat PropertyChangedEventArgs
, yang memiliki konstruktor yang mengharapkan string sebagai nama properti. Jadi pelanggan peristiwa PropertyChanged
(dalam hal ini, sistem WPF) akan menerima nama properti yang diperbarui, dan dapat bertindak sesuai.
Tip
Jangan gunakan literal string (seperti "CurrentTime"
) untuk nama properti. Menggunakan string itu sendiri rentan terhadap kesalahan ketik, yang dapat mengakibatkan masalah hard-to-debug ketika UI tidak diperbarui. Selain itu, penggantian nama properti yang tidak bersalah juga dapat menimbulkan kesalahan jika konstanta string tidak diperbarui. Ini adalah praktik yang baik untuk selalu menggunakan nameof
ekspresi, yang kebal terhadap kesalahan ketik dan dapat mengikuti operasi penggantian nama.
Seluruhnya Clock.cs
akan terlihat seperti berikut ini:
namespace DatabindingSampleWPF
{
using System;
using System.ComponentModel;
using System.Windows.Threading;
public class Clock : INotifyPropertyChanged
{
private DispatcherTimer _timer;
public string CurrentTime => DateTime.Now.ToLongTimeString();
public event PropertyChangedEventHandler PropertyChanged;
public Clock()
{
// setup _timer to refresh CurrentTime
_timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
_timer.Tick += (sender, o) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentTime)));
_timer.Start();
}
}
}
7. Jalankan aplikasi
Jika Anda menjalankan aplikasi sekarang, jam akan diperbarui. Anda telah membuat pengikatan data pertama Anda!
8. Ringkasan
Anda sekarang tahu cara menggunakan {Binding}
untuk membuat cara cepat dan otomatis mendapatkan data dari kode ke UI aplikasi WPF Anda. Anda juga telah terbiasa dengan INotifyPropertyChanged
antarmuka. Antarmuka ini memungkinkan aplikasi Anda memberi tahu kerangka kerja WPF ketika properti terikat data telah berubah dan UI harus diperbarui.