WPF触屏Touch事件在嵌套控件中的响应问题
2017-04-27 15:08
239 查看
前几天遇到个touch事件的坑,记录下来以增强理解。
具体是 想把一个listview嵌套到另一个listview,这时候如果list view(子listview)的内容过多超过容器高度,它是不会出现滚动条压缩内容区域的,反而会将滚动区域转移到外面的list view(父listview),这个无可争议,但这个问题开始没留意,为待会的坑埋下伏笔。
因为 然后就是设置鼠标滚轮。
首先我使用了MouseWheel事件,奇怪的是它明明是个路由事件,然而listview似乎做了处理,没有冒泡到父级。
于是我改写PreviewMouseWheel事件,吧从父级传过来的时间再冒泡回去。
在子类的listview中,我在滚动事件里写了个向上传递的触发事件:
这样我就能实现当鼠标焦点在子listview时,能触发父级的滚动事件
这时候为了触摸屏操作,我如是写了touchdown .touchmove touchup 三个事件,可是,当手势在子listview做滑动操作的时候,父级不滑动。
即使我完全伪造一个source为上级的touch事件,父级仍然岿然不动,如图:
于是我开始找原因,touch事件同样是路由事件,于MouseWheel不同的是,我可以在父listview触发它。
那么是什么原因呢,通过可视化树工具,可以发现,在嵌套的listview中实际上嵌套了两个scrollview, 当touch事件在 子listview中触发时,实际上事件被子级中的scrollview吸收了。但是为何伪造后仍然无法反应?
那是由于touch事件是一个特殊的事件,至少有别于滚轮事件,控件需要对手势在触摸屏上的坐标做出响应,两个相互嵌套的滑动控件,无法对同一手势坐标做出反应,否则他们之间的相对位置就会发生改变,也就是说两个scrollview不能同时依赖一个手势源,只有最上层的scrollview才能响应目标源。
不知道微软为何这么设定,至少我的理解是这样的
由于开始的设置,子listview中的scrollview永远不会有效果。因此容易被忽略
所以我们只要重写底层listview的template就好了,把原来包裹ItemsPresenter的Scrollview控件给删掉
touch事件就能被父一级的listview触发了!
希望这个绕坑的经历能帮助到大家,谢谢!
具体是 想把一个listview嵌套到另一个listview,这时候如果list view(子listview)的内容过多超过容器高度,它是不会出现滚动条压缩内容区域的,反而会将滚动区域转移到外面的list view(父listview),这个无可争议,但这个问题开始没留意,为待会的坑埋下伏笔。
因为 然后就是设置鼠标滚轮。
首先我使用了MouseWheel事件,奇怪的是它明明是个路由事件,然而listview似乎做了处理,没有冒泡到父级。
于是我改写PreviewMouseWheel事件,吧从父级传过来的时间再冒泡回去。
在子类的listview中,我在滚动事件里写了个向上传递的触发事件:
private void BodyList_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta); eventArg.RoutedEvent = UIElement.MouseWheelEvent; eventArg.Source = sender; BodyList.RaiseEvent(eventArg); }
这样我就能实现当鼠标焦点在子listview时,能触发父级的滚动事件
这时候为了触摸屏操作,我如是写了touchdown .touchmove touchup 三个事件,可是,当手势在子listview做滑动操作的时候,父级不滑动。
即使我完全伪造一个source为上级的touch事件,父级仍然岿然不动,如图:
private void UIElement_OnTouchMove(object sender, TouchEventArgs e) { var eventArg = new TouchEventArgs(e.TouchDevice,e.Timestamp); eventArg.RoutedEvent = UIElement.TouchMoveEvent; eventArg.Source = HAHAListBox; (sender as UIElement).TryFindParent<ListBox>().RaiseEvent(e); e.Handled = true; }
于是我开始找原因,touch事件同样是路由事件,于MouseWheel不同的是,我可以在父listview触发它。
那么是什么原因呢,通过可视化树工具,可以发现,在嵌套的listview中实际上嵌套了两个scrollview, 当touch事件在 子listview中触发时,实际上事件被子级中的scrollview吸收了。但是为何伪造后仍然无法反应?
那是由于touch事件是一个特殊的事件,至少有别于滚轮事件,控件需要对手势在触摸屏上的坐标做出响应,两个相互嵌套的滑动控件,无法对同一手势坐标做出反应,否则他们之间的相对位置就会发生改变,也就是说两个scrollview不能同时依赖一个手势源,只有最上层的scrollview才能响应目标源。
不知道微软为何这么设定,至少我的理解是这样的
由于开始的设置,子listview中的scrollview永远不会有效果。因此容易被忽略
所以我们只要重写底层listview的template就好了,把原来包裹ItemsPresenter的Scrollview控件给删掉
touch事件就能被父一级的listview触发了!
希望这个绕坑的经历能帮助到大家,谢谢!
相关文章推荐
- WPF触屏Touch事件在嵌套控件中的响应问题
- 解决UIScrollView,UIImageView等控件不能响应touch事件的问题
- listView嵌套button或者其它clickable控件时会出现listView的onitemClick事件不响应的问题
- 解决UIScrollView,UIImageView等控件不能响应touch事件的问题
- 解决小米系统下ViewPager、ScrollView内嵌套WebView时,Touch事件不响应的问题
- Android_关于子控件和父控件的事件响应问题
- senchatouch之tab事件经常无法响应的问题解决方案
- 线性布局里面嵌套两个控件,但是不想让控件响应事件
- 解决ViewPager嵌套Fragment内部点击事件无响应问题
- Android-ListView中嵌套(ListView)控件时item的点击事件不起作用的问题
- Android 隐藏ViewPager之后,控件点击事件无法响应的问题
- C#控件无法响应单击事件的问题
- ScrollView上加Button UIControlEventTouchUpInside事件超出边界扔响应问题
- 代码创建UIWindow -> UIView -> RootViewController中遇到UIview覆盖,控件事件不响应问题
- 我的Android进阶之旅------>Android中ListView中嵌套(ListView)控件时item的点击事件不起作的问题解决方法
- JQueryUI dialog控件不响应服务端事件问题解决,dialog不能提交表单
- 我的Android进阶之旅------>Android中ListView中嵌套(ListView)控件时item的点击事件不起作的问题解决方法
- 关于IOS7开始,靠左侧边的控件的事件响应问题
- ListView中嵌套(ListView)控件时item的点击事件不起作的问题解决方法
- 父布局与子布局控件的实现响应点击事件冲突问题。