什么是 WPF 预览事件?

我一直在寻找事件“ Preview * * * *”的描述,就像每个元素都有事件 KeyDown 和 PreviewKeyDown 一样。什么是差异(不是一个附加事件和一个不是,真正的传统差异和编程方式的差异)

In any class derived from Control, you can override both methods.. OnKeyDown and OnPreviewKeyDown, now I am writing my custom control, which method shall I use? And whats difference between both of them.

30906 次浏览

Basically, it's the same event but happens right before the main event. They exist so you can listen for those types of events without interfering with the control's normal behavior when those events occur.

For instance, buttons do things when you Click or MouseEnter, etc. If you handle those events yourself you have to make sure you do the same things otherwise your button won't act the same. The Preview events give you an event in the same timeline without having to worry about messing with existing functionality.

This is especially useful when dealing with custom styles/triggers/control templates. When you start overriding control appearance/behavior.

So in your Control, do the main work you want in the OnKeyDown event and leave the preview event for someone else to use, is how I work with them.

I found this blog entry really useful in describing the difference:

http://joshsmithonwpf.wordpress.com/2007/06/22/overview-of-routed-events-in-wpf/

You have the visual tree, when an event occurs on an element in the tree, first a preview event will travel from the root to the element (tunneling): the PreviewKeyDown event will be raised on all these elements, and then a "normal" event will travel from the element to the root (bubbling).

From Programming WPF - Chris Sells and Ian Griffith

With the exception of direct events, WPF defines most routed events in pairs - one tunnelling and the other bubbling. The tunnelling event name always begins with 'Preview' and is raised first. This gives parents the chance to see the event before it reaches the child. This is followed by the bubbling counterpart. In most cases, you will handle only the bubbling one. The Preview would be usually used to

  • block the event (e.Handled = true)
  • cause the parent to do something in advance to normal event handling.

e.g. if UI Tree = Button contains Grid contains Canvas contains Ellipse
Clicking on the ellipse would result in (MouseDownButton is eaten up by Button and Click is raised instead.)

PreviewMouseDownButton
PreviewMouseDownGrid
PreviewMouseDownCanvas
PreviewMouseDownEllipse
MouseDownEllipse
MouseDownCanvas
MouseDownGrid

This difference has to do with routed events, which is how WPF implements its event handling strategy. The standard event name (i.e. KeyDown, etc.) implies a bubbling routing strategy. The ones prepended with "Preview" (i.e. PreviewKeyDown, etc.) implies a tunneling routing strategy. You can read about these strategies in more detail here. Basically, when an event in WPF is invoked, it first travels from the top-most element down the visual tree to the element that invoked the event and finally returns upwards. On the way down the tree, you will encounter the PreviewKeyDown event, and on the return trip you will encounter the KeyDown event, in that order.