1

Lets say I have my user-control somewhere in the visual tree. Parent and children are 3rd-party controls that I cannot modify. I want to filter keyboard events in my control so that children controls do not receive some keyboard events, but the parent controls do.

I'll try to explain what I want to achieve with some diagrams. If controls do not handle keyboard events, all events bounce through the visual tree:

enter image description here

But, f.e. when user presses A,

  1. Child2.OnPreviewKeyDown() should NOT be called
  2. but Parent2.OnTextInput should still receive an event enter image description here

I can achive (1) by setting e.Handled = true in MyControl.PreviewKeyDown. The problem is that in this case TextInput event is not generated: enter image description here

Is there a way to achieve behavior like on the 2nd picture?

Added: The problem I'm trying to solve is that a 3rd-party control (Child 2) steals some input in OnPreviewKeyDown (and marks event as handled), and I'm trying to avoid that.

nevermind
  • 2,300
  • 1
  • 20
  • 36
  • Parent2 cannot handle the `PreviewKeyDown` instead of `Keydown`? – PScr Sep 24 '15 at 15:26
  • have you read this http://stackoverflow.com/questions/18604623/when-are-tunneling-and-bubbling-events-useful-in-wpf ? – netaholic Sep 24 '15 at 15:29
  • 1
    I don't think what you ask is possible without some major hack (read: brittle and not advisable). Things that come to mind is handle the preview event and reraise the event on the Parent. Or maybe there is a way via reflection the disconnect the handler in Child2. Neither of those things are very palatable though. – Frank J Sep 24 '15 at 15:31
  • there is no way to prevent from hitting the event, but you can exit earlier with `if (myhandler) return`, where `my handler` should be a boolean that you customize to make it `true`/`false` according to your needs – bto.rdz Sep 24 '15 at 15:39
  • @PScr Unfortunately no. Parent 2 should handle input only if it was not handle by any other control. And I had a mistake in my images: Parent uses TextInput event, not KeyDown event. – nevermind Sep 24 '15 at 15:39
  • @bto.rdz Can you please clarify what handler you are talking about? I can't change handler of Child 2 because it is a 3rd-party control – nevermind Sep 24 '15 at 15:49
  • you handler, just declare a boolean variable and make it work I would make an example but got no time – bto.rdz Sep 24 '15 at 15:53
  • Does have Child2 a `protected` OnPreviewKeyDown. If so, you could inherit then from Child2 overwrite the event handler to your liking and use the new control instead of the old one. – Frank J Sep 24 '15 at 17:15
  • @FrankJ It has, but actually Child2 is somewhere deep inside the ControlTemplate of that 3rd-party control (the real project is more complex, there are other controls involved, but I tried to not to go into details in the question). – nevermind Sep 24 '15 at 18:22
  • I think I will have to raise simulated KeyDown and TextInput events manually. P.S. That's why I dislike controls that you can't modify - you spend hours to figure out hacks and dirty tricks to get rid of features that you never use, and that break your other code :( – nevermind Sep 24 '15 at 18:24

1 Answers1

0

What you can generally do in WPF to handle a suppressed event is add a handler in code and re-raise the event. To do this, you use the UIElement.AddHandler() method, for example:

child2.AddHandler(UIElement.TextInput, new TextCompositionEventHandler(nameOfYourHandlerFunction), true);

The 'true' boolean value is what makes nameOfYourHandlerFunction fire even if the Handled flag is set. The event won't automatically re-bubble by doing that, so you need to raise the event again.

base.RaiseEvent(e);

This works for events that have a routing strategy of Bubble.

Ken M
  • 34
  • 4
  • According to what he wrote: He can't attach a handler in Parent2 since it is a 3rd party control internal, therefore he can't add this handler as you describe it. Additionally I believe that handling the preview key down event would prevent the TextInput event from ever being fired, therefore that wouldn't work either. – Frank J Sep 24 '15 at 17:13
  • With parent control situation is better than with child. I can get a reference to it. But anyway, TextInput event is not fired at all, if KeyDown or KeyUp was handled. – nevermind Sep 24 '15 at 18:22
  • Well, alternatively, you could manually handle and re-raise the KeyDown or KeyUp events (whichever was consumed) on child2 in much the same fashion as a way to get the routed event to continue bubbling past child2. I would really be surprised if the AddHandler function really doesn't work on child2 unless it's not a WPF control (like if you're hosting a Windows Forms control). Routed events in WPF still forward to the next listener even if the Handled flag is set. Setting the 'true' flag in AddHandler is the means provided to handle such events. – Ken M Sep 24 '15 at 18:52