Navigace v ListBoxu pomocí TreeView
Snad každého nadšence a vývojáře potěší, když se o technologii, kterou si zvolil začne zajímat větší okruh lidí. Jednak má možnost svoje případné problémy s kým řešit a druhak ví, že to asi není tak úplně slepá cesta, kterou se vydal.
A tak i mě potěšilo, hned dvakrát, že se poslední dobou začali i na českých komunitních fórech objevovat čím dál častěji otázky týkající se WPF a případně Silverlightu.
Jedna taková, poměrně záludná, byla položena na serveru builder.cz a to WPF synchronizace TreeView a ItemsControl, kde se David dotazoval jakým způsobem provést navigaci v ListBoxu, který používá vlastní DataTemplate přes ItemTemplateSelector, pomocí TreeView. TreeView v tomto případě bylo použito z toho důvodu, že zdroj dat byl hierarchický a tomu odpovídalo i vykreslování v navigovaném ListBoxu.
Na první pohled by to nemělo být nic složitého. David však přiložil příklad, který vše jasně demonstroval (mimochodem, takováto snaha získat odpověď se docela vymyká z tamních standardů). Narychlo jsem tak zkusil několik pokusů, které však ke správnému výsledku nevedly.
V noci jsem pak měl chvíli čas a tak jsem se k problému vrátil a pokusil se jej dořešit do zdárného konce. Co mě napadlo hned jako první, už při prvním pokusu, že je využívána virtualizace pro ListBox a tak nedojde k vygenerování všech prvků, na které je následně navěšena attached property.
Tuto skutečnost jsem si ověřil tedy jako první a skutečně tomu tak bylo. ListBox od verze .NET 3.5 SP1 používá jako výchozí panel pro vykreslování prvků VirtualizingStackPanel. Což je samozřejmě na jednu stranu chválihodné, na druhou to zapříčinilo výše popisovaný problém.
Možným řešením je tak vypnout tuto virtualizaci a nechat si vykreslit všechny prvky pomocí nastavení attached vlastnosti VirtualizingStackPanel.IsVirtualizing="False". Tím dojde nejen k vykreslení všech prvků ihned, ale zároveň se nastaví i attached property, která zajistí přesun vybraného prvku do viditelné části ListBoxu pomocí volání metody BringIntoView.
Úvaha nad možným řešením
Když jsem dále přemýšlel, jak by se daný problém dal řešit, napadlo mě hned několik možných řešení. Ani jedno jsem nerealizoval a je to tedy skutečně jen úvaha, která nemusí být realizovatelná.
Ona úvaha spočívá ve využití rozhraní IScrollInfo, kterým ListBox disponuje a pomocí něhož se dá nastavit – odskrolovat – na pozici, kterou potřebujeme. Pokud by tedy výška prvků byla známá, tak by nemuselo být velkým problémem zjistit potřebnou pozici vybraného prvku a tuto nastavit přes IScrollInfo. Tím by se dalo použít i nadále možností virtualizace prvků v ListBoxu.
Je to jen námět a pokud jej David nebo kdokoliv jiný úspěšně nebo i neúspěšně realizuje, budu rád, pokud se o to podělí v komentářích.
Komentáře