作者mortleo (mort)
看板C_Sharp
标题Re: [问题] wpf路由事件的一些问题
时间Tue Nov 27 14:26:46 2012
WPF 中的控制像是树状概念
也就是 Window 在最底层,向上是 Grid 或 Canvas
然後是一般控制项 Textbox 或 Button
目标是用滑鼠操作 Window 进行拖拉放大
因此必须先知道事件在视觉树中的传递顺序
http://nui.joshland.org/2010/04/why-wont-wpf-controls-work-with-touch.html
直接看图很容易理解
TouchDown 或 MouseDown 是由上往下
Preview 则是由下往上
接着再定义此操作行为的操作区域跟操作动作
如果有重复的区域跟同样的动作,就要排执行优先权,决定哪一个控制项的事件先执行
并挡住另一个控制室的事件发生。(使用者不会想要同时反白文字跟缩放视窗)
1. 操作区域(Window范围内)
a. 无其他控制项所在范围
b. 有控制项压在上面,但此控制项仅有显示功能,不需接收滑鼠操作触发个别事件。
(Ex:TextBox、Image、Path...)
c. 有控制项压在上面,此控制项有自己的滑鼠事件。
(Ex:TextBlock、Button、CheckBox...)
一般来说,c 的优先权比较高,所以 c 的控制项收到滑鼠事件後,执行完加上
e.Handlded = true 让事件不会继续往下传。
而 b 就比较简单,要关掉就设定 IsHitTest = false,滑鼠点不到他,
他也就不会收到或拦截事件了。
2.操作动作(点击、拖曳、放开)
MouseDown->MouseMove->MouseUp
MouseDown
在 a 或 b 区域时, Window 收到事件,先让 Window 用 CaptureMouse
锁住滑鼠。
MouseMove
检查目前滑鼠是否是被 Window 锁住中,是的话才执行缩放操作
MouseUp
呼叫 ReleaseMouseCapture 释放滑鼠。
※ 引述《Beramode (Xeno)》之铭言:
: 刚入门不久,写了几个小程式就碰上路由事件的处理
: MSDN看完还是有些地方不太明白
: MSDN上写说路由事件的策略分为三种,其中direct就是winform使用的事件模式
: 只有控制项本身会执行此事件,不会继续往父项跑,如果我想让一个控制项使用
: 策略为direct的事件,是否得自己宣告一个新事件,因为内建事件的策略好像都
: 是bubble,也找不到可以对单一事件策略修改的方法
: 以上问题的产生是因为我写了一个程式,可以用滑鼠直接对程式的window进行拖拉放大
: 等动作,但因为路由事件的关系,window下的控制项都吃到MouseDown、MouseMove这些
: 事件,变得无法正常使用了。我尝试用e.Handled=true来挡掉window.MouseDown的执行,
: 但是一个控制项就得写一次,而且有些控制项的MouseDown还不会触发,变得挡不住(像
: textBox就只能用previewMouseDown才能触发),如果控制项一多,一定会变得很复杂
: 想请问是否有方法可以让事件只让控制项本身使用,底下的成员不会去触发?
: 而不是得让底下成员一个一个去挡bubble
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 118.170.138.175
1F:推 Beramode:如果Window上的控制项非常多,不想一个一个设handled 11/27 17:00
2F:→ Beramode:有没有方法可以把window.MouseDown的策略改成Direct呢? 11/27 17:01
3F:→ mortleo:预设的不行,你可以透过自定义控制项来加上你想要的事件 11/27 19:35
4F:推 Beramode:知道了 谢谢 我研究一下如何自订事件 11/28 11:05