WPF popup listbox use keyboard for navigation - wpf

Can anyone suggest the solution how can I make navigation using down and up keys in listbox which come on popup.
Solutions like set selected items on keyup and keydown event are not working for me.
Should I make something more special then just set selected item in this case?

ListBox already implements selection navigation using keyboard when it is focused.
All you have to do is give it focus when you want, for example in the window that contains it:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Down)
{
listbox.SelectedIndex = 0;
listbox.Focus();
}
}
Because listbox.Focus(); will only give it focus but won't yet change the selection item (which will make the user hit's the "Down" button twice in order to do so) set the ListBox's SelectedIndex first.
Hope this helps

Related

ListBox fires lost focus event when lits ListBoxItem is selected, how to avoid this ?

ListBox fires lostfocus event when its ListBoxItem is selected, how to avoid this ?
I want LostFocus to fire only when something else outside it receives focus.
The thing is, ListBox never gets the focus, only it`s items do, so for this to work we`ll have to use them. Probably there`s some elegant solution for this, but here`s my take.
This I placed in code behind of the Window that contains ListBox:
private void myListBox_LostFocus(object sender, RoutedEventArgs e)
{
var focused = FocusManager.GetFocusedElement(this);
var item = focused as ListBoxItem;
if (item == null || !lbMain.Items.Contains(item.DataContext))
{
//do stuff
}
}
The second check in if statement is in case other ListBoxes are present. If your scenario is more complex you most probably will have to add some tweaks: for example if two ListBoxes have the same ItemsSource.
try to set on ListBoxItem the property Focusable to False. Eventually on elements inside your ListBoxItem DataTemplate.

WPF DataGrid loses focus after row delete / cut

I have a DataGrid implemented in an MVVM/Prism application. The DataGrid supports Cut/Copy/Paste/Delete through a context menu and keyboard gestures.
I find that when a row is deleted/cut the entire DataGrid loses focus and keyboard focus moves to the last focused control.
Is there anyway to prevent this?
After removing a row I may want to re-paste into the DataGrid. Furthermore if the grid is empty there is no way at all for it to get keyboard focus. Clicking an empty grid does not give it focus.
Here is a similar question, but it doesn't solve the issue for me:
DataGrid Looses Focus When Delete Key is Pressed
You could set the DataGrids Focus in the PreviewKeyDown-Event
private void TheDataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
{
var grid = (DataGrid)sender;
FocusManager.SetFocusedElement(Window.GetWindow(grid), grid); //not tested
}
}
If you dont want to put code in code-behind use AttachedProperties in combination with the DependencyPropertyChanged-Event.
How to set set focus.
A dirty solution might be to handle the LostFocus event exposed by DataGrid and set focus on the control.
It arguably marginally infringes on the MVVM pattern i.e keeping the view dumb as hell, but it's still view code.

WPF drag and drop from a ListBox that has SelectionMode=Extended

I have a ListBox and want the selection-mode to be extended. Also I want have to implement drag and drop functionality. The problem now is, that if the mouse is clicked on a selected item, it will be immediately be selected as single selection instead of waiting to the mouse-up-event for doing this.
Due to this behaviour, start dragging multiple items is for the user quasi impossible because always he clicks on the selection to start dragging, the selection changes to the item that is under the mouse and starts the drag-operation with this item.
Is there a good workaround for this problem or does even exists an official solution?
Here's what I've done. In your DragDrop code, subscribe to the PreviewMouseLeftButtonDown. If the item you are already clicking on is selected, then set e.Handled to true.
In my sample below, I identify a part of the list box item as a drag grip (with bumps) so that I can distinguish between the item and a drag surface. I just had to get the list box item data template and the drag and drop behavior to agree on a name of the drag grip element.
The PreviewMouseLeftButtonDown from my work in progress:
private void ItemsControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
dragStartPoint = e.GetPosition(null);
ItemsControl itemsControl = this.AssociatedObject as ItemsControl;
if (itemsControl != null)
{
this.sourceItemContainer = itemsControl.ContainerFromElement((Visual)e.OriginalSource) as FrameworkElement;
}
// If this is an multiple or extended selection list box, and on a drag grip, then ensure the item being hit is selected
// This prevents the ItemsControl from using this MouseDown to change selection, except over a selected item's drag grip.
if ((this.IsMultipleSelectionListBox() == true) && (this.IsOriginalSourceDragGrip(e) != false) && (this.IsSourceListBoxItemSelected() == true))
{
e.Handled = true;
}
}
The easiest workaround i can think of would be to change the ListBoxItem to select on MouseUp not Down like so and change the ContainerGenerator to serve your custom ListBoxItems:
public class CustomListBoxItem : ListBoxItem
{
protected override void OnMouseLeftButtonDown( MouseButtonEventArgs e )
{
//do nothing
}
protected override void OnMouseLeftButtonUp( MouseButtonEventArgs e )
{
base.OnMouseLeftButtonDown( e );
}
}
You might need some MouseLeave/LeftButtonDown logic if you want to prevent different items selecting when moving through the List while holding the mouse button down.
Use PreviewMouseLeftButtonDown to add the selected items for the drag operation.

Remove select all from combobox WPF

I have combobox in WPF application that when the user clicks on it, it selects all the text. How can I change the behavior of this to when the user clicks it just set the typing cursor like a normal textbox?
Try
<ComboBox IsEditable="True" />
According to Reflector, the ComboBox code contains this:
private static void OnGotFocus(object sender, RoutedEventArgs e)
{
ComboBox box = (ComboBox) sender;
if ((!e.Handled && box.IsEditable) && (box.EditableTextBoxSite != null))
{
if (e.OriginalSource == box)
{
box.EditableTextBoxSite.Focus();
e.Handled = true;
}
else if (e.OriginalSource == box.EditableTextBoxSite)
{
box.EditableTextBoxSite.SelectAll(); // <==
}
}
}
This method is registered for the GotFocus event in the static constructor using the EventManager:
EventManager.RegisterClassHandler(typeof(ComboBox), UIElement.GotFocusEvent, new RoutedEventHandler(ComboBox.OnGotFocus));
So, I think you can only change that behavior by deriving a custom control from ComboBox and override this event registration by your own method which replaces the call to SelectAll() with another method which sets the caret to the correct position. However, I do not know how to set the caret to the click position. You might have to use Reflector on the TextBox to find that...
Seems that I had to solve similar issue.
It's quite tricky, but the way I solved is to set IsEditable to false/true from code, at the same time I set the focus on TextBox.
Not the pretties way but does the job.

WPF TextBox - don't hide the selection

WPF's TextBox (System.Windows.Controls.TextBox) appears to highlight selected text only when it has the focus. I need to make a TextBox continue to show the selection when focus is lost.
In a standard Win32 EDIT control I could achieve this with ES_NOHIDESEL. How can I get the equivalent in WPF?
You can handle the LostFocus event and set the event arg to e.Handled = true. In this way the TextBox will not know that it lost focus and will keep your selection.
private void myTextCtrl_LostFocus(object sender, RoutedEventArgs e)
{
e.Handled = true;
}
This will give you a similar thing to what you are looking for, but unlike the Win32 way, it will still show your selection in the highlighted color instead of dark gray.
If you really want to go through the effort you could also write XAML for <TextBox.SelectionBrush>.
Another way is to use FocusManager, you can read about this method here.

Resources