简体   繁体   English

在开头插入项目时,防止LongListMultiSelector“自动滚动”

[英]Prevent LongListMultiSelector from “auto scrolling” when inserting items at the beginning

I am using a LongListMultiSelector to show messages. 我正在使用LongListMultiSelector显示消息。 Newest messages are at the botton - like in a messenger. 最新消息位于botton中,就像在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); ). 我知道ListHeaderTemplate中有一个按钮,它允许我加载较早的消息并将其插入列表的顶部( 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 编辑1

consider, oldFirstItem is the current first item, then I insert a new item in front of the item. 考虑一下, oldFirstItem是当前的第一项,然后在该项的前面插入一个新项。 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. 现在,新项目成为第一项,并且由于滚动位置未更改,因此新项目可见:感觉列表滚动到新插入的项目,但仅将项目1向下推至n。 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. 我想要的是,它将所有新项目上推-用户看不到的区域-以及oldFirstItem项目顶部的oldFirstItem using ScrollTo makes that list jump. 使用ScrollTo可使该列表跳转。

EDIT 2 I added a picture trying to show what I want to achieve. 编辑2我添加了一张图片,试图显示我想要实现的目标。 The area above the red line is not visible. 红线上方的区域不可见。 在此处输入图片说明

To get you going, I tried something but could not get it a 100% 为了让您顺利进行,我尝试了一些尝试,但未能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) 您可以轻松地将ScrollViewer封装在网格中并添加上方的按钮(如您的图片中所示)

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. 不幸的是,如果您再次触发第二行代码(例如,通过单击按钮),则会使列表向上滚动,但ScrollToVerticalOffset可以工作。 So for some reason ScrollToVerticalOffset is not working right away-after changing VerticalScrollBarVisibility. 因此,由于某些原因,在更改VerticalScrollBarVisibility后ScrollToVerticalOffset无法立即工作。 If you can get this last part figured out, I believe your question would be solved 如果您能弄清最后一部分,我相信您的问题将会解决

The thing that prevents your desired effect is the ListHeader control is at top when you insert item at top. 当您在顶部插入项目时,阻止您达到预期效果的是ListHeader控件在顶部。 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: 或者,您可以制作一个假的标头项目并处理add top事件,例如:

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

you can easily achieve this via adding new items to top of the observable collection 您可以通过将新项目添加到可观察集合的顶部来轻松实现此目的

obsData.Insert(0,newItem)

Reference 参考

如果看到...,您可以使用ScrollTo方法。

yourLongListMultiSelector.ScrollTo(yourNewInsertedItem);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM