Why does TextBox Leave fire when mouse leaves? - winforms

I thought that Leave was supposed to fire when a control loses focus, and MouseLeave was supposed to fire when the mouse is no longer in the control.
I have a TextBox, and if I click in it, then take the mouse out, the Leave event fires. I'm using Leave to validate the entry in the box, like when people hit tab to go to the next control.
Does this mean that a TextBox can't have focus unless the mouse remains in it?

You must have some other code setting focus, because Leave does not fire when the mouse moves out of the control.

You should not be using Leave or LostFocus for validation purposes, instead use TextBox.Validating which is designed specifically for validation scenarios.
This way, if you want to have a Cancel button for example, you can just set its CausesValidation property to false and editor controls Validating events will not fire.

It doesn't matter if the mouse is in it. Property Focus refers to another type of event, when a component is ready to have its value changed, It doesn't matter if you use the keyboard or the mouse. Why don't you validate TextBox value when the Textbox looses Focus?

Related

Weird keyboard focus event order

Weird WPF ComboBox behavior:
I just noticed that in a WPF ComboBox, when the Keyboard Focus is set via the tab key (tabbing focus from the previous control), and TextBox inside the ComboBox ("PART_EditableTextBox") is the source of the tunneling event OnPreviewGotKeyboardFocus.
But for some strange reason, if the focus is received by clicking the mouse inside the control, then OnPreviewGotKeyboardFocus gets called twice: first time, the Source is the ComboBox itself; and the second time, the Source is, again, PART_EditableTextBox.
I also noticed that when settings Focusable to False on the ComboBox, you can still focus to it using the Tab key, but not using the mouse.
Does anyone know why this strange behavior?
From Microsoft doc.
The KeyboardNavigation class is responsible for implementing default keyboard focus navigation when one of the navigation keys is pressed. The navigation keys are: TAB, SHIFT+TAB, CTRL+TAB, CTRL+SHIFT+TAB, UPARROW, DOWNARROW, LEFTARROW, and RIGHTARROW keys.
The navigation behavior of a navigation container can be changed by
setting the attached KeyboardNavigation properties TabNavigation,
ControlTabNavigation, and DirectionalNavigation. These properties are
of type KeyboardNavigationMode and the possible values are Continue,
Local, Contained, Cycle, Once, and None. The default value is
Continue, which means the element is not a navigation container.
The combobox itself is a navigation container. This means that when you press tab, the container for the PART_EditableTextBox has KeyBoardNavigationMode set to Continue by default (this means that the focus go directly to the first non container element). The click event instead work differenctly, since you are not pressing a keyboard key, this behaviour is overrided, and the event is launched in order by any element that WPF will find in the visual tree. This is done to ensure that you can handle this event to do operation on your control, before the focus reach the Textbox. Also, you have to consider that this is necessary, cause WPF can't know exactly what you are going to click. That's why he must raise the same event from each layer of the combobox in order (if you click on the expander the focus won't stop inside PART_EditableTextBox).
So in short, if you are going to press TAB, WPF by default know that the final element that will be focused is the Textbox inside the combobox, that's why it's not needed by the combobox itself to raise the event. On the other hand, if you click on the combobox, WPF need to check which element will be focused at last and if there are some operation that must be done before switching focus.
Regarding the Focusable property finally, this one for a control indicates whether the control can receive focus, which means that the control can receive keyboard input after the user clicks on the control. Focusable is normally set to true for controls that are designed to accept user input. The part that can receive the keyboard focus, is the Textbox. So if you set Focusable = false inside the combobox, the KeyboardNavigation class will place the focus on the Combobox, instead of Textbox, cause it can't apply it's default behaviour

WPF: Controlling focus in a custom control

I am developing a custom control (say BoxControl) which will have many controls in it like a textbox, few buttons etc.
I will have many BoxControls in a row and while navigating via tabs, I want it to behave like when a BoxControl gets focus, it always passes the focus to its textbox and when its textbox loses the focus, the entire BoxControl loses the focu and passes the focus to next BoxControl.
Any ideas how can it be done?
You will need to add an event handler to your BoxControl to handle the GotFocus event and then put the focus on its text box.
You will need also to add an event handler to the LostFocus event of the textbox and then you can raise a custom event on BoxControl so it's controller can know that has to pass the focus to the next BoxControl
Hope it helps.
You can set Focusable property to false by a Setter in your custom control's template. Both on the control and on the various elements inside.

How do I find out where the focus is going in my WPF application?

I have a search screen in my WPF application. The screen is implemented as a UserControl in a TabItem of a TabControl. When the user switches to the Search tab, I want the focus to go into one particular field.
So I added a Loaded event handler to the UserControl tag in the Xaml and I called the Focus method of the control I want to have the initial focus in the Loaded event handler. This worked great until I upgraded the Telerik control library I'm using today. Now, when I switch to the Search tab, the focus is NOT in the field I want to have it, but I can't tell what control does have the focus.
The field I want to have focus already has GotFocus & LostFocus event handlers for other reasons. I remembered that in Win Forms, the LostFocus event handler arguments tell you which control is going to get the focus. So I put a breakpoint in my LostFocus handler & discovered that the arguments to the LostFocus event handler in WPF don't include that information.
How can I figure out where the focus is going without putting GotFocus handlers on every control in my UserControl?
Tony
You can try putting your breakpoint on the LostKeyboardFocus Attached Event instead of the LostFocus Event. It uses the KeyboardFocusChangedEventArgs Class which does have properties that show which element had focus and where the focus is going.
private void textBox1_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
textBox1.Text = ((FrameworkElement)e.NewFocus).Name ;
}
Try to press Tab Key and see if it helps you find the control in focus.
You can also use Snoop as suggested in this Q/A: Any tips on debugging focus issues in WPF?
For starters, Snoop shows the current focused element and the current
FocusScope in the status bar.
You can get it to show you all the GotFocus and LostFocus events:
1. Run your app.
2. Run Snoop.
3. Choose your app in the dropdown.
4. Click the binoculars ("Snoop") button.
5. On the right pane, click the Events tab.
6. Click to bring down the dropdown.
7. Scroll down to the Keyboard section and check GotKeyboardFocus, LostKeyboardFocus, and optionally the PreviewXXX events.
8. Now do what you need to do to manipulate focus and watch the Snoop window.
Similarly you can track the FocusManager events the same way.

