UWP ScrollViewer -区分用户滚动和编程滚动
本文关键字:滚动 编程 用户 ScrollViewer -区 UWP | 更新日期: 2023-09-27 18:09:33
我有一个应用程序,当用户到达ScrollViewer
中的某个位置时,我需要采取特定的操作。此操作有时包括以编程方式将ScrollViewer
滚动到不同的位置。
为了监视用户的滚动动作,我正在监听ScrollViewer
的ViewChanged
事件。问题是,当我从ViewChanged
事件处理程序中以编程方式滚动时,相同的事件处理程序最终会再次被调用,导致不希望的额外滚动发生。
我已经尝试创建一个自定义方法来删除事件处理程序之前调用ScrollViewer.ChangeView()
,但这似乎没有效果。
谁能想出一个解决这个问题的方法,或者一个方法来区分用户的滚动操作和我的编程操作?
private void MyScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (conditionals)
{
ScrollTo(location);
}
}
private void ScrollTo(double offset)
{
MyScrollViewer.ViewChanged -= MyScrollViewer_ViewChanged;
MyScrollViewer.ChangeView(offset, null, null);
MyScrollViewer.ViewChanged += MyScrollViewer_ViewChanged;
}
不幸的是,无法确定是什么触发了ViewChanged
事件。然而,解决这个问题是有可能的。
问题是ChangeView()
是异步的,所以在调用ChangeView
之后立即重新添加事件处理程序太快了。ChangeView
将引发一系列ViewChanged
事件,最后一个是e.IsIntermediate == false
;只有在发生这种情况时,才应该重新挂钩事件处理程序。处理此问题的最佳方法可能是使用一个临时事件处理程序,等待e.IsIntermediate == false
,然后重新挂钩原始处理程序。
为了防止用户在执行ChangeView
期间与ScrollViewer
交互,可以暂时禁用滚动和缩放模式。
最后,如果用户在满足条件的情况下操作ScrollViewer
,则需要在调用ScrollTo()
之前取消该操作。
EDIT:在我的实现中,出现了一个问题,由于调用这些处理程序的次数,事件处理程序被添加了不止一次。为了解决这个问题,我从这里采取了一个简单的策略。
private void MyScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (!conditionals) return;
if (e.IsIntermediate)
{
var uiElement = MyScrollViewer.Content as UIElement;
uiElement?.CancelDirectManipulations();
}
ScrollTo(location);
}
private void Temporary_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (e.IsIntermediate) return;
MyScrollViewer.ViewChanged -= Temporary_ViewChanged;
MyScrollViewer.ViewChanged -= MyScrollViewer_ViewChanged;
MyScrollViewer.ViewChanged += MyScrollViewer_ViewChanged;
MyScrollViewer.HorizontalScrollMode = ScrollMode.Enabled;
MyScrollViewer.VerticalScrollMode = ScrollMode.Enabled;
MyScrollViewer.ZoomMode = ZoomMode.Enabled;
}
private void ScrollTo(double offset)
{
MyScrollViewer.ViewChanged -= MyScrollViewer_ViewChanged;
MyScrollViewer.ViewChanged -= Temporary_ViewChanged;
MyScrollViewer.ViewChanged += Temporary_ViewChanged;
MyScrollViewer.HorizontalScrollMode = ScrollMode.Disabled;
MyScrollViewer.VerticalScrollMode = ScrollMode.Disabled;
MyScrollViewer.ZoomMode = ZoomMode.Disabled;
MyScrollViewer.ChangeView(offset, null, null);
}