none
ListView with ComboBoxes in header: keyboard navigation

    Question

  • I've got a ListView with ComboBoxes in the headers (meant for filtering in the list, see sample below). Keyboard navigation is awkward and I cannot get it right:

    • If the user presses cursor(arrow)-up when the first item in the list is selected, focus moves to the ComboBox in the header of the first column.
    • And then it's trapped there, pressing down walks the elements in the ComboBox; it does not moves focus back to the list.
    • Pressing TAB moves focus to the next control in the window. There doesn't seem to be a way to get focus to the list elements anymore by keyboard.

    I guess what I want is that a) pressing 'arrow up' on the first element of the list does not transfer focus to the header, and b) that the list and header part can be separately reached by tabbing into them. I cannot seem to get this right. 

    Can this be done?

    Sample code:

    <ListView> <ListView.View> <GridView> <GridViewColumn> <GridViewColumn.Header> <ComboBox Width="150"> <ComboBoxItem Content="Filter Item 1" /> <ComboBoxItem Content="Filter Item 2" /> </ComboBox> </GridViewColumn.Header> </GridViewColumn> <GridViewColumn> <GridViewColumn.Header> <ComboBox Width="150"> <ComboBoxItem Content="Filter Item 1" /> <ComboBoxItem Content="Filter Item 2" /> </ComboBox> </GridViewColumn.Header> </GridViewColumn> </GridView> </ListView.View> <ListViewItem Content="Item 1" /> <ListViewItem Content="Item 2" /> <ListViewItem Content="Item 3" /> <ListViewItem Content="Item 4" /> </ListView>

    <TextBox or other control />

    Thanks!

    Tuesday, August 21, 2012 9:25 AM

Answers

  • Not quite, this way you have to use CTRL+TAB to get from filter to list, which will confuse a lot of users.

    Anyway, I am not allowed to spend any more time on this. So far, the main part of the problem (focus is moved to the filter on up arrow) is solved like this:

    private void testListView_PreviewKeyDown(object sender, KeyEventArgs e)
    {
    	if (testListView.SelectedIndex == 0)
    	{
    		if (e.Key == Key.Up)
    		{
    			e.Handled = true; // Don't move focus to the header/filter row on arrow-up.
    			return;
    		}
    	}
    }
    As for the tab behavior, I've left KeyboardNavigation.TabNavigation, ControlTabNavigation and DirectionalNavigation at their defaults. All other combinations seems to make things worse.

    Anyway, thanks for your effort Wizend/elmar!
    • Marked as answer by Dropmans Wednesday, August 22, 2012 7:11 AM
    • Edited by Dropmans Wednesday, August 22, 2012 7:21 AM
    Wednesday, August 22, 2012 7:11 AM

All replies

  • Hi,

    perhaps you should take a look at this thread:

    http://stackoverflow.com/questions/359758/setting-tab-order-in-wpf

    Regards,

    elmar

    Tuesday, August 21, 2012 2:05 PM
  • Thanks, but there is nothing in that thread that I didn't know. I've been playing around with a combination of KeyboardNavigation.TabNavigation/DirectionalNavigation and a PreviewKeydown handler, but cannot get the desired effect. The desired order I want is:

    - On tab of a previous control, the 1st ComboBox in the header gets focus. 

    - Next tabs move focus to next ComboBoxes. On last ComboBox, tab moves focus to the list.

    - The next tab moves focus to the control below the ListView. 

    For Shift-Tab vice versa.

    I did succeed in blocking the focus move from the list to the header row though (by using tje mentioned PreviewKeydown handler).

    Tuesday, August 21, 2012 2:14 PM
  • Did you already try

    <Control KeyboardNavigation.TabIndex="0" ... />
    

    Doing this you should be able to define your own 'costum' tab route.

    Regards,

    elmar

    Tuesday, August 21, 2012 2:52 PM
  • TabIndex is used to set the tab order over controls. I need to influence the tab order & behavior IN the (ListView) control.

    I can do that (and get close to the desired behavior I described above), by setting KeyboardNavigation.TabNavigation="Continue" (so you can tab through the ComboBoxes in the header). But then a tab on the list moves the selected item to the next. This is strange (other lists do not behave that way). Instead, I would want to move focus to the next control (again, as described in my response above).

    Tuesday, August 21, 2012 2:58 PM
  • I have tested your sample and I think now that you have already got your desired behaviour.

    When the focus is on combobox1 you get to the list by <CTRL+TAB>. Another <TAB> brings you to the next control (e.g. TextBox). Another <CTRL+TAB> and you get to combobox2. And after another <CTRL+TAB> brings you back to combobox1.

    So, no need for additional code!

    Best,

    elmar

    Tuesday, August 21, 2012 5:51 PM
  • Not quite, this way you have to use CTRL+TAB to get from filter to list, which will confuse a lot of users.

    Anyway, I am not allowed to spend any more time on this. So far, the main part of the problem (focus is moved to the filter on up arrow) is solved like this:

    private void testListView_PreviewKeyDown(object sender, KeyEventArgs e)
    {
    	if (testListView.SelectedIndex == 0)
    	{
    		if (e.Key == Key.Up)
    		{
    			e.Handled = true; // Don't move focus to the header/filter row on arrow-up.
    			return;
    		}
    	}
    }
    As for the tab behavior, I've left KeyboardNavigation.TabNavigation, ControlTabNavigation and DirectionalNavigation at their defaults. All other combinations seems to make things worse.

    Anyway, thanks for your effort Wizend/elmar!
    • Marked as answer by Dropmans Wednesday, August 22, 2012 7:11 AM
    • Edited by Dropmans Wednesday, August 22, 2012 7:21 AM
    Wednesday, August 22, 2012 7:11 AM