如何对嵌套在 MenuFlyout 中的 ListView 中的项目使用键盘导航?

问题描述 投票:0回答:1

我有一个按钮,按下时会打开 MenuFlyout。 MenuFlyout 有多个自定义 MenuFlyoutItem:一个具有嵌套的 StackPanel,一个具有绑定的 Command,以及一个可操作项的 ListView(使用 ListView.ItemTemplate 定义)。问题是,当使用键盘导航弹出按钮时,我无法访问/对 ListView 中的项目执行任何操作,焦点只会移动到整个 ListView 周围。

使用箭头键没有成功。我尝试在包装ListView的MenuFlyoutItem上定义TabFocusNavigation =“Cycle”和XYFocusKeyboardNavigation =“Enabled”,在ListView上定义IsItemClickEnabled =“True”,TabFocusNavigation =“Cycle”和XYFocusKeyboardNavigation =“Enabled”,以及每个组合这些。我在这里缺少什么?

xaml uwp uwp-xaml uwp-navigation
1个回答
0
投票

与此线程类似,解决方法是使用 Control.Focus(FocusState) 方法在 MenuFlyoutItem 获得焦点时设置 ListView 的焦点状态。

1.在事件

MenuFlyoutItem_GotFocus
中获取ListView。

2.设置ListView的

SelectedIndex
FocusState
,使ListView获得焦点。

主页.xaml

<Button Content="Button" Margin="397,404,0,0" VerticalAlignment="Top">
    <Button.Flyout>
        <MenuFlyout>
            <MenuFlyoutItem>
                <MenuFlyoutItem.Template>
                    <ControlTemplate>
                        <StackPanel >
                            <TextBlock Text="Test" />
                        </StackPanel>
                    </ControlTemplate>
                </MenuFlyoutItem.Template>
            </MenuFlyoutItem>

            <MenuFlyoutItem  GotFocus="MenuFlyoutItem_GotFocus">
                <MenuFlyoutItem.Template>
                    <ControlTemplate>
                        <ListView Loaded="ListView_Loaded" LostFocus="ListView_LostFocus">
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding}"/>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>
                    </ControlTemplate>
                </MenuFlyoutItem.Template>
            </MenuFlyoutItem>

            <MenuFlyoutItem Text="Test"></MenuFlyoutItem>
            
        </MenuFlyout>
    </Button.Flyout>
</Button>

MainPage.xaml.cs

  public ObservableCollection<string> IconItems { get; set; } = new ObservableCollection<string>();
  private void ListView_Loaded(object sender, RoutedEventArgs e)
  {
      for (int i = 0; i < 10; i++)
      {
          IconItems.Add($"index{i}");
      }
      var listview = sender as ListView;
      listview.ItemsSource = IconItems;
   
  }

    public bool isListViewFocus = false;
    private void MenuFlyoutItem_GotFocus(object sender, RoutedEventArgs e)
    {
        var menuFlyoutItem = sender as MenuFlyoutItem;

        ListView listView = FindChild<ListView>(menuFlyoutItem);

        if (listView != null && isListViewFocus == false) 
        {
            if (listView.SelectedIndex == -1) 
            {
                listView.SelectedIndex = 0;
            }
            else
            {
                listView.SelectedIndex = listView.SelectedIndex;
            }

            listView.Focus(FocusState.Programmatic);
        }

        isListViewFocus = true;
    }

    private void ListView_LostFocus(object sender, RoutedEventArgs e)
    {
        isListViewFocus = false;
    }

    public static T FindChild<T>(DependencyObject parent) where T : DependencyObject
    {
        if (parent == null)
            return null;

        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < childrenCount; i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);
            if (child is T typedChild)
                return typedChild;

            // Recursively search deeper into nested containers
            T result = FindChild<T>(child);
            if (result != null)
                return result;
        }

        return null; // Child not found
    }
© www.soinside.com 2019 - 2024. All rights reserved.