Silverlight tips’n’tricks: bindanje na ListBox
Upravo sam potrošio 4 sata na traženje buga u jednoj Silverlight aplikaciji koju trenutno radim. Pošto sam na kraju ipak uspio pronaći u kojem zecu leži grm, i kako sam siguran da će netko osim mene doći do istog problema jer se radi o često korištenom obrascu ravzijanja, bilo bi dobro podjeliti ovaj mali tips&tricks koji može spasiti par sati uzaludnog traženja internetom (koje mene nije dovelo do rješenja ipak).
Bug izgleda ovako:
ovo je jedna kontrola u razvoju, i njezin zadatak je da ispisuje njezin status, dali je minimizirana i maksimizirana. To ispisuje ListBoxu, koji radi na sljedeći načim:
- na UserControl je postavljena DataContext klasa (MVVM pattern)
- ta ViewModel klasa ima jednu listu stringova definiranu kao ObservableCollection<string> property
- pomoći Binding sposobnosti, ažurirane vrijednosti u tom propertyu se automatski osvježavaju u ListBoxu, odnosno ispisuje lista tih stringova.
Primjer XAML deklaracije ListBoxa:
Bug je desi kada dodate više od 3-4 stringova u listu, i pokušate selektirati jednog, u ListBoxu će ostati selektirani, ili nasumično se selektirati više stavaka, kao što je prikazano u screenshotu (ListBox nema omogućeno selektiranje više od jedne stavke).. [more]
Ono što je zanimljivo, bug se ne pojavljuje ako NE koristite binding, nego napravite običnu List<string> i pridodjelite ju ItemsSource propertyu od ListBox-a!
Razlog ovoj pojavi mi je i dalje ostao nepoznat, pa ga mogu pripisati jedino mamurnom programeru u Microsoftovom razvojmom timu, nedostatku unit testiva, ili zbog urote Adobe/Apple inflitriranih agenata u Microsoftovim redovima. Ja bi se kladio na ovo zadnje.
Rješenje je jednostavno: na ListBox se mora bindati objekt, a ne string! Ha! Jednostavno rješenje, zar ne? A koje sve solucije sam pronašao na internetu, to je strašno, hackove koje ulaze u tamne dubine Silverlighta, gdje još programerova ruka nije kročila.
Naša ViewModel klasa sada nema property ObservableCollection<string>, nego ObservableCollection<StateItem>, gdje je StateItem klasa koja ima jedan string property StateName.