Focusing the last ListBoxItem in code-behind [duplicate] - wpf

I have a defined list box like this:
var listBox = new ListBox();
listBox.Items.Add(1);
listBox.Items.Add(2);
listBox.Items.Add(3);
And I want to set focus directly to an item in the listbox.
If I do this:
listBox.SelectedIndex = 0;
listBox.Focus();
The focus is set to the entire listBox, so if I press arrow down to move the selection to the item below, I have to press the arrow twice. First time the focus jumps from the entire listBox to the first item, and then when I can press the arrow again and the selection finally jumps down.
I want to set the focus directly to that first item, so I don't have to press the arrow twice.

var listBoxItem =
(ListBoxItem)listBox
.ItemContainerGenerator
.ContainerFromItem(listBox.SelectedItem);
listBoxItem.Focus();

Here's a similar (if not equal) question Setting focus on a ListBox item breaks keyboard navigation
And the code (I don't mess with WPF so I can't guarantee this works, but it was accepted on the thread I linked so it might):
private void Window_Loaded(object sender, RoutedEventArgs e)
{
listBox.Focus();
listBox.SelectedIndex = 0;
((ListBoxItem)listBox.SelectedItem).Focus();
}

You can't use Focus.() on a listbox item. However you can select items which is pretty much the same thing as you are looking to do. listbox.SelectedIndex = 0;

Related

WPF: Reset ListView selected index after items refreshed

I have an ListView defined in XAML, and it's ItemsSource is set code-behind. ItemsSource is not a property, so I dont want bind it to observable collection.
To update GUI I call ListView.Items.Refresh() method after selected index was changed (I do some work on selection changed and list view items are display the result).
After that two situations may occurs:
if I change selected item of ListView by mouse, selected index is changed right and stay in its place after Refresh() method was called;
if I change selected item by arrows up and down on keyboard, selected index is always jumps to first item.
My question is what may I do to make selected item index of ListView right after selected item was changed by keyboard and items were refreshed in code?
Instead of SelectionChanged event why dont you try MouseLeftButtonDown event and KeyDown event.
This will solve your issue.
Snippet as follow,
private void lst_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
item = lst.SelectedItem;
fnTask();
}
private void lst_KeyDown(object sender, KeyEventArgs e)
{
item = lst.SelectedItem;
fnTask();
}
private void fnTask()
{
lst.Items.Refresh();
lst.SelectedItem = item;
}

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 popup listbox use keyboard for navigation

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

DataGrid + ContextMenu: How to get the row under the right click

In Silverlight 5, I have a DataGrid with a ContextMenuService.ContextMenu. If you click a row to select, then right click, you just check the grid.selecteditem for context. However, if you right click a row without selecting it, you don't have that row's context when the menu opens. How do you get the DataContext row of the grid that was right clicked on when the context menu opens? The right click on the grid seems to be an option, but it is intercepted for the contextmenu and does not fire unless a contextmenu is already open/in focus.
I have found tons of examples of getting around the original issue with Silverlight 4 and detecting the rown on right click. However, the contextmenu now intercepts the rigth click of the grid, so those no logner work. I also found posts on 'bugs' with the initial relase of the ContextMenu. All these posts/blogs are making it hard to find a current answer or solution.
yeah it seems like Silverlight 5 has changed something that breaks the old tricks.
We've been doing this: add row enters on row load handler. EG:
private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.MouseEnter += new MouseEventHandler(Row_MouseEnter);
e.Row.MouseLeave += new MouseEventHandler(Row_MouseLeave);
}
void Row_MouseEnter(object sender, MouseEventArgs e)
{
DataGridRow dgr = sender as DataGridRow;
IncidentGrid.SelectedItem = dgr.DataContext;
}
pretty ugly i know, but it's working.
Besides Roger's concerns of accuracy, I didn't want to wire up those events on every row because my grid is quite large, and I have to keep it lean.
I found a solution here...
https://mutelight.org/silverlight-datagrid-make-right-click-select-a-row
Apply just one event handler to the grid's MouseRightButtonDown event. The event args has the mouse position and you can use VisualTreeHelper to find which DataGridRow the mouse is over. Then that row's DataContext will have your SelectedItem.

Scrolling a listbox with page up/down

I had an ItemsControl, which you could use page up/down buttons to scroll expectedly. I switched it with a ListBox, to apply (thru triggers) a new DataTemplate when an item is selected.
Everything works fine, until using pageup or pagedown buttons. Instead of scrolling one page, it scrolls till the end or the beginning.
My previous attemps:
Not changing the item height when DataTemplate changes
Removed IsSelected=True trigger completely
All SelectionMode values
Do I miss something trivial?
private void RaiseKeyDownUpEventsOnEntitiesBox(Key key)
{
KeyEventArgs keyEventArgs = new KeyEventArgs(
InputManager.Current.PrimaryKeyboardDevice,
Keyboard.PrimaryDevice.ActiveSource,
System.Environment.ProcessorCount, key);
keyEventArgs.RoutedEvent = UIElement.KeyDownEvent;
entitiesBox.RaiseEvent(keyEventArgs);
keyEventArgs.RoutedEvent = UIElement.KeyUpEvent;
entitiesBox.RaiseEvent(keyEventArgs);
}
Page Down
RaiseKeyDownUpEventsOnEntitiesBox(Key.Next);
Page Up
RaiseKeyDownUpEventsOnEntitiesBox(Key.Prior);
Indeed, I missed something trivial. I forgot to remove the ScrollViewer outside the ItemsControl. I guess, this creates a confusion, since ListBox has its own ScrollViewer.
This raised another question. Previous ScrollViewer were automaticcally scrolled down from code behind. Now, that I can't reach the ListBox's ScrollViewer, I can't call its LineDown method. Here is my workaround:
// Responses is the ItemsSource
Responses.Add(e);
// xResponses is the ListBox
var item = xResponses.ItemContainerGenerator.ContainerFromIndex(0);
ScrollBar.LineDownCommand.Execute(null, item as IInputElement);
In the beginning, item might evaluate to null, however this does not create a problem. After adding a few items, luckily before we need to scroll, a container is returned successfully. Note that index is not important here, all we need is an IInputElement inside the ScrollViewer.

Resources