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.
Related
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.
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
Is there a way to make an entire WPF Window inert after a button click?
The window is invoked via Window.ShowDialog() and after use, the window is no longer needed for interaction but I leave it open to remind the user of the inputs in TextBox's, ListBox's, and give visual feedback via OxyPlot and so on. I leave it to the user to close the window manually.
One solution is to disable all buttons but that's tedious and it still leaves TextBox's functioning. That's not optimal because for anything to be functioning creates the wrong impression that the Window remains for anything other than looking at. It would be better for every control to be non-functioning by a single setting.
I did it by putting a name on the WPF window code behind and then setting .IsEnabled false upon the appropriate button click. All buttons, combo boxes, text boxes, and even OxyPlot became inert at that point and most parts were greyed out.
Consider creating a dedicated boolean dependency property in your code-behind or viewmodel and binding IsEnabled of every TextBox to the property.
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
My WPF combobox is populated with a different set of strings each click of a button. There are other controls on the window as well. The combobox is the 'first' (top) in the window, but the text doesn't get highlighted. When the user tabs through the controls, the text DOES get highlighted, but when it's the first on the window, it doesn't.
Maybe i need to force a highlight on the individual textbox control 'within' the combobox itself, but how would i do this? I couldnt seem to find the internal 'structure' of this control anywhere. Could anyone help here?
Jack
to get the TextBox of Combobox you can use
TextBox TxtBox = (TextBox)myCombo.Template.FindName("PART_EditableTextBox", myCombo);
I'm not sure it's the best solution, but you can use FrameworkElement.FindName to access the child control -- it's guaranteed to be present in a combobox, because it's a key constituent part of the control.
That stated, is it not better to try and call .Focus() on the control? That is likely why when you tab, the highlight is provided.
Another option is to derive from ComboBox, and expose the child text box as a property allowing you to set it's selection, or add a method directly to the combobox to set it for you.