UWP ListView 在索引 0 处插入项目时防止滚动

UWP ListView Prevent Scrolling When Item Inserted At Index 0

我有 UWP/Windows 10 个应用程序。它包含绑定到可观察集合的 ListView。列表视图包含按时间倒序排列的项目(最新的在顶部)。

通常当新项目到达时,我需要将它们插入集合的顶部。这工作正常,项目被插入并且列表视图通过绑定机制更新为新项目。

我的问题是,如果列表视图已经滚动到列表的顶部,新项目将以动画形式出现并将所有其他项目向下推。由于多种原因,这是有问题的,但用户的一个大烦恼是,他们通常正要点击顶部的项目,但它在最后一毫秒在他们下面发生变化,他们最终点击了错误的项目。

如果列表已经向下滚动到至少顶部项目的高度,则没有问题。该项目被插入到列表的顶部,滚动条更新以指示您现在可以比以前更向上滚动,但列表的垂直滚动位置不会移动并且可见的 area/viewport 保持不变。

当列表中的顶部项目可见并且在它之前插入了一个新项目时,这与我想要的行为相同。垂直滚动 position/view 端口应保持不变,滚动条应更新以指示您现在可以向上滚动,这样做应该会显示新项目。

有谁知道如何获得这种行为?

更新:所以我的问题比我最初想象的要复杂一些。新项目插入位置零,列表不滚动(如果它已经向下滚动 1 个像素或更多)。那太棒了。但是,如果项目随后更新(额外数据的异步加载),这会导致项目模板高度发生变化,然后列表会在数据更新时滚动。

例如;

Item1 (top of visible list)
Item1 line 2
Item2
Item2 line 2

Then new item added

Item0 (not visible)
Item0 line 2
Item1 (top of visible list)
Item1 line 2
Item2
Item2 line 2

All good. Now item0 updates and it's line 2 becomes a much longer piece of text that wraps;

Item0 
Item0 AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAA (List scrolls so everything from here down is now visible)
AAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAA
Item1 (no longer top of visible list)
Item1 line 2
Item2
Item2 line 2

编辑 2: 我目前没有物理 phone 来测试,但我刚刚在 Windows 10 移动模拟器中尝试过,那里的行为正是我想要的。即使第一个项目的一小部分滚出屏幕,添加一个在加载后不久增加其高度的新项目也不会导致视口滚动。但是我不想要的行为仍然发生在桌面上。 "universal" 应用程序非常令人失望。

您可以为此使用 ListView 函数 ScrollIntoView。一般问题是,此函数仅确保显示 Listitem,而不确保显示项目的位置。(在 ListView 的 top/bottom)

不过你可以用一个小技巧来实现:

1:记住应该显示的项目

firstitem = ItemListView.Items(0)

2: 在此之前插入项目时,确保列表视图以 (1:) 中的项目显示在顶部的方式滚动

'Your Insert Function
ItemListView.Items.Insert(0, "test") '<-- Your Insert function

'Scroll in a way that the item from (1:) is shown on top
ItemListView.ScrollIntoView(ItemListView.Items(ItemListView.Items.Count - 1))
ItemListView.UpdateLayout()
ItemListView.ScrollIntoView(firstitem)

列表视图默认 ItemsPanel 有一个 属性 称为 ItemsUpdatingScrollMode。您可以将其设置为 KeepItemsInView.

你仍然必须事先向下滚动至少一个像素,使用 ListViews 内部 ScrollViewerChangeView 可以实现什么.

<ListView.ItemsPanel>
  <ItemsPanelTemplate>
    <ItemsStackPanel ItemsUpdatingScrollMode="KeepItemsInView" />
  </ItemsPanelTemplate>
</ListView.ItemsPanel>