通用Windows 8.1存储项目。
我想知道,当ListView在用户交互后停止滚动时。我在网上找到了大量的信息,但没有一个可靠的工作在WP 8.1上的例子(WPF / WP8示例没有多大帮助,并且有很多它们。)
这就是我现在所做的。
<ListView
x:Name="MessageList"
ItemsSource="{Binding Messages}"
VerticalAlignment="Bottom"
ItemContainerStyle="{StaticResource ChatListViewItemStyle}"
PointerEntered="MessageList_OnPointerEntered"
>
<ListView.ItemTemplate>
<DataTemplate>
<messages:MessageContainer />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我在后面的代码中从ListView获得ScrollViewer引用。
// GetChildElement<T>(this DependencyObject root) is a simple extension method of mine
Scroll = MessageList.GetChildElement<ScrollViewer>();
PointerEntered
处理程序用于检测用户交互的开始。检测到交互时,我订阅Scroll.ViewChanged
并使用事件的IsIntermediate
标志来检测列表何时停止滚动(包括惯性)。
void MessageList_OnPointerEntered(object sender, PointerRoutedEventArgs e)
{
Debug.WriteLine("START MONITORING INTERACTION");
Scroll.ViewChanged += OnViewChangedByUser;
}
void OnViewChangedByUser(object sender, ScrollViewerViewChangedEventArgs e)
{
Debug.WriteLine("WAITING FOR INTERACTION TO END");
if (!e.IsIntermediate) {
Debug.WriteLine("INTERACTION ENDED");
Scroll.ViewChanged -= OnViewChangedByUser;
}
}
这在某种程度上有效。
问题是,ViewChanged
当列表被滚动到该端不会触发/启动和用户拉动它出界并释放它,从而引起它与惯性返回回来。因此,检测到交互开始,但结果不是。 ViewChanged
根本没有被解雇 - IsIntermediate
= True,也不是False。
什么是做我想做的更好的方法?
答案 0 :(得分:2)
可悲的是,除了重复轮询和检查ScrollOffset之外,在Windows 8.1上没有好办法。
我只得到一个10个双打的数组,就像每秒10次我移入当前的滚动偏移量。在同一个处理程序中检查最后5个是否等于列表的结尾而不是引发事件。
答案 1 :(得分:1)
正如TamásDeme所说,没有什么好办法可以做到所需要的。但是,我发现了一个适用于我的情况的解决方法(虽然没什么好看的。)
事实上,当滚动停止时,我正在检测列表是否滚动到底部。它正在检测滚动的结束是导致这么多麻烦的原因。
问题分为两部分:1 - 检测用户交互的结束,2 - 检测惯性的结束。令人惊讶的是,没有好办法解决其中任何一个问题。值得庆幸的是,我真正需要的只是在滚动(用户驱动或惯性动画)停止时知道VerticalOffset
的值。我实际上不必知道用户是否仍然持有该列表。
void MessageList_OnPointerEntered(object sender, PointerRoutedEventArgs e)
{
IsScrolledToLastLine = false; // this is to signal, that the user is
// holding the list, and there must be no
// automatic scrolling, when content is
// added to it.
Debug.WriteLine("[*]START MONITORING INTERACTION");
Scroll.ViewChanged += OnViewChangedByUser;
Scroll.LayoutUpdated += OnScrollLayoutUpdated;
}
void OnScrollLayoutUpdated(object sender, object e)
{
// will trigger multiple times during scrolling
// AND
// will trigger when inertia finally stops
// (regardless of the changes of VerticalOffset)
IsScrolledToLastLine = Scroll.ScrollableHeight == Scroll.VerticalOffset;
Debug.WriteLine("Interaction progress: {0}", IsScrolledToLastLine);
}
void OnViewChangedByUser(object sender, ScrollViewerViewChangedEventArgs e)
{
if (!e.IsIntermediate) {
IsScrolledToLastLine = Scroll.ScrollableHeight == Scroll.VerticalOffset;
Debug.WriteLine("Interaction end: {0}", IsScrolledToLastLine);
Scroll.LayoutUpdated -= OnScrollLayoutUpdated;
Scroll.ViewChanged -= OnViewChangedByUser;
}
}
LayoutUpdated
。与ViewChanged
不同,当事件图片中显示的情况下惯性停止时,此事件也会被触发。不幸的是,没有办法在LayoutUpdated
中确定列表是否完全停止滚动。
ViewChanged
时, VerticalOffset
正常工作; LayoutUpdated
涵盖了滚动过度的情况。
还有另一个问题:滚动列表边缘时,OnScrollLayoutUpdated
可能会保持订阅状态,因为ViewChanged
不会触发。幸运的是,我可以忽略它,这不会破坏任何东西。