1

I have a window with a textbox that is not throwing textInput events when typing.

I have been looking at it with Snooper. Only the KeyDown and KeyUp events get thrown.

Screenshot of snooper results while typing

It IS responding to a few keys: Space, backspace, Insert, home, delete, end

It responds to copy & paste commands, as well as Select All

It is NOT responding to any character, symbol or number

And here's the kicker: This window is opened via a shared method that is called from two different places in the code. When called from one location the textbox works perfectly, when called from other location it doesn't.

I have ruled out binding, data converters, styles, control location. I stripped the window down to just a single plain textbox with no bindings, and the problem persists.

I've tried all I can think of to track down this mysterious bug. I can't see what could be handling my event before the previewTextInput even gets throw, or why it could possibly be only occurring half the time.

Any ideas about the cause of this bug, or other tools I could try to trace the events would be greatly appreciated!

Edit: Adding some code to demonstrate. This has been stripped down to the barest code required, and the issue is still occurring.

<Window x:Class="EventViewEmail"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="880" Height="600">

    <TextBox VerticalAlignment="Top"/>
</Window>

notice the lack of bindings, styles, or anything else that may be interfering the control

Public Class EventViewEmail
    'all code removed from the view-behind'
End Class   

this is the static class that builds the window. The two separate calls to this class build the arguments differently. I've removed the code that uses the arguments to show that they aren't affecting the issue at hand.

Public Class EventManager
    Public Shared Sub Show(e As EventEdit, p As WorkplanPageViewModel)
        Dim w = New EventViewEmail
        If w Is Nothing Then Return

        'removed datacontext for testing'
        'w.DataContext = e '
        'w.Tag = p'
        w.Show()
    End Sub
End Class

The only other thing I can add is that the code calling the Show() sub are coming from two separate solutions. Not sure what impact that could possibly have after I've removed all the arguments

Edit 2: I have been trying to trace the events sequence to narrow down where the event is getting handled. So far I can see that between the keyDown and keyUp events, there is a sequence of events that should be happening that isn't:

  • PreviewInputReport / InputReport (no source)
  • PreviewTextInputStart / TextInputStart (textbox)
  • PreviewTextInput / TextInput (textbox)
  • PreviewInputReport / InputReport (textboxView)

the keydown event isn't being handled, so I'm not sure why the PreviewInputReport is not getting fired

Shaboboo
  • 1,347
  • 1
  • 16
  • 35
  • Please post relevant code and or a little sample so we can help you and so we can try and reproduce the issue; you should know this by now being a member 10+ years :) – Trevor Aug 02 '19 at 20:59
  • _"When opened one way the textbox works perfectly, when opened the other way it doesn't."_ Ahh, the one way. But the other way? Good read. – BionicCode Aug 03 '19 at 05:05
  • @Çöđěxěŕ I've added the code, in case you didn't know what a window containing nothing but a Textbox looks like... ;) – Shaboboo Aug 06 '19 at 13:56
  • @Shaboboo provided code is not enough to debug the issue. Is it possible for you to create a solution with reproducible issue and share it somewhere, may be github? – Dipen Shah Aug 07 '19 at 18:03
  • @DipenShah I don't expect you to be able to reproduce or debug this issue. I'm asking for ideas for how to debug this further. If you had my code what approach would you take to find the issue? I have tried wpf spoof but all it was able to show me was the event isn't getting thrown. How can I find out why? – Shaboboo Aug 09 '19 at 12:58
  • 1
    @Shaboboo I would suggest to download debug symbols from .net framework and start from the very bottom. – Dipen Shah Aug 09 '19 at 13:02
  • Have you looked into the [TextBoxBase.OnPreviewKeyDown Method](https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.primitives.textboxbase.onpreviewkeydown?view=netframework-4.8)? Also did you read the remarks section about using the `PreviewTextInput Event` [here](https://learn.microsoft.com/en-us/dotnet/api/system.windows.uielement.previewtextinput?view=netframework-4.8) – Trevor Aug 09 '19 at 17:36
  • 1
    If you want some ideas here's one from the top of my head - perhaps you have a global `Window` style in one of the solutions that handles this event? Try setting `w.Style = New Style` in your `Show` method. – Grx70 Aug 11 '19 at 07:19
  • @Çöđěxěŕ The OnPreviewKeyDown does get fired, however the previewTextInput event does not. Any idea what might interrupt the event chain and stop the PreviewTextInput / TextInput events from getting fired? – Shaboboo Aug 12 '19 at 13:20
  • @Shaboboo not at this time I don't, but in the link I posted the remarks section contains this: `multiple key events may raise just one text input event` which may be the issue you are running into. – Trevor Aug 12 '19 at 13:23
  • but if ONE key press doesn't raise ANY input event, you can rest assured that MULTIPLE key presses will not result in even ONE input event. As I said above, it is only responding to specific keys, like space and backspace, Home and end. It is NOT throwing the previewTextInput Or TextInput while pressing any letter, symbol or character. (only when the window is open method is called from one location in code). Thanks for the thought though! – Shaboboo Aug 12 '19 at 13:26
  • 2
    Look for global event handlers like `EventManager.RegisterClassHandler(typeof(TextBox), UIElement.PreviewTextInputEvent, ...)` and/or behaviors. Are you using any third-party UI library? Look in their code as well. – l33t Aug 12 '19 at 14:02
  • @Grx70 thanks for the idea, I've tried it out on the window and the textbox itself, it seems the styles are not the problem here. One more thing ruled out! – Shaboboo Aug 12 '19 at 15:45
  • @ l33t I have thoroughly checked my code and there are no global event handlers registering to this event. We're also not using any third party Libraries. – Shaboboo Aug 13 '19 at 13:46

5 Answers5

2

Disclaimer

I'll post C# code because I'm not fluent enough in VB to write code (only to read it in a limited scope). I'll try to translate it if I find some time, or anyone of you can feel free to do it.


I have managed to reproduce the behavior you described by handling the PreviewTextInput event up the visual tree on the window (remember it's a tunneling routed event):

<Window (...)>
    <StackPanel>
        <TextBox x:Name="myTextBox"></TextBox>
    </StackPanel>
</Window>
public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        PreviewTextInput += (s, e) => e.Handled = true;
    }
}

