假設 element tree 如下:
Window
|
Grid
|
---------------------------
| | |
Button TextBlock ScrollViewer
| |
TextBlock StackPanel
|
TextBlock
而 Routed Event Handler 大概長以下這樣:
void functionName(object sender, RoutedEventArgs args)其中參數的部份有幾個重點:
{ ....(事件處理)... }
- sender:此物件將 event 送到 application 中
- args.Source:真正導致 event 發生的 element
若是在 element tree 中左下角的 TextBlock 按一下滑鼠右鍵,分別會產生出以下的 event:
PreviewMouseDown -> MouseDown其中 sender 的部份,觸發 event 順序如下:
- PreviewMouseDown:Window -> Grid -> Button -> TextBlock
- MouseDown:TextBlock -> Button -> Grid -> Window
因此從上面可以知道,PreviewMouseDown 是屬於 tunneling event、MouseDown 屬於 bubbling event。
而透過 Event Routing 的特性,若是要讓較上層的 element 先處理 mouse down 的動作,可以撰寫在 PreviewMouseDown 中。
Mouse Event
MouseDown 與 MouseUp 不一定會同時出現
例如:在視窗中按下按鈕,會發生 MouseDown event,但如果持續按著不放,再離開視窗的範圍後再放開滑鼠,不會出現 MouseUp event。
因此,若要解決此問題,可以透過在 UIElement 或 ContentElement 中所定義的 CaptureMouse 方法來解決。
當呼叫了 CaptureMouse 方法後,即使滑鼠離開視窗,視窗也會持續的接收 MouseMove 與 MouseUp 事件。
最後當 MouseUp 事件處理完成後,可以呼叫 ReleaseMouseCapture 或是設定 Mouse.Capture 為 null 來釋放所捕捉的滑鼠。
Keyboard Event
在 WPF 中,keyboard event 都會下放到 TextBox、RichTextBox、ScrollViewer 這一類的控制項中作處理。
需要注意的是,只有當 element 或是控制項具有鍵盤焦點時,才會是 keyboard event 的來源。
此外,keyboard event 亦屬於 routed event,因此具有焦點的 element 的所有上層 element,都可以參與 keyboard event,且其 IsKeyboardFocusWithin 屬性都會是 true。
當 element 獲得 or 失去焦點時,會觸發 GotKeyboardFocus 與 LostKeyboardfocus 事件,也都是 routed event;此外,由於兩個事件屬於 tunneling event,因此在 element tree 中上方的 element 可以先察覺到焦點的改變。
而 Keyboard 的輸入包含了三種 event,發生順序如下:
- KeyDown (參數型態為 KeyEventArgs)
- TextInput (參數型態為 TextCompositionEventArgs)
- KeyUp (參數型態為 KeyEventArgs)
但比較需要注意的是,若按下的是「Shift」、方向鍵、或是其他功能鍵,並不會產生 TextInput 事件。舉例來說,或先按下 Shift 再按 A,一共會觸發兩次 KeyDown 事件、一次 TextInput 事件、兩次 KeyUp 事件。
沒有留言:
張貼留言