Stop a WPF Textbox from losing focus

I have a WPF Textbox, that I want to check that the text value is correct before I allow it to lose keyboard/focus.
I have tried setting e.Handled in the InputBox_LostFocus & InputBox_LostKeyboardFocus events, but it doesnt seem to be achieving what I want.
Any suggestions on how I can lock focus to a Textbox?
The best way to do this is to handle the PreviewLostKeyboardFocus event which is fired while the event is tunneling down to your textbox. Set handle to true and nothing else will receive the notification (meaning focus will not be transfered away from your textbox). Hope this helps.
You can call Mouse.Capture on a UIElement. This will then give you every mouse event that hapens whether on the element or not. but its tricky to use. You can capture the mouse on your text box and register for lost capture events, when you lose capture you can recapture. you have to watch out for strange behaviors. Generally its bad practice (I think) to not allow a user to move off a field. what is better is to allow them to do whatever they want, but disable the button that they push after entering data until all fields are valid (or something similar)
Here are some links
other SO question
msdn sample code
the combo box uses mouse capture to tell if the user has clicked elsewhere in the app to close the combo box if its open if you click on another control (or outside the window)
I dont know if this technique will stop you tabbing off the element. there are two kinds of focus in a wpf app. You have logical focus and keyboard focus. Multiple elements can have logical focus at once (each within a focus scope). think for example a textbox can have logical focus while you are clicking a menu (which has logical focus as well). Keyboard focus can only be in one place at a time. You are going to make a lot of work for yourself. I would seriously consider if you are doing your interaction in the right way. You could spend days getting this interaction correct. If you stop your textbox losing focus, what happens if the user clicks the close button?
heres the msdn article on focus

WPF Mouse behavior when ComboBox is focused

When the WPF ComboBox is clicked and in-focus, the only interaction that occurs after that can be with the ComboBox. If anything else is interacted with, including the window functions (minimize, restore, close, resize) and any control in the window, the action is ignored and the ComboBox loses focus.
In addition, MouseEnter and MouseLeave on the window buttons are still active, but when MouseEnter on the window border(?) occurs, the mouse pointer does not change to the resize pointer. This behavior makes sense because of the ComboBox's use of the popup control. The popup control exists independently of the main visual tree and if i.e. the window moves or gets resized, the popup remains fixed floating above the main window.
I have tried using Reflector, to see what the ComboBox is doing, but I have not been able to find what I am looking for. Basically, I do not know if this behavior is coming from the window, the ComboBox, or if it has something to do with the popup. How can I solve this problem?
You're right on in your description there, the popup keeps all action focus until it itself loses focus. If you're trying to change the functionality of the ComboBox you may want to look at creating your own ControlTemplate that behaves differently and does not keep the default action of the popup control.
Hope this helps, not entirely sure what you're trying to do.
I know this question is old, but for anyone coming here looking for the answer, it is to use Mouse.Capture.
The ComboBox sets Mouse.Capture(comboBox, CaptureMode.SubTree) in OnIsDropDownOpenChanged. This ensures that all mouse events are captured by the ComboBox. When the Popup is closed Mouse.Capture(null) releases the mouse capture.

Resources