Prevent LongListMultiSelector from "auto scrolling" when inserting items at the beginning

417 views Asked by At

I am using a LongListMultiSelector to show messages. Newest messages are at the botton - like in a messenger. I know have a button in the ListHeaderTemplate, that allows me to load earlier messages and insert them at the top at the list (ObservableCollection.Insert(0, item);).

Inserting works, but it looks like that the list scrolls automatically to the last inserted item - it actually does not scroll, but it feels like it scrolls, because after the insert, the new item is displayed, but i rather looking for a solution that keeps the item visible that was the first before the new items where inserted and that i have to do another vertical scroll to the new top to reach the list header again.

Any clues?

EDIT 1

consider, oldFirstItem is the current first item, then I insert a new item in front of the item. now the new item, becomes the first item, and since the scroll position does not change, the new item is visible: it feels like the list scrolls to the new inserted item, but it only pushed items 1 to n down. what i want is, that it pushes all new items up - into the area that the user does not see - and oldFirstItem at the top of the items that are visble. using ScrollTo makes that list jump.

EDIT 2 I added a picture trying to show what I want to achieve. The area above the red line is not visible.enter image description here

4

There are 4 answers

3
Jakub Krampl On

If I see... you can use ScrollTo method.

yourLongListMultiSelector.ScrollTo(yourNewInsertedItem);
2
frno On

To get you going, I tried something but could not get it a 100%

Here is a working basic page template which in fact does what you require with messages

<phone:PhoneApplicationPage >

<ScrollViewer x:Name="Scroll" VerticalAlignment="Bottom" Height="500" ScrollViewer.VerticalScrollBarVisibility="Disabled">
    <StackPanel VerticalAlignment="Bottom" >
        <toolkit:LongListMultiSelector x:Name="DataList" ItemsSource="{Binding}" ScrollViewer.VerticalScrollBarVisibility="Disabled" VerticalAlignment="Bottom"
        VirtualizingStackPanel.VirtualizationMode="Recycling"></toolkit:LongListMultiSelector>
    </StackPanel>
</ScrollViewer>

</phone:PhoneApplicationPage>

This keeps new messages down, pulling the list up. The scrolling is now disabled. You can easily enclose ScrollViewer in grid and add the button above (like in your picture)

Now the code that would go into the button click

    Scroll.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
    Scroll.ScrollToVerticalOffset(DataList.ActualHeight);

Unfortunately this scrolls the list up BUT if you trigger the second line of code again for example via button click, ScrollToVerticalOffset works. So for some reason ScrollToVerticalOffset is not working right away-after changing VerticalScrollBarVisibility. If you can get this last part figured out, I believe your question would be solved

2
David To On

The thing that prevents your desired effect is the ListHeader control is at top when you insert item at top. You can do some tricky code to bypass it:

var temp = MyLongListMultiSelector.ListHeader; //also works with ListHeaderTemplate
MyLongListMultiSelector.ListHeader = null;
MyObservableCollection.Insert(0, item);    
MyLongListMultiSelector.ListHeader = temp;

Or you can make a fake header item and handle the add top event like:

MyLongListMultiSelector.Remove(fakeHeaderItem);
MyObservableCollection.Insert(0, item); 
MyObservableCollection.Insert(0, fakeHeaderItem); 
0
techloverr On

you can easily achieve this via adding new items to top of the observable collection

obsData.Insert(0,newItem)

Reference