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
Related
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
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.
Literally, I want to know that.
In some case, .Focus() appear better than SetFocusedElement(). But another case, it's reversal. So I must know what's different things are there.
Additionally, by MSDN, .Focus() is for keyboard focus, and SetFocusedElement is for logical focus. But I can't feel different thing between logical focus and keyboard focus.
The keyboard focus is generally easier to understand, as that is effectively the control that would receive keyboard input if the user typed. So if you click in a TextBox it will receive keyboard focus and you can start typing. Other controls have other behaviors and may not really support the keyboard, but they can still get the keyboard focus.
For logical focus, your application can be made up of several parts. For example, most applications would have a ToolBar/Ribbon at the top and then their main content below. Now, imagine that your content is a TextBox that currently has the keyboard focus. When you click in a ToolBar/Ribbon control, the keyboard focus is moved to that control. But you really want to "remember" that the TextBox in your content had the keyboard focus before.
To achieve this the ToolBar/Ribbon will create new "focus scope". So when you click in the ToolBar/Ribbon control, you move the keyboard focus but the TextBox still has the logical focus for the window. That allows the TextBox to be given the keyboard focus back when the user is done working with the ToolBar/Ribbon.
The same holds true if you interact with another application, as your application doesn't have the keyboard focus. When you go back to working in your application, it uses the logical focus to know who had keyboard focus last (and should have it restored).
Using FocusManager.SetFocusedElement(), you can specify a UserControl of which you want to set focus on an element. So you can set focus on a control that is in a different part of your program.
Control.Focus() is just straightforward, you set focus on the said control (which is more intuitive).
Wild guess: you use FocusManager.SetFocusedElement() improperly, resulting in unwanted behaviors but bottom line, it's the same thing really.
Sidenote: "logical" focus and "keyboard" focus are 2 different things in WPF.
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
I have a small Silverlight 4 app that essentially consists of a grid containing a label and a combo box. When I click the label, I replace it with a second text box so that I can edit the label (much the way you can edit the name of a Silverlight control in VS2010).
I have a LostFocus event handler on the text box that will end editing when the control loses focus (restoring the updated label). Trouble is, users tend to click on the panel when they are done editing rather than on another control (or hitting Enter, which is also supported).
I tried adding a left mouse down event handler to the panel. However, that only fires when the text box does not have the focus (I guess the text box captured the mouse?)
Is there an approach to recognize that a non-input control was clicked that would enable me to terminate edit mode?
You can subscribe to Grid's MouseLeftButtonDown routed event using the following code:
panel.AddHandler(UIElement.MouseLeftButtonDownEvent,
new MouseButtonEventHandler(panel_OnMouseLeftButtonDown), true);
Unlike common events routed events are bubbled from innermost control to its parent, then to grandparent etc. In the same way you could subscribe to panel's parent to intercept clicks outside your panel.