Weird keyboard focus event order - wpf

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

Related

How to set focus to a default child control unless the user clicks on a different child control?

I have a pretty simple use case but I cannot make it work right. I've got a ListView whose item template is a Note custom UserControl:
Each Note has a few simple controls as shown.
I want this to work so that if a row is selected programmatically or by clicking somewhere in it, it sets focus to the first textbox in that row. But if you click on a control in the row, it activates that control (i.e. lets you edit the Exhibit contents or click the Delete button).
If I don't do anything to set focus, clicking on the row highlights the row but doesn't set focus to any child control.
Within the Note control I have tried this:
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
base.OnGotKeyboardFocus(e);
text.Focus();
}
text is the name of that first TextBox, and it does set focus, but it also does this if I click directly on the Exhibit textbox or Delete button, making them unusable.
So, how can I enable the focusing that I want when the container control gets focus, UNLESS it got that focus via a click on a specific child control (which should then keep the focus)?
After a bit more searching, I found the correct way to implement this: at the root of the container control (the Note UserControl in my case), you can specify the name of the control to be the default focus control:
FocusManager.FocusedElement="{Binding ElementName=text}
Not sure how I missed that one.

How to set focus to UserControl (make it selectable)?

I need to set focus to UserControl itself, not its child.
Otherwise I cannot implement insertion from the buffer. :(
Setting Focusable=True doesn't help.
Google and SO tells only how to set focus to UserControl child.
My control contains:
- Toolbar with several buttons bound to commands of the corresponding
VM
- TextBox which is the input for the filter
- DataGrid - list of items.
I need to bind Ctrl+V command to VM. But to handle this gesture UserControl must have focus within. When there are no items in the grid (VM's collection is empty) buttons are disabled and the only element which can get focus is TextBox. But it handles Ctrl+V in its own way and I don't want to change this behavior.
Thus, I need something to set focus to when I click the area of UserControl.
I believe UserControl is the best candidate for it.
But I don't know how to make it selectable.
The whole problem was in my misunderstanding of controls' behavior.
This SO question clearly shows it I believe.
Thus, setting UserControl.Focusable = true is not sufficient. To make it navigatable via keyboard IsTabStop must be true also. And to make UC selectable by mouse click we should call Focus() in mouse eventhandler. That's it.

Why does TextBox Leave fire when mouse leaves?

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?

TextBox Cursor is NOT blinking

I have a WPF datagrid (4.0) with a custom column (derived from DataGridTextColumn).
In GenerateEditingElement I create a custom textbox control (with an additional button) and like to set the cursor into it so that the user can directly start editing.
The closest I get is that the caret is shown but is not blinking and I need an additional click to start editing.
All other stuff (binding, ...) is working nicely
Any ideas?
Since the caret is shown, but not blinking, then I am guessing your control has Logical Focus, but not Keyboard Focus.
How are you setting the control as Focused?
myControl.Focus(); will give the control logical focus, but it won't respond to keyboard events because it doesn't have Keyboard focus. To give an element KeyboardFocus, use
Keyboard.Focus(myControl);
This is because WPF allows you to define multiple Focus Scopes, and each scope can have it's own focused element, however only one control in the entire application can have Keyboard Focus

wpf selecting controls inside a listbox

I have a textbox and some labels inside the data template of bounded listbox.
When I click on any label the whole item is highlighted in blue, but when I click directly on a different textbox the selection does not change.
Is there a way to make the selection of the listbox change even when a textbox is clicked?
thanks
This is what I've exactly asked few days ago, see post: "WPF: Trigger SelectedIndex changed whilst clicking on any control within a ListBoxItem area"
basically there are few solutions, using code behind and XAML, but I've not verified latter approach yet
The reason is because the TextBox handles the click event in order to receive focus. There are a number of ways to handle this, including but not limited to:
stop the TextBox handling mouse events (which prevents the user from focussing it using the mouse)
use an eventhandler when the TextBox gains focus (or PreviewClick or similar), to select the parent ListItem

Resources