Memperkenalkan pengikatan data

Selesai

Tech logo of U W P and W P F.

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!

Tech logo of U W P and W P F. W P F appears dimmed.

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.

Screenshot of the Visual Studio Create a new project dialog box.

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 TextBlockCurrentTime 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.

Screenshot of the running app with the clock.

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 , TextBlockubah {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.

Tech logo of U W P and W P F. U W P appears dimmed.

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.

Screenshot of the Visual Studio Create a new WPF project dialog box.

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 TextBlockCurrentTime 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 TextBlockCurrentTime 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.

Screenshot of the running app with the clock.

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 usings, 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.