tags:

views:

699

answers:

4

I have a WPF ListBox bound to an observable collection. When things are added to the collection, the listbox scroll position shifts by the size of the added entries. I'd like to be able to preserve the scroll position, so that even as things are added to the list, the items currently in view don't move. Is there a way to accomplish this?

A: 

I'm not sure if there's an override for that, but I doubt it.

When in doubt use manual binding? :-} Seriously, the default binding behavior will be - well - default, so if you need special behavior manual binding is a better choice. With manual binding you can save the scroll position and reset it after you've added the items.

Rick Strahl
Which leads to an obvious question - how do I determine the current scroll position?
Kevin Dente
+2  A: 

Create a CollectionView. Try this:

    private ObservableCollection<int> m_Values;
    private CollectionView m_View;

    private void Bind()
    {
        m_Values = new ObservableCollection<int>();
        m_View = new CollectionView(m_Values);
        MyListBox.ItemsSource = m_View;
    }

    private void MyListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        Debug.WriteLine(m_View.CurrentItem);
        Debug.WriteLine(m_View.CurrentPosition);
    }
Kai Wang
Please explain further. This answer does not seem to solve the problem - it just reports the current item and position. I am having the same problem, using a ListBox with a ItemsPanel set to a VirtualizingStackPanel. The problem as I see it is that the list box items continue to move as new items are added to the Observable collection. While it is possible to move items back to where they were after a new item is added (e.g., by using SelectedIndex), this creates a jerky motion. What is needed is a way to prevent the scroll position from changing in the first place as new items are added.
CyberMonk
A: 

Do you control when things are added? I mean do you have one or two defined points where data gets changed? If so, one easy solution (perhaps not elegant) would be so have a local int variable to hold the current ListBox.SelectedIndex. Just before data changes, save the selectedIndex to this variable and after data is added, set the SelectedIndex of the listBox to the value of this variable.

Gustavo Cavalcanti
A: 

Firstly find the current position by ListBox.SelectedIndex and then use ListBox.ScrollIntoView(/* Current Index */). Even if the new items are added in list your current position and view will be the same.

Rushin