Problem:
I'm having trouble managing focus and item selection in a WPF ListBox with an embedded ListBox and some custom selection management in the code behind.
Background:
The "parent" ListBox is assigned a DataTemplate containing a "child" ListBox. I have added code to navigate using the up and down arrow keys from the parent ListBoxItem to the child items and from the child items back to the parent items.
When navigating back to a parent item which is not the first item in the first level list box the focus is always set to the first item and it is selected even though it is set in the program to a non-first item (e.g. parent item #2). I have traced through the code and the focus and selection is set to a non-first item but then another event to select and set the focus to the first item is always received.
There was another case on stackoverflow which was similar to what I am experiencing. The case is wpf listview lost the focus I tried all of the answers and responses in this case and none of them worked.
Does anyone have insight into why I can't programmatically select a non-first element in the parent ListBox?
Try using ListBox.IsSynchronizedWithCurrentItem = true then working with the list's collection view (if you're not explicitly creating one, you can use CollectionViewSource.GetDefaultView) to set the current item (ICollectionView.MoveCurrentTo()).
Selectors have a much more preferable method of dealing with selected items when working with the collection view, rather than SelectedItem.
I have been struggling with the Focus in ListBoxes too. Perhaps the answers to these two questions will help you further. Especially the trick with setting the focus on a Background thread is very very useful.
Deselect item in ListBox
Delay change of focus
Related
I have a UserControl in WPF and it contains a variety of controls in it... The most important being the DataGrid Control. The DataGrid control is bound to an Observable Collection list. This list filled with different items based on couple of filters selected by the user. Now, once the DataGrid displays all the data. I want to set the Focus on the first (Filters) combobox on my usercontrol. Is there any way to know when the DataGrid has completely loaded??? Is there any DataTrigger I could set that i could trigger to inform me that Grid was refreshed with new list and I can set the ComboBox to focus. Basically i'm not able to set the focus to the first control on my UserControl when the data in the DataGrid has been repopulated... Please let me know if anyone knows how to resolve this issue!!
Thanks in advance.
I hate to work in code behind but sometimes that is only way. This can be done in two ways according to me:
Use EventAggregator to raise the event from your ViewModel once you are done with your filtering logic in it. Listen to this event in view code behind and in the handler do firstCombo.Focus()
Second is bit dirty, So there must be the button or the last control after which you apply filter on your listview. In the buttonClickHandler/or any event of the last control (like selectionchange) directly do firstCombo.Focus(). In this case the moment you will press your button focus will move to combo.
Thanks
I have a big list (~10000 items) inside a ComboBox, that uses the VirtualizingStackPanel class. The scrolling performance is good, anyway I like to know how to identify the top item shown in the GUI - which is, not necessarily the one with index zero, but the one that is on top of the current scrolled item list. ? Thank you.
I use the FrameworkElement.IsVisible property. Using the method at the link below, you can also check to see if an element is partially visible(which would be useful in your case):
In WPF, how can I determine whether a control is visible to the user?
You could (by using a background thread or by doing a computation when the user scrolls in the combobox), check the items in the ComboBox to see if their FrameworkElement.IsVisible property were set to true. If so, you update that elements IsVisible property in its ViewModel. Now you have a collection in your ViewModel of items that are marked visible or not(and that are constantly updated concerning the visibility of the CoboBox item that it represents). Now you can find which is the first using .First(x=>x.IsVisible==true) on the collection of items.
I'm building a Windows Store app using XAML. I have a scrollable ListView that has its SelectedItem set on start.
Now, I have two requirements:
I would like the selected item to be always visible
In addition it
should be displayed in the middle of the list when possible (it's
not possible for the first element).
The first requirement I can partially fulfill by using list's LayoutUpdated event and list.ScrollIntoView(item) method, but this doesn't allow me to scroll down the list manually until the item is unselected.
For the 2nd requirement I have no ideas.
Ok, found out how to achieve that: http://fczaja.blogspot.com/2013/05/xaml-listview-scroll-selecteditem-to.html
I have Combo boxes inside a list box and whenever the list box is scrolled and the combo box is scrolled off of the screen the list box is firing a selection change event on the combo box and setting the selected index of the combo box to null.
If I scroll back and forth multiple times you will see the selected item display and be removed by scrolling the list back and forth.
Does anyone have an idea on ow to fix this? I need the combo box to retain the selected index.
I have even changed the collection that holds the Combo-box data to a list from an observable collection and it still does the same thing.
I am using silver light v4, .net 4
Thanks...
This is probably a result of the default virtualising nature of the ListBox. As items scroll off the displayed the items are actually removed from the Visual Tree. If you don't have too many items in the list set the ItemsPanel property of the ListBox to an ItemsPanelTemplate containing a simple StackPanel.
Better would be to cease using the selection change event in this scenario, use a binding on the SelectedItem property instead.
I had the same issue, but with a datagrid.
I tried this (preferable solution), but it didnt work for me.
Silverlight ComboBox and SelectedItem
So i had to go with this....
http://forums.silverlight.net/post/396922.aspx
Is there any way to tell when the containers are finished being made for a ListView?
A detailed explanation of what I've done so far
I have a ListView control that has a DataTemplate in one of its columns that contains a CheckBox Control.. I've figured out how to access the CheckBox dynamically using the object that the ListView is bound to.
ListViewItem lItem = (ListViewItem)ListView.ItemContainerGenerator.ContainerFromItem(trackToHandle);
CheckBox checkBoxToHandle = FindChild<CheckBox>(lItem, "CheckBox");
The problem is that the CheckBoxes "reset" (become unchecked) whenever I scroll too far or whenever I sort the columns.
I figured out this was because the VirtualizingStackPanel was only spitting out containers for those ListViewItems that were visible (or almost visible)..
And because the CheckBox is inside a DataTemplate that is defined in the XAML it gets thrown away everytime it goes out of view or when the list is sorted.
I got around this by creating a separate list of CheckBoxes and using the actual CheckBoxes "click" event to change the state of the corresponding CheckBox in my list.. then made a little method to go change the state of all the visible CheckBoxes whenever the user scrolls... as a result it appears like it should have in the first place.
Except when I sort the columns.
I tried making it re-do the CheckBoxes (like before) right after it'd sorted a column but it didn't work.
My best guess is that it doesn't immediately make the containers after I sort..
Is there any way to tell when the containers are finished being made for a ListView?
If you bind your checkboxes IsChecked property to a boolean property on your data context, then you will not have this issue.
The whole purpose of the VirtualizingStackPanel is reduce memory usage by not creating ListItem's unless needed.
In effect, you need to move the data side of the checkbox away from the control.