UWP - 父控件拦截指针事件(其中子控件为 ScrollViewer)
Posted
技术标签:
【中文标题】UWP - 父控件拦截指针事件(其中子控件为 ScrollViewer)【英文标题】:UWP - Interception of pointer events by parent control (where child is ScrollViewer) 【发布时间】:2021-10-11 12:35:30 【问题描述】:我正在寻找一种方法来拦截所有事件,例如父级的 PointerReleased。
我的问题是我无法拦截 ScrollViewer 的父 PointerReleased 事件。
我想用手指将手指(光标)放入 ScrollViewer 移动 100 像素,然后松开;它应该像 Scrollviewer.IsHitTestVisible=false 一样工作,并将所有事件接收到 outerStack(scrollerviewer 的父级),但 scrollviewer 应该像 IsHitTestVisible=true 一样工作,并继续将所有相关事件获取到自身(scrollviewer)及其子级(scrollviewer 子级,如 innerStack )。
我收到以下日志
innerStack_PointerPressed
scrollView_PointerPressed
outerStack_PointerPressed
CoreWindow_PointerPressed
但我期待看到这个
innerStack_PointerPressed
scrollView_PointerPressed
outerStack_PointerPressed
CoreWindow_PointerPressed
outerStack_PointerReleased
CoreWindow_PointerReleased
有代码示例
<Page
x:Class="App9.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="ThemeResource ApplicationPageBackgroundThemeBrush">
<StackPanel x:Name="outerStack"
Background="Red"
Padding="40"
PointerPressed="outerStack_PointerPressed"
PointerReleased="outerStack_PointerReleased">
<ScrollViewer x:Name="scrollView"
Background="Blue"
Padding="40"
PointerPressed="scrollView_PointerPressed"
PointerReleased="scrollView_PointerReleased"
VerticalScrollBarVisibility="Visible"
VerticalScrollMode="Enabled"
HorizontalScrollBarVisibility="Visible"
HorizontalScrollMode="Enabled"
Height="500">
<StackPanel x:Name="innerStack"
Background="Green"
Padding="40"
PointerPressed="innerStack_PointerPressed"
PointerReleased="innerStack_PointerReleased">
<TextBlock Text="A" FontSize="100"/>
<TextBlock Text="B" FontSize="100"/>
<TextBlock Text="C" FontSize="100"/>
<TextBlock Text="D" FontSize="100"/>
<TextBlock Text="E" FontSize="100"/>
<TextBlock Text="F" FontSize="100"/>
<TextBlock Text="G" FontSize="100"/>
<TextBlock Text="H" FontSize="100"/>
<TextBlock Text="I" FontSize="100"/>
<TextBlock Text="J" FontSize="100"/>
<TextBlock Text="K" FontSize="100"/>
<TextBlock Text="L" FontSize="100"/>
<TextBlock Text="M" FontSize="100"/>
<TextBlock Text="N" FontSize="100"/>
<TextBlock Text="O" FontSize="100"/>
<TextBlock Text="P" FontSize="100"/>
<TextBlock Text="Q" FontSize="100"/>
<TextBlock Text="R" FontSize="100"/>
<TextBlock Text="S" FontSize="100"/>
<TextBlock Text="T" FontSize="100"/>
<TextBlock Text="U" FontSize="100"/>
<TextBlock Text="V" FontSize="100"/>
<TextBlock Text="W" FontSize="100"/>
<TextBlock Text="X" FontSize="100"/>
<TextBlock Text="Y" FontSize="100"/>
<TextBlock Text="Z" FontSize="100"/>
</StackPanel>
</ScrollViewer>
</StackPanel>
</Page>
using System.Diagnostics;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
namespace App9
public sealed partial class MainPage : Page
public MainPage()
this.InitializeComponent();
Window.Current.CoreWindow.PointerPressed += CoreWindow_PointerPressed;
Window.Current.CoreWindow.PointerReleased += CoreWindow_PointerReleased;
private void CoreWindow_PointerPressed(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.PointerEventArgs args)
Debug.WriteLine("CoreWindow_PointerPressed");
private void CoreWindow_PointerReleased(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.PointerEventArgs args)
Debug.WriteLine("CoreWindow_PointerReleased");
private void outerStack_PointerPressed(object sender, PointerRoutedEventArgs e)
Debug.WriteLine("outerStack_PointerPressed");
private void outerStack_PointerReleased(object sender, PointerRoutedEventArgs e)
Debug.WriteLine("outerStack_PointerReleased");
private void scrollView_PointerPressed(object sender, PointerRoutedEventArgs e)
Debug.WriteLine("scrollView_PointerPressed");
private void scrollView_PointerReleased(object sender, PointerRoutedEventArgs e)
Debug.WriteLine("scrollView_PointerReleased");
private void innerStack_PointerPressed(object sender, PointerRoutedEventArgs e)
Debug.WriteLine("innerStack_PointerPressed");
private void innerStack_PointerReleased(object sender, PointerRoutedEventArgs e)
Debug.WriteLine("innerStack_PointerReleased");
【问题讨论】:
【参考方案1】:最简单的解决方法是将next属性放到ScrollViewer的内容视图中
ScrollViewer.Content.ManipulationMode="TranslateX,System"
解决方案并不完美,但很简单。
更多信息https://docs.microsoft.com/ru-ru/archive/blogs/wsdevsol/where-did-all-my-gestures-go
【讨论】:
如果您已经解决了您的问题,请mark它被接受【参考方案2】:我的问题是我无法拦截 ScrollViewer 的父 PointerReleased 事件。
请参阅Events and routed events overview 文档,将 Handled 属性设置为 true 会影响事件系统行为。当 Handled 为 true 时,大多数事件处理程序的路由停止;事件不会继续沿着路由通知其他附加的处理程序该特定事件情况。
所以你可以将滚动视图的PointerReleased
Handled 设置为 true
private void scrollView_PointerPressed(object sender, PointerRoutedEventArgs e)
Debug.WriteLine("scrollView_PointerPressed");
e.Handled = true;
private void scrollView_PointerReleased(object sender, PointerRoutedEventArgs e)
Debug.WriteLine("scrollView_PointerReleased");
e.Handled = true;
【讨论】:
感谢您的回答!该链接真的很有帮助;我正在寻找 AddHandler 方法。但无论如何,它无济于事。如果用户在 ScrollViewer 上滚动手指(触摸模式,而不是鼠标),则 ScrollViewer 会引发 PointerCaptureLost 事件。并且 ScrollViewer 的 PARENT 不会知道任何未来的事件,即使使用 AddHandler 也是如此。目前尚不清楚如何处理手指运动,直到有关手指释放的最新事实。 从上面的案例描述中,你想拦截ScrollViewer的父级PointerReleased事件,为什么你的cmets告诉从父级捕获路由事件,你的真正目的是什么? 感谢您的回答!是的,我想拦截 ScrollViewer 的父事件。我有两条评论,一条是我现在得到的,第二条是我想要得到的,抱歉造成混乱。我的主要目标是为我的自定义手势识别器提供高级事件。因此,我想确保 ScrollViewer 在默认情况下正常工作,并且我的自定义手势识别器从 ScrollViewer 的父级获取所有事件以检测全屏手势。 根据测试,在设计的触摸模型中滚动时,滚动视图将中断点释放事件。并且为滚动视图父级注册手势不是一个好习惯,它会使交互过于复杂。 我们建议您使用按钮或其他控件来处理您上面提到的全局事件。以上是关于UWP - 父控件拦截指针事件(其中子控件为 ScrollViewer)的主要内容,如果未能解决你的问题,请参考以下文章