Moving focus inside ListView

BitSmithy 2,206 Reputation points
2023-09-27T15:24:47.09+00:00

Hello,

I have a ListView

        <ListView x:Name="lvList" Width="200" Grid.Column="0" Margin="0,100,0,0" SelectionMode="None">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment"  Value="Stretch"/>
                    <Setter Property="HorizontalAlignment"  Value="Stretch"/>
                </Style>
            </ListView.ItemContainerStyle>
            <ListViewItem>
                <StackPanel Orientation="Horizontal" >
                    <CheckBox Style="{StaticResource CheckBoxStyle}" Width="10"/>
                    <TextBox x:Name="tbxCanvasX" Header="X" HorizontalAlignment="Stretch"></TextBox>
                </StackPanel>
            </ListViewItem>
        </ListView>

I adds items to the ListView code behind

            ListViewItem li = new ListViewItem();
            
            StackPanel sp = new StackPanel();
            sp.Orientation = Orientation.Horizontal;
            CheckBox cbx = new CheckBox();
            cbx.Style = this.Resources["CheckBoxStyle"] as Style;
                  
			TextBox tbx = new TextBox();
			
            sp.Children.Add(cbx);             
			sp.Children.Add(tbx);             
			li.Content = sp;

            lvUIEPropertiesMenu.Items.Add(li);

Now, I want to walking using TAB key throught ListViewItems. But If focus is on first TextBox on the list and I press TAB key, the Focus not moves to the next ListViewItem, but to other control beyound the ListView. I want focus moved to the next ListViewItem.

Developer technologies | Universal Windows Platform (UWP)
0 comments No comments
{count} votes

Accepted answer
  1. Anonymous
    2023-09-28T03:42:15.22+00:00

    Hello,

    Welcome to Microsoft Q&A!

    I want focus moved to the next ListViewItem.

    To achieve such behavior, you will need to handle the KeyDown and KeyUp events of all the ListViewItems to manually control the focus status.

    First, please set the TabNavigation property of the ListView as Cycle.

     <ListView x:Name="lvList" Width="200" Grid.Column="0" Margin="0,100,0,0" TabNavigation="Cycle" SelectionMode="None" >
    
    

    Then you add the same the KeyDown and KeyUp event handler to all the ListViewItems. Inside the event, you need to manually set focus when tab is pressed. Since the TextBox will automatically receive focus if you set focus to the ListViewItem, so we need to disable the TextBox in KeyDown and switch it back in KeyUp .

    The event code is here:

     private void MainPage_Loaded(object sender, RoutedEventArgs e)
     {
         // set the fisrt item as focused if needed
         ListViewItem Item = lvList.ContainerFromIndex(0) as ListViewItem;
         Item.Focus(FocusState.Programmatic);
     }
    
     private void ListViewItem_KeyUp(object sender, KeyRoutedEventArgs e)
     {
         // make textbox work again.
         ListViewItem currentitem = sender as ListViewItem;
         TextBox targetBox = FindChild(currentitem) as TextBox;
         targetBox.IsTabStop = true;
     }
    
     private void lvList_KeyDown(object sender, KeyRoutedEventArgs e)
     {
         if (e.Key == Windows.System.VirtualKey.Tab)
         {
             //When the tab pressed,get current item index
             ListViewItem currentitem = sender as ListViewItem;
             var index = lvList.IndexFromContainer(currentitem);
             // then get the next item and set focus
             var count = lvList.Items.Count;
             if (index + 1 > count - 1)
             {
                 //back to first item
                 ListViewItem nextItem = lvList.ContainerFromIndex(0) as ListViewItem;
                 TextBox targetBox = FindChild(nextItem) as TextBox;
                 targetBox.IsTabStop = false;
                 nextItem.Focus(FocusState.Programmatic);
                 
             }
             else
             {
                 // focus on next item
                 ListViewItem nextItem = lvList.ContainerFromIndex(index + 1) as ListViewItem;
                 TextBox targetBox = FindChild(nextItem) as TextBox;
                 targetBox.IsTabStop = false;
                 nextItem.Focus(FocusState.Programmatic);
             }
    
         }
     }
    
    
     public static DependencyObject FindChild(DependencyObject parant)
     {
         int count = VisualTreeHelper.GetChildrenCount(parant);
    
         for (int i = 0; i < count; i++)
         {
             var MyChild = VisualTreeHelper.GetChild(parant, i);
             if (MyChild is FrameworkElement && (FrameworkElement)MyChild is TextBox)
                 return MyChild;
    
             var FindResult = FindChild(MyChild);
             if (FindResult != null)
                 return FindResult;
         }
    
         return null;
     }
    

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.