So in my opinion it's a strong suspect for the cause of your problems. It also explains the comment to @AQuirky's answer that your PreviewTextInput handler is not called. You can confirm that that's the case by subscribing differently (the handler is called even if the event was marked as handled):

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        PreviewTextInput += (s, e) => e.Handled = true;
        myTextBox.AddHandler(
            routedEvent: PreviewTextInputEvent,
            handler: new TextCompositionEventHandler((s, e) =>
            {
                if (e.Handled)
                    throw new Exception("Gotcha!");
            }),
            handledEventsToo: true);
    }
}

If this turns out to be correct diagnosis, then there's one thing that's somewhat mysterious - who and where does handle the PreviewTextInput event? I guess that's for you to investigate...

This comment from @l33t might come in handy:

Look for global event handlers like EventManager.RegisterClassHandler(typeof(TextBox), UIElement.PreviewTextInputEvent, ...) and/or behaviors. Are you using any third-party UI library? Look in their code as well.


Update

Since it seems like PreviewTextInput is not the culprit after all, here's what I'd do next.

If I'm not mistaken, there's a whole chain of events being fired prior to TextInputEvent, and I believe handling any of those can break the chain. It also looks like InputManager is responsible for managing this event cycle (you can inspect its C# source code here).

That being said I suggest doing the following:

  1. Using InputManager.Current subscribe to its PreProcessInput and/or PostProcessInput events (optionally also PreNotifyInput and PostNotifyInput)
  2. Record the events chain in the working scenario (especially inspect the args' StagingItem.Input.RoutedEvent, which holds the routed event currently being processed)
  3. Repeat the procedure for the not working scenario
  4. Pinpoint the first difference - the first routed event being processed in the working scenario, but not being processed in the not working scenario
  5. Investigate both last common routed event and the first one that's different - perhaps one of those is handled in your code?
Community
  • 1
  • 1
Grx70
  • 10,041
  • 1
  • 40
  • 55
  • So, I put PreviewTextInput handlers at every level of the visual tree. When I open the window from the call that works I can see the event tunneling down from the window to the textbox. When I open the window from the spot that is not working, the PreviewTextInput event does not fire at any level. Interesting side note; the space button does not fire the PreviewTextInput event in either scenario, but works to insert a space in both. – Shaboboo Aug 13 '19 at 13:43
  • Could you clarify exactly what scenarios cause what results? If you're subscribing to the `PreviewTextInput` using [this AddHandler overload](https://learn.microsoft.com/en-us/dotnet/api/system.windows.uielement.addhandler?view=netframework-4.8#System_Windows_UIElement_AddHandler_System_Windows_RoutedEvent_System_Delegate_System_Boolean_) and it's not being invoked then there's something really odd going on - either you have a nasty hack in your code or there really is a bug in .NET framework. – Grx70 Aug 13 '19 at 14:37
  • Just a quick check list: 1) you're adding the handler to the `TextBox` inside the child window 2) you're calling the [`AddHandler` method](https://learn.microsoft.com/en-us/dotnet/api/system.windows.uielement.addhandler?view=netframework-4.8#System_Windows_UIElement_AddHandler_System_Windows_RoutedEvent_System_Delegate_System_Boolean_) on the `TextBox` and not using the _VB.NET_'s [`AddHandler` statement](https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/addhandler-statement). Is that correct? – Grx70 Aug 13 '19 at 14:46
  • Sorry, excuse the comment earlier, I hadn't finished properly testing your handler, which IS working as expected. That handledEventsToo is wonderful, thank you. Still debugging! – Shaboboo Aug 13 '19 at 14:46
  • I can confirm the handler with handledEventsToo works perfectly in the working case, but in the not working case the TextBox_PreviewTextInput event handler is not getting called. I'm going to try attaching this handler higher on the visual tree next – Shaboboo Aug 13 '19 at 14:58
  • Tried the PreviewTextInput handler with handledEventsToo on the window itself, it is not getting called at all in the not-working scenario – Shaboboo Aug 13 '19 at 15:09
  • 1
    How about [`PreviewTextInputStart`](https://learn.microsoft.com/en-us/dotnet/api/system.windows.input.textcompositionmanager.previewtextinputstart?view=netframework-4.8) event? My intuition is that this event is fired first, and if handled, prevents firing the `PreviewTextInput`, but I have no way to confirm this at this moment as I don't have access to a computer with VS installed. – Grx70 Aug 13 '19 at 15:27
  • PreviewTextInputStart event handler is not getting called in the not working version either. (works in the working version) – Shaboboo Aug 13 '19 at 15:40
  • Thanks for the updated answer. I'm combing through all the events now, the only difference I've noticed so far is the original source for some events. I'm giving you the bounty for being so helpful thus far – Shaboboo Aug 13 '19 at 20:49
2

In this case it turned out that the form that launched the window in the not working case was a winform. The winform was blocking the keystrokes. This was fixed by opening the window as a modal.

Shaboboo
  • 1,347
  • 1
  • 16
  • 35
1

I had the same problem here. The difference between the two calls was: one time the WPF-Windows was called modal (works) and one time nonmodal (doesnt work), everytime from a WindowsForms Window.

As Shaboboo wrote in his anwer, this is the difference, but what, if you need to call nonmodal. The answer is given this thread. (stupid me, I had the same problem 2 years ago, asked and got an answer). We have to use

ElementHost.EnableModelessKeyboardInterop(wpfWindow);

Thanks again to V.Leon

woelfchen42
  • 419
  • 2
  • 8
0

The problem is that while the TextInput is being fired (not thrown...exceptions are thrown) you are not seeing it because the text box itself is using it. To catch this event you need to use the PreviewTextInput. So for example

    <TextBox TextInput="UIElement_OnTextInput" PreviewTextInput="UIElement_OnPreviewTextInput"></TextBox>

With event handlers...

    private void UIElement_OnTextInput(object sender, TextCompositionEventArgs e)
    {
        Console.WriteLine($"In text input event, {e.Text}");
    }

    private void UIElement_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
    {
        Console.WriteLine($"In preview text input event, {e.Text}");
    }

The first handler is never called, the second one always.

AQuirky
  • 4,691
  • 2
  • 32
  • 51
  • Problem is that preview TextInput Event is also not getting thrown. We're only seeing the KeyDown and KeyUp Events. Something is interrupting the event chain before the preview event is thrown – Shaboboo Aug 12 '19 at 13:09
  • *fired, not thrown, sorry – Shaboboo Aug 12 '19 at 13:17
  • I've never seen a situation where PreviewTextInput does not work. Put in the event handler. It will work. Do not rely on your tools. They are telling you the wrong story. If you simply start fresh...using the code you have posted...it will work. Now if it still does not work in your target application then that mean the problem is in code you have not posted and so I nor anyone else can help you., – AQuirky Aug 13 '19 at 04:31
0

Your handler is not called because other handlers have marked the event as handled. You can add an handler with AddHandler() and pass true for the third argument:

public MainWindow()
{
    var handler = new RoutedEventHandler(OnTextInput);
    myTextBox.AddHandler(TextInputEvent, handler, handledEventsToo: true);
}

private static void OnTextInput(object sender, RoutedEventArgs e)
{
}
Maxence
  • 12,868
  • 5
  • 57
  • 69