How to support Enter key to move focus in text list column

I created the following view

        <ListView.View>
            <GridView>
                <GridViewColumn Header="Tester"
                                DisplayMemberBinding="{Binding User}" />
                <GridViewColumn Header="Executed On" 
                                DisplayMemberBinding="{Binding ExecutionDate}" />
                <GridViewColumn Header="Comment">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <DockPanel>
                                <TextBox Text="{Binding Comment}" Name="TxtComment"
                                         MinWidth="100" VerticalContentAlignment="Top"
                                         BorderThickness="0" PreviewKeyDown="TxtComment_PreviewKeyDown"/>
                            </DockPanel>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>

Now I believe that after I type something in the Comment field and press the Enter key, the next line of the Comment field will get focus.

I added the following code for the "PreviewKeyDown" event, but it seems that the next whole line will focus not only on the "Comment" field ...

    Private Sub TxtComment_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Input.KeyEventArgs)
    Dim focusRequest As TraversalRequest
    Dim focusedElement As Object = sender

    Select Case e.Key
        Case Key.Enter
            focusRequest = New TraversalRequest(FocusNavigationDirection.Down)
        Case Else
            ' Do nothing
            Return
    End Select
    '  Do not further propagate event
    e.Handled = True
    'Move focus
    DirectCast(focusedElement, UIElement).MoveFocus(focusRequest)
End Sub

Hope someone tells me how to solve this problem, ^ 0 ^

+3
source share
3 answers

SelectionChanged ListView, Enter Enter VisualTreeHelper .

ListView XAML; , , , ObservableCollection ListView ( ), SelectionChanged:

<ListView x:Name="myView" ItemsSource="{Binding Path=MyData}"  
          SelectionChanged="myView_SelectionChanged">
  <ListView.View>
    <GridView>
      <GridViewColumn Header="Tester" 
                      DisplayMemberBinding="{Binding User}" />
      <GridViewColumn Header="Executed On"  
                      DisplayMemberBinding="{Binding ExecutionDate}" />
      <GridViewColumn Header="Comment">
        <GridViewColumn.CellTemplate>
          <DataTemplate>
            <DockPanel>
              <TextBox Text="{Binding Comment}" Name="TxtComment" 
                        MinWidth="100" VerticalContentAlignment="Top" 
                        BorderThickness="0" 
                        PreviewKeyDown="TxtComment_PreviewKeyDown"/>
             </DockPanel>
          </DataTemplate>
        </GridViewColumn.CellTemplate>
      </GridViewColumn>
    </GridView>
  </ListView.View>
</ListView>

, visualtreeHelper :

private void TxtComment_PreviewKeyDown(object sender, KeyEventArgs e)
{
   TraversalRequest focusRequest = null;
   TextBox focusedElement = sender as TextBox;

   switch (e.Key)
   {
      case Key.Enter:
         focusRequest = new TraversalRequest(FocusNavigationDirection.Down);
         if ( focusedElement != null )
         {
            //Move focus 
            bool moved = focusedElement.MoveFocus(focusRequest);
            if (moved)
            {
               e.Handled = true;
            }
         }
         break;
      default:
         break;
   }
}

// find the TextBox here
private void myView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
   ListView lv = sender as ListView;
   if ( lv != null)
   {
      ItemContainerGenerator generator = lv.ItemContainerGenerator;
      ListViewItem selectedItem = (ListViewItem) generator.ContainerFromIndex(lv.SelectedIndex);
      TextBox tbFind = GetDescendantByType(selectedItem, typeof (TextBox), "TxtComment") as TextBox;
      if (tbFind != null)
      {
         FocusHelper.Focus(tbFind);
      }
   }
}

public static Visual GetDescendantByType(Visual element, Type type, string name)
{
   if (element == null) return null;
   if (element.GetType() == type)
   {
      FrameworkElement fe = element as FrameworkElement;
      if (fe != null)
      {
         if (fe.Name == name)
         {
            return fe;
         }
      }
   }
   Visual foundElement = null;
   if (element is FrameworkElement)
      (element as FrameworkElement).ApplyTemplate();
   for (int i = 0;
        i < VisualTreeHelper.GetChildrenCount(element);
        i++)
   {
      Visual visual = VisualTreeHelper.GetChild(element, i) as Visual;
      foundElement = GetDescendantByType(visual, type, name);
      if (foundElement != null)
         break;
   }
   return foundElement;
}

Focus TextBox:

public static class FocusHelper
{
  public static void Focus(UIElement element)
  {
     element.Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(delegate()
     {
        element.Focus();
     }));
  }
}
+1

vb.net.

    Dim focusRequest As TraversalRequest = Nothing
    Dim focusedElement As TextBox = TryCast(sender, TextBox)
0

Had a similar problem (I need my GridView to behave like a DataGrid for my user convenience). This is similar to another solution posted here (I reused some of these helper functions). Just name the input elements and attach an event handler. The code below works with Framework 4.5. If you are working with Framework 4, just change the "listView.ItemContainerGenerator.Items" links to "listView.Items".

    private void FrameworkElement_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key != Key.Enter)
            return;

        var element = sender as FrameworkElement;
        if (element == null)
            return;

        var container = (ListViewItem)GetAnscestorByType<ListViewItem>(element);
        if (container == null)
            return;

        var listView = (ListView)GetAnscestorByType<ListView>(container);
        if (listView == null)
            return;

        var index = listView.ItemContainerGenerator.IndexFromContainer(container);
        if (index < 0 || index >= listView.ItemContainerGenerator.Items.Count - 1)
            return;

        var nextItem = listView.ItemContainerGenerator.Items[index + 1];
        if (nextItem == null)
            return;

        var nextContainer = listView.ItemContainerGenerator.ContainerFromItem(nextItem) as Visual;
        if (nextContainer == null)
            return;

        listView.ScrollIntoView(nextItem);

        var hit = GetDescendantByType(nextContainer, element.GetType(), element.Name) as FrameworkElement;
        if (hit == null)
            return;

        Focus(hit);
    }

    public static void Focus(FrameworkElement element)
    {
        element.Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(() => element.Focus()));
    }

    public static Visual GetAnscestorByType<T>(Visual element)
        where T : FrameworkElement
    {
        if (element == null)
            return null;

        var parent = VisualTreeHelper.GetParent(element) as Visual;
        while (parent != null)
        {
            if (parent is T)
                return parent;

            parent = VisualTreeHelper.GetParent(parent) as Visual;
        }
        return null;
    }

    public static Visual GetDescendantByType(Visual element, Type type, string name)
    {
        if (element == null) 
            return null;

        if (element.GetType() == type && ((FrameworkElement)element).Name == name)
            return element;

        Visual foundElement = null;
        if (element is FrameworkElement)
            (element as FrameworkElement).ApplyTemplate();
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
        {
            Visual visual = VisualTreeHelper.GetChild(element, i) as Visual;
            foundElement = GetDescendantByType(visual, type, name);
            if (foundElement != null)
                break;
        }
        return foundElement;
    }
0
source

Source: https://habr.com/ru/post/1765464/


All Articles