Tutorial: Membuat pengikatan data
Misalkan Anda telah merancang dan mengimplementasikan UI yang terlihat bagus yang diisi dengan gambar tempat penampung, teks boilerplate "lorem ipsum", dan kontrol yang belum melakukan apa pun. Selanjutnya, Anda harus menghubungkannya ke data nyata dan mengubahnya dari prototipe desain menjadi aplikasi hidup.
Dalam tutorial ini, Anda akan mempelajari cara mengganti boilerplate dengan pengikatan data dan membuat tautan langsung lainnya antara UI dan data Anda. Anda juga akan mempelajari cara memformat atau mengonversi data untuk ditampilkan, dan menjaga UI dan data Anda tetap sinkron. Ketika Anda menyelesaikan tutorial ini, Anda akan dapat meningkatkan kesederhanaan dan organisasi kode XAML dan C#, sehingga lebih mudah untuk dipertahankan dan diperluas.
Anda akan mulai dengan versi sampel PhotoLab yang disederhanakan. Versi pemula ini mencakup lapisan data lengkap ditambah tata letak halaman XAML dasar, dan meninggalkan banyak fitur untuk membuat kode lebih mudah dijelajahi. Tutorial ini tidak dibangun ke aplikasi lengkap, jadi pastikan untuk memeriksa versi akhir untuk melihat fitur seperti animasi kustom dan tata letak adaptif. Anda dapat menemukan versi akhir di folder akar repositori Windows-appsample-photo-lab .
Aplikasi sampel PhotoLab memiliki dua halaman. Halaman utama menampilkan tampilan galeri foto, bersama dengan beberapa informasi tentang setiap file gambar.
Halaman detail menampilkan satu foto setelah dipilih. Menu pengeditan flyout memungkinkan foto diubah, diganti namanya, dan disimpan.
Prasyarat
- Visual Studio 2019 atau yang lebih baru: Unduh Visual Studio (Edisi Komunitas gratis.)
- Windows SDK (10.0.17763.0 atau yang lebih baru): Unduh Windows SDK terbaru (gratis)
- Windows 10, Versi 1809 atau yang lebih baru
Bagian 0: Dapatkan kode pemula dari GitHub
Untuk tutorial ini, Anda akan mulai dengan versi sampel PhotoLab yang disederhanakan.
Buka halaman GitHub untuk sampel: https://github.com/Microsoft/Windows-appsample-photo-lab.
Selanjutnya, Anda harus mengkloning atau mengunduh sampel. Pilih tombol Kloning atau unduh . Sub-menu muncul.
Jika Anda tidak terbiasa dengan GitHub:
a. Pilih Unduh ZIP dan simpan file secara lokal. Ini mengunduh file .zip yang berisi semua file proyek yang Anda butuhkan.
b. Ekstrak file. Gunakan File Explorer untuk menelusuri file .zip yang baru saja Anda unduh, klik kanan, dan pilih Ekstrak Semua....
c. Telusuri ke salinan sampel lokal Anda, dan buka
Windows-appsample-photo-lab-master\xaml-basics-starting-points\data-binding
direktori.Jika Anda terbiasa dengan GitHub:
a. Kloning cabang utama repositori secara lokal.
b. Telusuri ke
Windows-appsample-photo-lab\xaml-basics-starting-points\data-binding
direktori.Photolab.sln
Klik dua kali untuk membuka solusi di Visual Studio.
Bagian 1: Ganti tempat penampung
Di sini, Anda membuat pengikatan satu kali di XAML templat data untuk menampilkan gambar nyata dan metadata gambar alih-alih konten tempat penampung.
Pengikatan satu kali adalah untuk data baca-saja yang tidak berubah, yang berarti mereka berkinerja tinggi dan mudah dibuat, memungkinkan Anda menampilkan kumpulan data besar dalam GridView
dan ListView
kontrol.
Ganti tempat penampung dengan pengikatan satu kali
xaml-basics-starting-points\data-binding
Buka folder dan luncurkanPhotoLab.sln
file di Visual Studio.Pastikan Platform Solusi Anda diatur ke x86 atau x64, bukan Arm, lalu jalankan aplikasi. Ini menunjukkan status aplikasi dengan tempat penampung UI, sebelum pengikatan telah ditambahkan.
Buka MainPage.xaml dan cari
DataTemplate
ImageGridView_DefaultItemTemplate bernama. Anda akan memperbarui templat ini untuk menggunakan pengikatan data.Sebelum:
<DataTemplate x:Key="ImageGridView_DefaultItemTemplate">
Nilai
x:Key
digunakan olehImageGridView
untuk memilih templat ini untuk menampilkan objek data.x:DataType
Tambahkan nilai ke templat.Setelah:
<DataTemplate x:Key="ImageGridView_DefaultItemTemplate" x:DataType="local:ImageFileInfo">
x:DataType
menunjukkan jenis mana ini adalah templat untuk. Dalam hal ini, ini adalah templat untukImageFileInfo
kelas (di manalocal:
menunjukkan namespace lokal, seperti yang didefinisikan dalam deklarasi xmlns di dekat bagian atas file).x:DataType
diperlukan saat menggunakanx:Bind
ekspresi dalam templat data, seperti yang dijelaskan berikutnya.Dalam , temukan elemen bernama
ItemImage
dan ganti nilainyaSource
seperti yangImage
ditunjukkanDataTemplate
.Sebelum:
<Image x:Name="ItemImage" Source="/Assets/StoreLogo.png" Stretch="Uniform" />
Setelah:
<Image x:Name="ItemImage" Source="{x:Bind ImageSource}" Stretch="Uniform" />
x:Name
mengidentifikasi elemen XAML sehingga Anda dapat merujuknya ke tempat lain di XAML dan di kode di belakang.x:Bind
ekspresi memberikan nilai ke properti UI dengan mendapatkan nilai dari properti objek data. Dalam templat, properti yang ditunjukkan adalah properti dari apa pun yangx:DataType
telah diatur. Jadi dalam hal ini, sumber data adalahImageFileInfo.ImageSource
properti .Catatan
Nilai ini
x:Bind
juga memberi tahu editor tentang jenis data, sehingga Anda dapat menggunakan IntelliSense alih-alih mengetikkan nama properti dalamx:Bind
ekspresi. Coba pada kode yang baru saja Anda tempel: tempatkan kursor tepat setelahnyax:Bind
dan tekan Spacebar untuk melihat daftar properti yang dapat Anda ikat.Ganti nilai kontrol UI lainnya dengan cara yang sama. (Coba lakukan ini dengan IntelliSense alih-alih menyalin/menempelkan!)
Sebelum:
<TextBlock Text="Placeholder" ... /> <StackPanel ... > <TextBlock Text="PNG file" ... /> <TextBlock Text="50 x 50" ... /> </StackPanel> <muxc:RatingControl Value="3" ... />
Setelah:
<TextBlock Text="{x:Bind ImageTitle}" ... /> <StackPanel ... > <TextBlock Text="{x:Bind ImageFileType}" ... /> <TextBlock Text="{x:Bind ImageDimensions}" ... /> </StackPanel> <muxc:RatingControl Value="{x:Bind ImageRating}" ... />
Jalankan aplikasi untuk melihat tampilannya sejauh ini. Tidak ada tempat penampung lagi! Kita berangkat ke awal yang baik.
Catatan
Jika Anda ingin bereksperimen lebih lanjut, coba tambahkan TextBlock baru ke templat data, dan gunakan trik x:Bind IntelliSense untuk menemukan properti yang akan ditampilkan.
Bagian 2: Gunakan pengikatan untuk menyambungkan antarmuka pengguna galeri ke gambar
Di sini, Anda akan membuat pengikatan satu kali di halaman XAML untuk menyambungkan tampilan galeri ke koleksi gambar, menggantikan kode prosedural yang ada yang melakukan ini di code-behind. Anda juga akan membuat tombol Hapus untuk melihat bagaimana tampilan galeri berubah saat gambar dihapus dari koleksi. Pada saat yang sama, Anda akan mempelajari cara mengikat peristiwa ke penanganan aktivitas untuk lebih banyak fleksibilitas daripada yang disediakan oleh penanganan aktivitas tradisional.
Semua pengikatan yang tercakup sejauh ini berada di dalam templat data dan merujuk ke properti kelas yang ditunjukkan oleh x:DataType
nilai . Bagaimana dengan XAML lainnya di halaman Anda?
x:Bind
ekspresi di luar templat data selalu terikat ke halaman itu sendiri. Ini berarti Anda dapat mereferensikan apa pun yang Anda masukkan ke dalam code-behind atau deklarasikan di XAML, termasuk properti kustom dan properti kontrol UI lain di halaman (selama mereka memiliki x:Name
nilai).
Dalam sampel PhotoLab, salah satu penggunaan untuk pengikatan seperti ini adalah untuk menghubungkan kontrol utama GridView
langsung ke pengumpulan gambar, alih-alih melakukannya di code-behind. Nantinya, Anda akan melihat contoh lain.
Mengikat kontrol GridView utama ke koleksi Gambar
Di MainPage.xaml.cs, temukan
GetItemsAsync
metode dan hapus kode yang mengaturItemsSource
.Sebelum:
ImageGridView.ItemsSource = Images;
Setelah:
// Replaced with XAML binding: // ImageGridView.ItemsSource = Images;
Di MainPage.xaml, temukan
GridView
atribut bernamaImageGridView
dan tambahkanItemsSource
. Untuk nilai , gunakanx:Bind
ekspresi yang mengacu pada properti yangImages
diimplementasikan dalam code-behind.Sebelum:
<GridView x:Name="ImageGridView"
Setelah:
<GridView x:Name="ImageGridView" ItemsSource="{x:Bind Images}"
Properti
Images
berjenisObservableCollection<ImageFileInfo>
, sehingga item individual yang ditampilkan dalamGridView
tipeImageFileInfo
. Ini cocok dengan nilai yangx:DataType
dijelaskan di Bagian 1.
Semua pengikatan yang telah kita lihat sejauh ini adalah pengikatan baca-saja satu kali, yang merupakan perilaku default untuk ekspresi biasa x:Bind
. Data hanya dimuat pada inisialisasi, yang membuat pengikatan berperforma tinggi - sempurna untuk mendukung beberapa tampilan kompleks himpunan data besar.
Bahkan pengikatan ItemsSource
yang baru saja Anda tambahkan adalah pengikatan baca-saja satu kali dengan nilai properti yang tidak berubah, tetapi ada perbedaan penting untuk dibuat di sini. Nilai properti yang tidak berubah Images
adalah satu instans tertentu dari koleksi, diinisialisasi sekali seperti yang ditunjukkan di sini.
private ObservableCollection<ImageFileInfo> Images { get; }
= new ObservableCollection<ImageFileInfo>();
Nilai Images
properti tidak pernah berubah, tetapi karena properti berjenis ObservableCollection<T>
, konten koleksi dapat berubah, dan pengikatan akan secara otomatis melihat perubahan dan memperbarui UI.
Untuk menguji ini, kita akan menambahkan tombol untuk sementara waktu yang menghapus gambar yang saat ini dipilih. Tombol ini tidak berada dalam versi akhir karena memilih gambar akan membawa Anda ke halaman detail. Namun, perilaku ObservableCollection<T>
masih penting dalam sampel PhotoLab akhir karena XAML diinisialisasi di konstruktor halaman (melalui InitializeComponent
panggilan metode), tetapi Images
koleksi diisi nanti dalam GetItemsAsync
metode .
Menambahkan tombol hapus
Di MainPage.xaml, temukan
CommandBar
MainCommandBar bernama dan tambahkan tombol baru sebelum tombol zoom. (Kontrol zoom belum berfungsi. Anda akan menghubungkan mereka di bagian berikutnya dari tutorial.)<AppBarButton Icon="Delete" Label="Delete selected image" Click="{x:Bind DeleteSelectedImage}" />
Jika Anda sudah terbiasa dengan XAML, nilai ini
Click
mungkin terlihat tidak biasa. Di versi XAML sebelumnya, Anda harus mengatur ini ke metode dengan tanda tangan penanganan aktivitas tertentu, biasanya menyertakan parameter untuk pengirim peristiwa dan objek argumen khusus peristiwa. Anda masih dapat menggunakan teknik ini ketika Anda memerlukan argumen peristiwa, tetapi denganx:Bind
, Anda juga dapat terhubung ke metode lain. Misalnya, jika Anda tidak memerlukan data peristiwa, Anda dapat terhubung ke metode yang tidak memiliki parameter, seperti yang kami lakukan di sini.Di MainPage.xaml.cs, tambahkan
DeleteSelectedImage
metode .private void DeleteSelectedImage() => Images.Remove(ImageGridView.SelectedItem as ImageFileInfo);
Metode ini hanya menghapus gambar yang dipilih dari
Images
koleksi.
Sekarang jalankan aplikasi dan gunakan tombol untuk menghapus beberapa gambar. Seperti yang Anda lihat, UI diperbarui secara otomatis, berkat pengikatan data dan jenisnya ObservableCollection<T>
.
Catatan
Kode ini hanya menghapus instans ImageFileInfo
dari Images
koleksi di aplikasi yang sedang berjalan. Ini tidak menghapus file gambar dari komputer.
Bagian 3: Menyiapkan penggeser zoom
Di bagian ini, Anda akan membuat pengikatan satu arah dari kontrol di templat data ke penggeser zoom, yang berada di luar templat. Anda juga akan mempelajari bahwa Anda dapat menggunakan pengikatan data dengan banyak properti kontrol, bukan hanya yang paling jelas seperti TextBlock.Text
dan Image.Source
.
Mengikat templat data gambar ke penggeser zoom
Temukan bernama
DataTemplate
ImageGridView_DefaultItemTemplate
dan ganti**Height**
nilaiGrid
danWidth
kontrol di bagian atas templat.Sebelum
<DataTemplate x:Key="ImageGridView_DefaultItemTemplate" x:DataType="local:ImageFileInfo"> <Grid Height="200" Width="200" Margin="{StaticResource LargeItemMargin}">
Setelah
<DataTemplate x:Key="ImageGridView_DefaultItemTemplate" x:DataType="local:ImageFileInfo"> <Grid Height="{Binding Value, ElementName=ZoomSlider}" Width="{Binding Value, ElementName=ZoomSlider}" Margin="{StaticResource LargeItemMargin}">
Apakah Anda melihat bahwa ini adalah Binding
ekspresi, dan bukan x:Bind
ekspresi? Ini adalah cara lama untuk melakukan pengikatan data, dan sebagian besar sudah usang. x:Bind
melakukan hampir semua yang Binding
dilakukan, dan banyak lagi. Namun, saat Anda menggunakan x:Bind
dalam templat data, templat tersebut mengikat ke jenis yang dideklarasikan dalam x:DataType
nilai . Jadi bagaimana Anda mengikat sesuatu dalam templat ke sesuatu di halaman XAML atau di code-behind? Anda harus menggunakan ekspresi gaya Binding
lama.
Binding
ekspresi tidak mengenali x:DataType
nilai, tetapi ekspresi ini Binding
memiliki ElementName
nilai yang bekerja hampir dengan cara yang sama. Ini memberi tahu mesin pengikatan bahwa Nilai Pengikatan adalah pengikatan ke Value
properti elemen yang ditentukan pada halaman (yaitu, elemen dengan x:Name
nilai tersebut). Jika Anda ingin mengikat properti di code-behind, itu akan terlihat seperti {Binding MyCodeBehindProperty, ElementName=page}
di mana page
merujuk ke x:Name
nilai yang ditetapkan dalam Page
elemen di XAML.
Catatan
Secara default, Binding
ekspresi adalah satu arah, yang berarti bahwa ekspresi tersebut akan secara otomatis memperbarui UI saat nilai properti terikat berubah.
Sebaliknya, default untuk x:Bind
adalah satu kali, yang berarti bahwa setiap perubahan pada properti terikat diabaikan. Ini adalah default karena ini adalah opsi performa paling tinggi, dan sebagian besar pengikatannya adalah data statis baca-saja.
Pelajaran di sini adalah bahwa jika Anda menggunakan x:Bind
dengan properti yang dapat mengubah nilainya, pastikan untuk menambahkan Mode=OneWay
atau Mode=TwoWay
. Anda akan melihat contoh ini di bagian berikutnya.
Jalankan aplikasi dan gunakan slider untuk mengubah dimensi templat gambar. Seperti yang Anda lihat, efeknya cukup kuat tanpa membutuhkan banyak kode.
Catatan
Untuk tantangan, coba ikat properti UI lain ke properti penggeser Value
zoom, atau ke penggeser lain yang Anda tambahkan setelah penggeser zoom. Misalnya, Anda dapat mengikat FontSize
properti penggeleksi baru TitleTextBlock
dengan nilai default 24. Pastikan untuk menetapkan nilai minimum dan maksimum yang wajar.
Bagian 4: Meningkatkan pengalaman zoom
Di bagian ini, Anda akan menambahkan properti kustom ItemSize
ke code-behind dan membuat pengikatan satu arah dari templat gambar ke properti baru. Nilai ItemSize
akan diperbarui oleh penggeser zoom dan faktor lain seperti tombol Paskan ke layar dan ukuran jendela, membuat pengalaman yang lebih halus.
Tidak seperti properti kontrol bawaan, properti kustom Anda tidak secara otomatis memperbarui UI, bahkan dengan pengikatan satu arah dan dua arah. Mereka berfungsi dengan baik dengan pengikatan satu kali, tetapi jika Anda ingin perubahan properti Anda benar-benar muncul di antarmuka pengguna Anda, Anda perlu melakukan beberapa pekerjaan.
Buat properti ItemSize sehingga memperbarui UI
Di MainPage.xaml.cs, ubah tanda tangan
MainPage
kelas sehingga mengimplementasikanINotifyPropertyChanged
antarmuka.Sebelum:
public sealed partial class MainPage : Page
Setelah:
public sealed partial class MainPage : Page, INotifyPropertyChanged
Ini menginformasikan sistem pengikatan yang
MainPage
memilikiPropertyChanged
peristiwa (ditambahkan berikutnya) yang dapat didengarkan pengikatan untuk memperbarui UI.PropertyChanged
Tambahkan peristiwa keMainPage
kelas .public event PropertyChangedEventHandler PropertyChanged;
Kejadian ini menyediakan implementasi lengkap yang diperlukan oleh
INotifyPropertyChanged
antarmuka. Namun, agar memiliki efek apa pun, Anda harus secara eksplisit menaikkan peristiwa di properti kustom Anda.ItemSize
Tambahkan properti dan naikkanPropertyChanged
peristiwa di setter-nya.public double ItemSize { get => _itemSize; set { if (_itemSize != value) { _itemSize = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemSize))); } } } private double _itemSize;
Properti
ItemSize
mengekspos nilai bidang privat_itemSize
. Menggunakan bidang backing seperti ini memungkinkan properti untuk memeriksa apakah nilai baru sama dengan nilai lama sebelum memunculkan peristiwa yang berpotensi tidak perluPropertyChanged
.Peristiwa itu sendiri dimunculkan oleh
Invoke
metode . Tanda tanya memeriksa apakahPropertyChanged
peristiwa null - yaitu, apakah ada penanganan aktivitas yang telah ditambahkan. Setiap pengikatan satu arah atau dua arah menambahkan penanganan aktivitas di belakang layar, tetapi jika tidak ada yang mendengarkan, tidak ada lagi yang akan terjadi di sini. Namun, jikaPropertyChanged
tidak null, makaInvoke
dipanggil dengan referensi ke sumber peristiwa (halaman itu sendiri, diwakili olehthis
kata kunci) dan objek event-args yang menunjukkan nama properti. Dengan info ini, pengikatan satu arah atau dua arah keItemSize
properti akan diberi tahu tentang perubahan apa pun sehingga mereka dapat memperbarui UI yang terikat.Di MainPage.xaml, temukan
DataTemplate
namaImageGridView_DefaultItemTemplate
dan gantiHeight
nilaiGrid
danWidth
kontrol di bagian atas templat. (Jika Anda melakukan pengikatan kontrol-ke-kontrol di bagian sebelumnya dari tutorial ini, satu-satunya perubahan adalah menggantiValue
denganItemSize
danZoomSlider
denganpage
. Pastikan untuk melakukan ini untuk danHeight
Width
!)Sebelum
<DataTemplate x:Key="ImageGridView_DefaultItemTemplate" x:DataType="local:ImageFileInfo"> <Grid Height="{Binding Value, ElementName=ZoomSlider}" Width="{Binding Value, ElementName=ZoomSlider}" Margin="{StaticResource LargeItemMargin}">
Setelah
<DataTemplate x:Key="ImageGridView_DefaultItemTemplate" x:DataType="local:ImageFileInfo"> <Grid Height="{Binding ItemSize, ElementName=page}" Width="{Binding ItemSize, ElementName=page}" Margin="{StaticResource LargeItemMargin}">
Sekarang setelah UI dapat merespons ItemSize
perubahan, Anda harus benar-benar membuat beberapa perubahan. Seperti disebutkan sebelumnya, ItemSize
nilai dihitung dari status saat ini dari berbagai kontrol UI, tetapi perhitungan harus dilakukan setiap kali kontrol tersebut berubah status. Untuk melakukan ini, Anda akan menggunakan pengikatan peristiwa sehingga perubahan UI tertentu akan memanggil metode pembantu yang memperbarui ItemSize
.
Memperbarui nilai properti ItemSize
Tambahkan metode ke
DetermineItemSize
MainPage.xaml.cs.private void DetermineItemSize() { if (FitScreenToggle != null && FitScreenToggle.IsOn == true && ImageGridView != null && ZoomSlider != null) { // The 'margins' value represents the total of the margins around the // image in the grid item. 8 from the ItemTemplate root grid + 8 from // the ItemContainerStyle * (Right + Left). If those values change, // this value needs to be updated to match. int margins = (int)this.Resources["LargeItemMarginValue"] * 4; double gridWidth = ImageGridView.ActualWidth - (int)this.Resources["DefaultWindowSidePaddingValue"]; double ItemWidth = ZoomSlider.Value + margins; // We need at least 1 column. int columns = (int)Math.Max(gridWidth / ItemWidth, 1); // Adjust the available grid width to account for margins around each item. double adjustedGridWidth = gridWidth - (columns * margins); ItemSize = (adjustedGridWidth / columns); } else { ItemSize = ZoomSlider.Value; } }
Di MainPage.xaml, navigasikan ke bagian atas file dan tambahkan pengikatan
SizeChanged
peristiwa kePage
elemen .Sebelum:
<Page x:Name="page"
Setelah:
<Page x:Name="page" SizeChanged="{x:Bind DetermineItemSize}"
Temukan bernama
Slider
ZoomSlider
(di bagianPage.Resources
) dan tambahkan pengikatanValueChanged
peristiwa.Sebelum:
<Slider x:Name="ZoomSlider"
Setelah:
<Slider x:Name="ZoomSlider" ValueChanged="{x:Bind DetermineItemSize}"
Temukan yang
ToggleSwitch
bernamaFitScreenToggle
dan tambahkanToggled
pengikatan peristiwa.Sebelum:
<ToggleSwitch x:Name="FitScreenToggle"
Setelah:
<ToggleSwitch x:Name="FitScreenToggle" Toggled="{x:Bind DetermineItemSize}"
Jalankan aplikasi dan gunakan penggeser zoom dan Paskan ke pengalih layar untuk mengubah dimensi templat gambar. Seperti yang Anda lihat, perubahan terbaru memungkinkan pengalaman zoom/ubah ukuran yang lebih halus sambil menjaga kode tetap terorganisir dengan baik.
Catatan
Untuk tantangan, coba tambahkan TextBlock
setelah ZoomSlider
dan ikat Text
properti ke ItemSize
properti . Karena tidak ada dalam templat data, Anda dapat menggunakan x:Bind
alih-alih Binding
seperti pada pengikatan sebelumnya ItemSize
.
Bagian 5: Mengaktifkan pengeditan pengguna
Di sini, Anda akan membuat pengikatan dua arah untuk memungkinkan pengguna memperbarui nilai, termasuk judul gambar, peringkat, dan berbagai efek visual.
Untuk mencapai hal ini, Anda akan memperbarui , yang ada DetailPage
yang menyediakan penampil gambar tunggal, kontrol zoom, dan antarmuka pengguna pengeditan.
Namun, pertama-tama, Anda perlu melampirkan DetailPage
sehingga aplikasi menavigasi ke sana saat pengguna mengklik gambar dalam tampilan galeri.
Lampirkan DetailPage
Di MainPage.xaml, temukan yang
GridView
bernamaImageGridView
. Untuk membuat item dapat diklik, aturIsItemClickEnabled
keTrue
dan tambahkan penangananItemClick
aktivitas.Tip
Jika Anda mengetik perubahan di bawah ini alih-alih menyalin/menempelkan, Anda akan melihat pop-up IntelliSense yang bertuliskan "<Penanganan> Aktivitas Baru". Jika Anda menekan tombol Tab, tombol tersebut akan mengisi nilai dengan nama handler metode default, dan secara otomatis membagi metode yang ditunjukkan pada langkah berikutnya. Anda kemudian dapat menekan F12 untuk menavigasi ke metode di kode belakang.
Sebelum:
<GridView x:Name="ImageGridView">
Setelah:
<GridView x:Name="ImageGridView" IsItemClickEnabled="True" ItemClick="ImageGridView_ItemClick">
Catatan
Kami menggunakan penanganan aktivitas konvensional di sini alih-alih ekspresi x:Bind. Ini karena kita perlu melihat data peristiwa, seperti yang ditunjukkan berikutnya.
Di MainPage.xaml.cs, tambahkan penanganan aktivitas (atau isi, jika Anda menggunakan tip di langkah terakhir).
private void ImageGridView_ItemClick(object sender, ItemClickEventArgs e) { this.Frame.Navigate(typeof(DetailPage), e.ClickedItem); }
Metode ini hanya menavigasi ke halaman detail, meneruskan item yang diklik, yang merupakan objek yang
ImageFileInfo
digunakan oleh DetailPage.OnNavigatedTo untuk menginisialisasi halaman. Anda tidak perlu menerapkan metode itu dalam tutorial ini, tetapi Anda dapat melihat untuk melihat apa yang dilakukannya.(Opsional) Hapus atau komentari kontrol apa pun yang Anda tambahkan di play-point sebelumnya yang berfungsi dengan gambar yang saat ini dipilih. Menjaga mereka tidak akan menyakiti apa pun, tetapi sekarang jauh lebih sulit untuk memilih gambar tanpa menavigasi ke halaman detail.
Sekarang setelah Anda menghubungkan dua halaman, jalankan aplikasi dan lihat-lihat. Semuanya berfungsi kecuali kontrol pada panel pengeditan, yang tidak merespons saat Anda mencoba mengubah nilai.
Seperti yang Anda lihat, kotak teks judul memang menampilkan judul dan memungkinkan Anda mengetik perubahan. Anda harus mengubah fokus ke kontrol lain untuk menerapkan perubahan, tetapi judul di sudut kiri atas layar belum diperbarui.
Semua kontrol sudah terikat menggunakan ekspresi biasa x:Bind
yang kita bahas di Bagian 1. Jika Anda ingat, ini berarti semuanya adalah pengikatan satu kali, yang menjelaskan mengapa perubahan pada nilai tidak terdaftar. Untuk memperbaiki ini, yang harus kita lakukan adalah mengubahnya menjadi pengikatan dua arah.
Membuat kontrol pengeditan interaktif
Di DetailPage.xaml, temukan
TextBlock
titleTextBlock dan kontrol RatingControl setelahnya, dan perbarui ekspresinyax:Bind
untuk menyertakan Mode=TwoWay.Sebelum:
<TextBlock x:Name="TitleTextBlock" Text="{x:Bind item.ImageTitle}" ... > <muxc:RatingControl Value="{x:Bind item.ImageRating}" ... >
Setelah:
<TextBlock x:Name="TitleTextBlock" Text="{x:Bind item.ImageTitle, Mode=TwoWay}" ... > <muxc:RatingControl Value="{x:Bind item.ImageRating, Mode=TwoWay}" ... >
Lakukan hal yang sama untuk semua slider efek yang datang setelah kontrol peringkat.
<Slider Header="Exposure" ... Value="{x:Bind item.Exposure, Mode=TwoWay}" ... <Slider Header="Temperature" ... Value="{x:Bind item.Temperature, Mode=TwoWay}" ... <Slider Header="Tint" ... Value="{x:Bind item.Tint, Mode=TwoWay}" ... <Slider Header="Contrast" ... Value="{x:Bind item.Contrast, Mode=TwoWay}" ... <Slider Header="Saturation" ... Value="{x:Bind item.Saturation, Mode=TwoWay}" ... <Slider Header="Blur" ... Value="{x:Bind item.Blur, Mode=TwoWay}" ...
Mode dua arah, seperti yang mungkin Anda harapkan, berarti bahwa data bergerak ke kedua arah setiap kali ada perubahan di kedua sisi.
Seperti pengikatan satu arah yang dibahas sebelumnya, pengikatan dua arah ini sekarang akan memperbarui UI setiap kali properti terikat berubah, berkat INotifyPropertyChanged
implementasi di ImageFileInfo
kelas . Namun, dengan pengikatan dua arah, nilai juga akan berpindah dari UI ke properti terikat setiap kali pengguna berinteraksi dengan kontrol. Tidak ada lagi yang diperlukan di sisi XAML.
Jalankan aplikasi dan coba kontrol pengeditan. Seperti yang Anda lihat, saat Anda membuat perubahan, sekarang mempengaruhi nilai gambar, dan perubahan tersebut bertahan saat Anda menavigasi kembali ke halaman utama.
Bagian 6: Memformat nilai melalui pengikatan fungsi
Satu masalah terakhir tetap ada. Saat Anda memindahkan penggeser efek, label di sampingnya masih tidak berubah.
Bagian terakhir dalam tutorial ini adalah menambahkan pengikatan yang memformat nilai slider untuk ditampilkan.
Mengikat label effect-slider dan memformat nilai untuk tampilan
TextBlock
Temukan setelahExposure
slider dan gantiText
nilai dengan ekspresi pengikatan yang diperlihatkan di sini.Sebelum:
<Slider Header="Exposure" ... /> <TextBlock ... Text="0.00" />
Setelah:
<Slider Header="Exposure" ... /> <TextBlock ... Text="{x:Bind item.Exposure.ToString('N', culture), Mode=OneWay}" />
Ini disebut pengikatan fungsi karena Anda mengikat ke nilai pengembalian metode. Metode harus dapat diakses melalui kode halaman di belakang atau
x:DataType
jenis jika Anda berada dalam templat data. Dalam hal ini, metode ini adalah metode .NETToString
yang akrab, yang diakses melalui properti item halaman, dan kemudian melaluiExposure
properti item. (Ini menggambarkan bagaimana Anda dapat mengikat metode dan properti yang sangat bersarang dalam rantai koneksi.)Pengikatan fungsi adalah cara ideal untuk memformat nilai untuk ditampilkan karena Anda dapat meneruskan sumber pengikatan lain sebagai argumen metode, dan ekspresi pengikatan akan mendengarkan perubahan pada nilai tersebut seperti yang diharapkan dengan mode satu arah. Dalam contoh ini, argumen budaya adalah referensi ke bidang yang tidak berubah yang diimplementasikan dalam code-behind, tetapi bisa saja dengan mudah menjadi properti yang menimbulkan
PropertyChanged
peristiwa. Dalam hal ini, setiap perubahan pada nilai properti akan menyebabkanx:Bind
ekspresi memanggilToString
dengan nilai baru lalu memperbarui UI dengan hasilnya.Lakukan hal yang sama untuk
TextBlock
label yang memberi label slider efek lainnya.<Slider Header="Temperature" ... /> <TextBlock ... Text="{x:Bind item.Temperature.ToString('N', culture), Mode=OneWay}" /> <Slider Header="Tint" ... /> <TextBlock ... Text="{x:Bind item.Tint.ToString('N', culture), Mode=OneWay}" /> <Slider Header="Contrast" ... /> <TextBlock ... Text="{x:Bind item.Contrast.ToString('N', culture), Mode=OneWay}" /> <Slider Header="Saturation" ... /> <TextBlock ... Text="{x:Bind item.Saturation.ToString('N', culture), Mode=OneWay}" /> <Slider Header="Blur" ... /> <TextBlock ... Text="{x:Bind item.Blur.ToString('N', culture), Mode=OneWay}" />
Sekarang saat Anda menjalankan aplikasi, semuanya berfungsi, termasuk label penggeser.
Kesimpulan
Tutorial ini telah memberi Anda rasa pengikatan data dan menunjukkan beberapa fungsionalitas yang tersedia. Satu kata hati-hati sebelum kami membungkus: tidak semuanya dapat diikat, dan kadang-kadang nilai yang Anda coba sambungkan tidak kompatibel dengan properti yang anda coba ikat. Ada banyak fleksibilitas dalam pengikatan, tetapi tidak akan berfungsi dalam setiap situasi.
Salah satu contoh masalah yang tidak diatasi dengan pengikatan adalah ketika kontrol tidak memiliki properti yang cocok untuk diikat, seperti halnya fitur zoom halaman detail. Penggeser zoom ini perlu berinteraksi dengan ScrollViewer
yang menampilkan gambar, tetapi ScrollViewer
hanya dapat diperbarui melalui metodenya ChangeView
. Dalam hal ini, kami menggunakan penanganan aktivitas konvensional untuk menjaga ScrollViewer
penggeser zoom dan tetap sinkron; lihat ZoomSlider_ValueChanged
metode dan MainImageScroll_ViewChanged
untuk DetailPage
detailnya.
Meskipun demikian, pengikatan adalah cara yang kuat dan fleksibel untuk menyederhanakan kode Anda dan menjaga logika UI Anda terpisah dari logika data Anda. Ini akan membuatnya jauh lebih mudah bagi Anda untuk menyesuaikan salah satu sisi pembagian ini sambil mengurangi risiko memperkenalkan bug di sisi lain.
Salah satu contoh UI dan pemisahan data adalah dengan ImageFileInfo.ImageTitle
properti . Properti ini (dan ImageRating
properti) sedikit berbeda dari ItemSize
properti yang Anda buat di Bagian 4 karena nilai disimpan dalam metadata file (diekspos melalui ImageProperties
jenis) alih-alih di bidang. Selain itu, ImageTitle
mengembalikan ImageName
nilai (diatur ke nama file) jika tidak ada judul dalam metadata file.
public string ImageTitle
{
get => String.IsNullOrEmpty(ImageProperties.Title) ? ImageName : ImageProperties.Title;
set
{
if (ImageProperties.Title != value)
{
ImageProperties.Title = value;
var ignoreResult = ImageProperties.SavePropertiesAsync();
OnPropertyChanged();
}
}
}
Seperti yang Anda lihat, setter memperbarui ImageProperties.Title
properti lalu memanggil SavePropertiesAsync
untuk menulis nilai baru ke file. (Ini adalah metode asinkron, tetapi kami tidak dapat menggunakan await
kata kunci dalam properti - dan Anda tidak ingin karena getter dan setter properti harus segera selesai. Jadi sebagai gantinya, Anda akan memanggil metode dan mengabaikan objek yang Task
dikembalikannya.)
Melaju lebih jauh
Sekarang setelah Anda menyelesaikan lab ini, Anda memiliki cukup pengetahuan yang mengikat mengatasi masalah Anda sendiri.
Seperti yang mungkin telah Anda perhatikan, jika Anda mengubah tingkat pembesaran tampilan pada halaman detail, tingkat perbesar tampilan akan diatur ulang secara otomatis saat Anda menavigasi mundur, lalu pilih gambar yang sama lagi. Dapatkah Anda mencari tahu cara mempertahankan dan memulihkan tingkat zoom untuk setiap gambar satu per satu? Semoga sukses!
Anda harus memiliki semua info yang Anda butuhkan dalam tutorial ini, tetapi jika Anda membutuhkan lebih banyak panduan, dokumen pengikatan data hanya dengan sekali klik. Mulai di sini:
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk