Bagaimana cara saya menggunakan RelativeSource
binding WPF dan apa perbedaan kasus penggunaan?
.net
wpf
xaml
data-binding
relativesource
David Schmitt
sumber
sumber
AncestorType
.FindAncestor
, sebelumnyaAncestorType
, saya mendapatkan kesalahan berikut: "RelativeSource tidak dalam mode FindAncestor". (Dalam VS2013, versi Komunitas){Binding Path=DataContext.SomeProperty, RelativeSource=...
. Ini agak tak terduga bagi saya sebagai pemula ketika saya mencoba untuk mengikat DataContext orangtua dalam DataTemplate.Atribut default
RelativeSource
adalahMode
properti. Satu set lengkap nilai valid diberikan di sini ( dari MSDN ):PreviousData Memungkinkan Anda untuk mengikat item data sebelumnya (bukan kontrol yang berisi item data) dalam daftar item data yang sedang ditampilkan.
TemplatedParent Mengacu pada elemen yang menjadi templat (di mana elemen terikat data) diterapkan. Ini mirip dengan pengaturan TemplateBindingExtension dan hanya berlaku jika Binding ada di dalam templat.
Diri Mengacu pada elemen yang Anda atur pengikatannya dan memungkinkan Anda untuk mengikat satu properti elemen tersebut ke properti lain pada elemen yang sama.
FindAncestor Mengacu pada leluhur dalam rantai induk elemen terikat data. Anda dapat menggunakan ini untuk mengikat leluhur dari jenis tertentu atau subkelasnya. Ini adalah mode yang Anda gunakan jika Anda ingin menentukan AncestorType dan / atau AncestorLevel.
sumber
Berikut adalah penjelasan yang lebih visual dalam konteks arsitektur MVVM:
sumber
{Binding Message}
(sedikit lebih sederhana ...)Path=DataContext.Message
agar ikatannya bekerja. Ini masuk akal, mengingat bahwa Anda dapat melakukan binding relatif dengan lebar / tinggi / dll. sebuah kontrol.Bechir Bejaoui memaparkan kasus penggunaan RelativeSources di WPF dalam artikelnya di sini :
sumber
ListView
. Orang tua memiliki 2ListView
level lebih di bawahnya. Ini membantu saya mencegah melewati data ke masing-masing vm berikutnya masing-masingListView
'sDataTemplate
Dalam WPF
RelativeSource
binding memperlihatkan tigaproperties
untuk mengatur:1. Mode: Ini adalah
enum
yang bisa memiliki empat nilai:2. AncestorType: ketika mode
FindAncestor
kemudian menentukan tipe leluhur apa3. AncestorLevel: ketika mode
FindAncestor
maka tingkat leluhur apa (jika ada dua tipe induk yang samavisual tree
)Berikut ini tautan referensi .
sumber
Jangan lupa TemplatedParent:
atau
sumber
Patut dicatat bahwa bagi mereka yang tersandung pemikiran Silverlight ini:
Silverlight hanya menawarkan pengurangan sebagian dari perintah-perintah ini
sumber
Saya membuat perpustakaan untuk menyederhanakan sintaks WPF yang mengikat termasuk membuatnya lebih mudah untuk menggunakan RelativeSource. Berikut ini beberapa contohnya. Sebelum:
Setelah:
Berikut adalah contoh bagaimana metode pengikatan disederhanakan. Sebelum:
Setelah:
Anda dapat menemukan perpustakaan di sini: http://www.simplygoodcode.com/2012/08/simpler-wpf-binding.html
Catatan dalam contoh 'SEBELUM' yang saya gunakan untuk metode yang mengikat kode itu sudah dioptimalkan dengan menggunakan
RelayCommand
yang terakhir saya periksa bukan bagian asli WPF. Tanpa itu contoh 'SEBELUM' akan lebih lama.sumber
Beberapa potongan berguna:
Berikut cara melakukannya sebagian besar dalam kode:
Saya sebagian besar menyalin ini dari Binding Relative Source dalam kode Behind .
Juga, halaman MSDN cukup bagus sejauh contoh: RelativeSource Class
sumber
Saya baru saja memposting solusi lain untuk mengakses DataContext dari elemen induk di Silverlight yang berfungsi untuk saya. Itu menggunakan
Binding ElementName
.sumber
Saya tidak membaca setiap jawaban, tetapi saya hanya ingin menambahkan informasi ini dalam kasus pengikatan perintah sumber relatif tombol.
Saat Anda menggunakan sumber relatif dengan
Mode=FindAncestor
, ikatan harus seperti:Jika Anda tidak menambahkan DataContext di jalur Anda, pada saat eksekusi tidak dapat mengambil properti.
sumber
Ini adalah contoh penggunaan pola ini yang bekerja untuk saya di datagrid kosong.
sumber
Jika elemen bukan bagian dari pohon visual, maka RelativeSource tidak akan pernah berfungsi.
Dalam hal ini, Anda perlu mencoba teknik yang berbeda, dipelopori oleh Thomas Levesque.
Dia memiliki solusi di blognya di bawah [WPF] Cara mengikat data ketika DataContext tidak diwarisi . Dan itu bekerja dengan sangat brilian!
Jika blognya sedang down, Lampiran A berisi salinan mirror dari artikelnya .
Tolong jangan berkomentar di sini, silakan komentar langsung di posting blog-nya .
Lampiran A: Cermin posting blog
Properti DataContext di WPF sangat berguna, karena ia secara otomatis diwarisi oleh semua anak dari elemen tempat Anda menetapkannya; karena itu Anda tidak perlu mengaturnya lagi pada setiap elemen yang ingin Anda ikat. Namun, dalam beberapa kasus, DataContext tidak dapat diakses: itu terjadi untuk elemen yang bukan bagian dari pohon visual atau logis. Maka bisa sangat sulit untuk mengikat properti pada elemen-elemen itu ...
Mari kita ilustrasikan dengan contoh sederhana: kami ingin menampilkan daftar produk di DataGrid. Di kisi, kami ingin dapat menampilkan atau menyembunyikan kolom Harga, berdasarkan nilai properti ShowPrice yang diekspos oleh ViewModel. Pendekatan yang jelas adalah untuk mengikat Visibilitas kolom ke properti ShowPrice:
Sayangnya, mengubah nilai ShowPrice tidak berpengaruh, dan kolom selalu terlihat ... mengapa? Jika kita melihat jendela Output di Visual Studio, kita perhatikan baris berikut:
Kita dapat mencoba mengubah ikatan untuk mendapatkan hasil yang diinginkan, misalnya dengan mengatur RelativeSource ke DataGrid itu sendiri:
Atau kita dapat menambahkan Kotak Centang terikat ke ShowPrice, dan mencoba mengikat visibilitas kolom ke properti IsChecked dengan menentukan nama elemen:
Tapi tidak satu pun dari solusi ini yang berhasil, kami selalu mendapatkan hasil yang sama ...
Pada titik ini, tampaknya satu-satunya pendekatan yang dapat dilakukan adalah mengubah visibilitas kolom dalam kode-belakang, yang biasanya kita lebih suka hindari ketika menggunakan pola MVVM ... Tapi saya tidak akan menyerah begitu cepat, setidaknya tidak sementara ada opsi lain untuk dipertimbangkan 😉
Solusi untuk masalah kita sebenarnya cukup sederhana, dan memanfaatkan kelas Freezable. Tujuan utama kelas ini adalah untuk mendefinisikan objek yang memiliki keadaan yang dapat dimodifikasi dan hanya-baca, tetapi fitur yang menarik dalam kasus kami adalah bahwa objek Freezable dapat mewarisi DataContext bahkan ketika mereka tidak berada di pohon visual atau logis. Saya tidak tahu mekanisme pasti yang memungkinkan perilaku ini, tetapi kita akan memanfaatkannya untuk membuat pekerjaan mengikat kita ...
Idenya adalah untuk membuat kelas (saya menyebutnya BindingProxy untuk alasan yang harus segera menjadi jelas) yang mewarisi Freezable dan mendeklarasikan properti ketergantungan data:
Kami kemudian dapat mendeklarasikan instance kelas ini di sumber daya DataGrid, dan mengikat properti Data ke DataContext saat ini:
Langkah terakhir adalah menentukan objek BindingProxy ini (mudah diakses dengan StaticResource) sebagai Sumber untuk pengikatan:
Perhatikan bahwa jalur pengikatan telah diawali dengan "Data", karena jalur sekarang relatif terhadap objek BindingProxy.
Pengikatan sekarang berfungsi dengan benar, dan kolom ditampilkan dengan benar atau disembunyikan berdasarkan properti ShowPrice.
sumber