Saya memiliki ListBox
yang mengikat ke koleksi anak di ViewModel. Item listbox ditata dalam template data berdasarkan properti pada ViewModel induk:
<Style x:Key="curveSpeedNonConstantParameterCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified,
ElementName=someParentElementWithReferenceToRootDataContext}"
Value="True">
<Setter Property="Control.Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Saya mendapatkan kesalahan keluaran berikut:
System.Windows.Data Error: 39 : BindingExpression path error:
'CurveSpeedMustBeSpecified' property not found on
'object' ''BindingListCollectionView' (HashCode=20467555)'.
BindingExpression:Path=DataContext.CurveSpeedMustBeSpecified;
DataItem='Grid' (Name='nonConstantCurveParametersGrid');
target element is 'TextBox' (Name='');
target property is 'NoTarget' (type 'Object')
Jadi jika saya mengubah ekspresi binding agar "Path=DataContext.CurrentItem.CurveSpeedMustBeSpecified"
berfungsi, tetapi hanya selama konteks data dari kontrol pengguna induk adalah a BindingListCollectionView
. Ini tidak dapat diterima karena kontrol pengguna lainnya mengikat properti CurrentItem
di BindingList
secara otomatis.
Bagaimana cara menentukan ekspresi binding di dalam gaya agar berfungsi terlepas dari konteks data induk menjadi tampilan koleksi atau item tunggal?
Anda dapat menggunakan
RelativeSource
untuk menemukan elemen induk, seperti ini -Lihat pertanyaan SO ini untuk lebih jelasnya
RelativeSource
.sumber
Mode=FindAncestor
agar berfungsi, tetapi ini berfungsi dan jauh lebih baik dalam skenario MVVM karena menghindari kontrol penamaan.Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:YourParentElementType}}}"
RelativeSource vs. ElementName
Kedua pendekatan ini dapat mencapai hasil yang sama,
RelativeSrouce
Metode ini mencari kontrol dari jendela tipe (dalam contoh ini) di pohon visual dan ketika menemukannya Anda pada dasarnya dapat mengaksesnya
DataContext
menggunakanPath=DataContext....
. Kelebihan dari metode ini adalah Anda tidak perlu terikat dengan sebuah nama dan ini agak dinamis, namun, perubahan yang dibuat pada pohon visual Anda dapat memengaruhi metode ini dan mungkin merusaknya.ElementName
Metode ini mengacu pada statis padat
Name
sehingga selama lingkup Anda dapat melihatnya, Anda baik-baik saja. Anda harus berpegang pada konvensi penamaan Anda untuk tidak merusak metode ini tentu saja Pendekatannya sederhana dan yang Anda butuhkan hanyalah menentukan aName="..."
untuk Window / UserControl Anda.Meskipun ketiga jenis (
RelativeSource, Source, ElementName
) mampu melakukan hal yang sama, namun menurut artikel MSDN berikut, masing-masing sebaiknya digunakan di bidang keahliannya masing-masing.Cara: Tentukan Sumber Binding
Temukan deskripsi singkat masing-masing ditambah tautan ke detail lebih lanjut di tabel di bagian bawah halaman.
sumber
Saya sedang mencari cara melakukan sesuatu yang serupa di WPF dan saya mendapatkan solusi ini:
Saya harap ini berhasil untuk orang lain. Saya memiliki konteks data yang diatur secara otomatis ke ItemsControls, dan konteks data ini memiliki dua properti:
MyItems
-yang merupakan kumpulan-, dan satu perintah 'CustomCommand'. KarenaItemTemplate
menggunakan aDataTemplate
, makaDataContext
level atas tidak dapat langsung diakses. Kemudian solusi untuk mendapatkan DC induk adalah menggunakan jalur relatif dan menyaring berdasarkanItemsControl
jenis.sumber
masalahnya adalah bahwa DataTemplate bukan bagian dari elemen yang diterapkan padanya.
ini berarti jika Anda mengikat ke templat Anda mengikat sesuatu yang tidak memiliki konteks.
Namun jika Anda meletakkan elemen di dalam template maka ketika elemen itu diterapkan ke induknya, ia mendapatkan konteks dan binding kemudian berfungsi
jadi ini tidak akan berhasil
tapi ini bekerja dengan sempurna
karena setelah templat data diterapkan, kotak grup ditempatkan di induk dan akan memiliki akses ke Konteksnya
jadi yang harus Anda lakukan adalah menghapus gaya dari template dan memindahkannya ke elemen di template
perhatikan bahwa konteks untuk itemscontrol adalah item bukan kontrol yaitu ComboBoxItem untuk ComboBox bukan ComboBox itu sendiri dalam hal ini Anda harus menggunakan kontrol ItemContainerStyle sebagai gantinya
sumber
Ya, Anda bisa mengatasinya dengan menggunakan
ElementName=Something
saran Juve.TAPI!
Jika elemen anak (di mana Anda menggunakan jenis pengikatan ini) adalah kontrol pengguna yang menggunakan nama elemen yang sama seperti yang Anda tentukan di kontrol induk, maka pengikatan menuju ke objek yang salah !!
Saya tahu posting ini bukanlah solusi tetapi saya pikir semua orang yang menggunakan ElementName dalam pengikatan harus tahu ini, karena ini kemungkinan bug runtime.
sumber