8

How can I tell when the default textbox context menu is about to open (before it opens) or after it has closed (not before, after)? The ContextMenuOpening and ContextMenuClosing events don't seem to fire when I'm using the standard, built-in menu. I'm guessing I could simply recreate the menu and populate it with standard commands, but that does seem to be a bit overkill.

The reason for this specifically, is I have a templated control that has a textbox swapped in when in 'Edit' mode. That control automatically drops out of edit mode when the textbox loses focus. Problem is when the context menu pops up, the textbox loses focus, and thus it drops out of edit mode, and the context menu disappears instantly.

What I want to do is just before the context menu opens, set a flag to short-circuit LostFocus event code on the textbox. Then after the context menu closes, I need to clear that flag but I also need to detect if the control that now has the focus is still the textbox, and if not, then process the code as if it did lose focus. (Alternately I could test an event prior to it closing if I knew which control will have the focus once it does close. It would achieve the same effect.)

This is needed to handle the specific case if someone shows the context menu (and as such the textbox technically doesn't have focus anymore) but then clicks elsewhere in the UI which dismisses the context menu, because I then need to detect that the textbox has in fact lost focus and as such the control should drop out of edit mode. But if the user dismisses the context menu by clicking back in the textbox, then I don't want that LostFocus event to fire.

Make sense?

M


UPDATE: Technically this question wasn't answered although I marked it as such since the responders did help me solve my problem. But as for the actual question here, it looks like the answer is 'You can't'.

The good news is since the default textbox context menu is just three standard items, it's easy to duplicate by adding this to the resources somewhere...

<ContextMenu x:Key="DefaultTextBoxContextMenu">
    <MenuItem Command="ApplicationCommands.Cut" />
    <MenuItem Command="ApplicationCommands.Copy" />
    <MenuItem Command="ApplicationCommands.Paste" />
</ContextMenu>

...and attach it like this...

<TextBox x:Name="EditTextBox"
    ContextMenu="{StaticResource DefaultTextBoxContextMenu}"
    ContextMenuOpening="EditTextBox_ContextMenuOpening"
    ContextMenuClosing="EditTextBox_ContextMenuClosing" />

...then your eventing works as you would expect. Still odd if you ask me, but a trivial work-around anyway so I won't complain.

M

Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286

2 Answers2

7

When the textbox's context menu opens the textbox loses keyboard focus, but retains logical focus. In other words, its LostKeyboardFocus event will fire but its LostFocus event will not. The textbox's IsFocused property remains true when the context menu is open. Based on your description of the problem, you should be able to rely on logical focus to determine when to end "edit mode" in your control.

Joe White
  • 94,807
  • 60
  • 220
  • 330
Josh Smith
  • 884
  • 6
  • 9
  • 2
    Welcome to StackOverflow! Looking forward to more great answers. – Rick Sladkey Apr 15 '11 at 06:17
  • Josh, I read the timestamps backwards. You were '12' and he was '11' but I forgot the 'ago' part. I've switched the answer to you! Check out the comments under his however for some other questions I have related to this issue. – Mark A. Donohoe Apr 15 '11 at 06:32
  • Just so you know: http://meta.stackexchange.com/questions/28416/what-is-the-policy-on-signatures-and-links-in-answers/52486#52486 – H.B. Apr 15 '11 at 11:55
  • @H.B. Oops, I didn't know about the "no links in signature" rule. I've removed it from my post. – Josh Smith Apr 15 '11 at 14:49
  • Hi @Josh Smith Apparently you've got quite the rep with WPF! Didn't know that about you but as they say Google is my friend. SO... between this, and a similar question here... http://stackoverflow.com/questions/5850784/how-do-you-solve-this-lostfocus-lostkeyboardfocus-issue, I've figured this out as per my answer there. BUT... it seems 'hackish' to me although it does work! That said, can you shed any light on this? Is there a better way? Again, there I explain why neither LostFocus nor LostKeyboardFocus by themselves will give me what I wanted, hence the lengthy solution. Thoughts? – Mark A. Donohoe May 02 '11 at 04:02
1

By default a TextBox still reports true for IsFocused while the default context menu is open but reports false for IsKeyboardFocused. That is to say, LostFocus is not raised on the TextBox when the context menu is opened but will be raised if the context menu is closed by selecting some other control. This sounds like precisely the behavior you are looking for.

You can show this default behavior with a small test program:

<Grid>
    <StackPanel>
        <TextBox Text="Some text one"
                 GotFocus="TextBox_GotFocus"
                 LostFocus="TextBox_LostFocus"/>
        <TextBox Text="Some text two"/>
    </StackPanel>
</Grid>

and the code-behind:

    private void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        Debug.WriteLine("GotFocus");
    }

    private void TextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        Debug.WriteLine("LostFocus");
    }

If you are not getting this default behavior in the context of your larger application, then there might be a focus scope issue interfering.

Rick Sladkey
  • 33,988
  • 6
  • 71
  • 95
  • Aaaah! I've been using LostKeyboardFocus, not LostFocus! DAMN that was simple! LOL!! Voted up and accepted! BTW, you beat Josh by one minute so you get the answer, but I'm voting you both up. – Mark A. Donohoe Apr 15 '11 at 06:25
  • One other question though... am I right that the Context Menu events don't fire if it's just the default context menu, or am I missing something there too? – Mark A. Donohoe Apr 15 '11 at 06:27
  • 1
    I think he beat me by one minute. You can switch the answer to him! – Rick Sladkey Apr 15 '11 at 06:29
  • More importantly, I have a style that uses the IsKeyboardFocusWithin to style itself (the textbox is inside) but again, when the context menu opens up, since it is the Keyboard Focus that switches, the style changes too. My work-around was to create a second style that uses the IsEditing on the control to handle that case, but it's a bit inelegant to me. Thoughts? – Mark A. Donohoe Apr 15 '11 at 06:30
  • 1
    If IsKeyboardFocusWithin style is something subtle then having the style change when the context menu is up is not bad. If it is jarring, then you need some other state and your IsEditing seems like the right tool for the job. – Rick Sladkey Apr 15 '11 at 06:38