locked
ListBox Focus Issue On ItemSource Update

    Question

  • I have an app where Focus is very important. All is working well except when a listbox is updated (Complete change of items or simply the addition or removal of an item)

    If you have a simple Xaml page with a button and a listbox and the listbox's bound data is updated then Focus will shift to the button. Is there an event I can hook into to programmatically switch focus back the listbox?

    My second issue is when the entire list changes along with the selected item, the first item in the list which is the selected item has a border around it (To indicate it is Focused) even though it's not focused and the button doesn't change colour to indicate it is focused even though it is. Stranger still, if I change focus from the button to the list box, the item that was focused before the list updated (eg the third item in the list) shows as being focused as well as the selected item. If I move between the button and the list box the third item will show and lose the border linked to Focus Visual State.  As soon as I press left or right on the list box the focus shifts to the selected item and everything works as normal.

    Any ideas would be greatly appreciated.
    Thanks

    Friday, May 30, 2014 2:24 AM

Answers

  • Why bind to a list? ObservableCollection extends List and implements INotifyCollectionChanged. Helps with binding if the list items are added or removed. I don't think List does updates the UI when the items are changed.
    Saturday, May 31, 2014 7:21 PM

All replies

  • In the visual state groups for the ListViewItem, there are different groups for Focus and Selection. If an item has focus it may not be selected. Pressing the arrow keys causes the next item to be selected which seems to fix this behavior.

    The event you're probably looking for is the CollectionChanged event from your collection.

    If you're using MVVM and the source is in the viewmodel, your ObservableCollection<Item> Items will have this event.

    In your code behind, create an event handler to focus your listbox when the collection is changed.

           {           
                ViewModel viewModel = new ViewModel();
                DataContext = viewModel;
                viewModel.Objects.CollectionChanged += Objects_CollectionChanged;
    
            }
    
            private void Objects_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
            {
                MyListBox.Focus(FocusState.Programmatic);
            }


    As for the other problem about multiple items having focus, my guess is that the ListViewItem container is being re-used and it has the focused visual state from the previous item which was focused and selected. The panel recycles item containers and stores the private variables for reuse. I'm not saying visual states are private variables but I would guess it's something similar going on in this case too.  If you're using a UserControl as your ListViewItem's Content then the constructor and Loaded event will be called again so you can update your UI if necessary or change visual state. Do you want all items to be unfocused when the item is loaded? If you want the same object to be focused in the new collection that was focused before, then why remove the object from the collection in the first place? If that's the case then update the collection using Add and Remove instead of Clear(). 


    Friday, May 30, 2014 2:53 AM
  • Thanks Bryan,
    Sadly it's bound to a list so I don't have access to CollectionChanged.

    The good news however is that I seem to have fixed the issue by changing from a ListBox to a GridView.  It completely solved issue 2 and also issue 1 as long as I have the data collection and selected item ready in my view model before loading the page.  In cases where this is not possible then I've implemented a check on the grid view to see if it has items.  If not then I simply select something else to focus.  The data is then loaded and bound. Although the user then has to press the down arrow on their remote control or keyboard, it's at least now very clear where the focus is sitting.

    Thanks again for the help.


    • Edited by StormENT Friday, May 30, 2014 4:08 AM
    Friday, May 30, 2014 4:08 AM
  • Why bind to a list? ObservableCollection extends List and implements INotifyCollectionChanged. Helps with binding if the list items are added or removed. I don't think List does updates the UI when the items are changed.
    Saturday, May 31, 2014 7:21 PM