I have a ItemsControl
which displays its items in a ScrollViewer
, and does virtualisation. I am trying to scroll that ScrollViewer
to an (offscreen, hence virtualised) item it contains. However, since the item is virtualised, it doesn't really exist on the screen and has no position (IIUC).
I have tried BringIntoView
on the child element, but it doesn't scroll into view. I have also tried manually doing it with TransformToAncestor
, TransformBounds
and ScrollToVerticalOffset
, but TransformToAncestor
never returns (I guess also because of the virtualisation, because it has no position, but I have no proof of that) and code after it never executes.
Is it possible to scroll to an item with a virtualising ItemsControl
? If so, how?
I know I'm pretty late to the party but hopefully this may help someone else coming along looking for the solution...
... and my XAML is setup like this...
Using @AaronCook example, Created a behavior that works for my VirtualizingItemsControl. Here is the code for that:
and usage is:
Helpful for those who like Behaviors and clean XAML, no code-behind.
Poking around in the .NET source code leads me to recommend you the use of a
ListBox
and itsScrollIntoView
method. The implementation of this method relies on a fewinternal
methods likeVirtualizingPanel.BringIndexIntoView
which forces the creation of the item at that index and scrolls to it. The fact that many of those mechanism are internal means that if you try to do this on your own you're gonna have a bad time.(To make the selection this brings with it invisible you can retemplate the
ListBoxItems
)I've been looking at getting a ItemsControl with a VirtualizingStackPanel to scroll to an item for a while now, and kept finding the "use a ListBox" answer. I didn't want to, so I found a way to do it. First you need to setup a control template for your ItemsControl that has a ScrollViewer in it (which you probably already have if you're using an items control). My basic template looks like the following (contained in a handy style for the ItemsControl)
So I've basically got a border with a scroll viewer thats going to contain my content.
My ItemsControl is defined with:
Ok now for the fun part. I've created a extension method to attach to any ItemsControl to get it to scroll to the given item:
So with the extension method in place you would use it just like ListBox's companion method:
Works great!
Note that you can also call sv.ScrollToEnd() and the other usual scrolling methods to get around your items.
I know this is an old thread, but in case someone else (like me) comes across it, I figured it would be worth an updated answer that I just discovered.
As of .NET Framework 4.5,
VirtualizingPanel
has a publicBringIndexIntoViewPublic
method which works like a charm, including with pixel based scrolling. You'll have to either sub-class yourItemsControl
, or use theVisualTreeHelper
to find its childVirtualizingPanel
, but either way it's now very easy to force yourItemsControl
to scroll precisely to a particular item/index.