c# - 如何禁用 FlipView 键盘按键而不在子控件上禁用它

标签 c# wpf xaml mahapps.metro

故事,我在窗口中使用 MahApps.Metro FlipView,FlipView 内部包含一个 GridView,这工作得很好,但我有一个问题,我无法使用键盘箭头在 GridView 单元格中导航,UpDown 箭头有效,但 LeftRight 箭头无效,当我按下它时,翻转 View 会更改页面.

我尝试像这样处理 OnPreviewKeyPress,

private void FlipView_PreviewKeyDown(object sender, KeyEventArgs e)
{
    e.Handled = true;
}

但是 GridView 也没有收到按键。

最佳答案

您在尝试处理 PreviewKeyDown 时走在了正确的轨道上。诀窍是,您需要手动触发 DataGridKeyDown 事件。

这是适用于我的测试用例的实现:

private void UIElement_PreviewKeyDown(object sender, KeyEventArgs e)
{
    var dataGrid = FlipView.SelectedItem as DataGrid;
    if (dataGrid == null) return; // the selected item is not a DataGrid
    if (!dataGrid.SelectedCells.Any()) return; // no selected cells to move between
    // create a new event args to send to the DataGrid
    var args = new KeyEventArgs(
        Keyboard.PrimaryDevice,
        Keyboard.PrimaryDevice.ActiveSource,
        0,
        e.Key);
    args.RoutedEvent = Keyboard.KeyDownEvent; // get the event
    dataGrid.RaiseEvent(args); // raise the event
    e.Handled = true; // prevent the FlipView from going forward/backward
}

假设当 (1) 所选项目是 DataGrid 时,您只想抑制向前/向后移动 FlipView 的能力(2) DataGrid 有一个或多个选定的单元格。 (否则,您希望箭头键像往常一样工作。)


这是我的测试用例的完整代码:

主窗口.xaml.cs:

using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Input;

namespace Sandbox
{
    public partial class MainWindow
    {
        public List<Item> Items { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            Items = new List<Item>
            {
                new Item { Id = 1, Name = "First" },
                new Item { Id = 2, Name = "Second" },
                new Item { Id = 3, Name = "Third" },
                new Item { Id = 4, Name = "Fourth" },
            };
        }

        private void UIElement_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            var dataGrid = FlipView.SelectedItem as DataGrid;
            if (dataGrid == null) return;
            if (!dataGrid.SelectedCells.Any()) return;
            var args = new KeyEventArgs(
                Keyboard.PrimaryDevice,
                Keyboard.PrimaryDevice.ActiveSource,
                0,
                e.Key);
            args.RoutedEvent = Keyboard.KeyDownEvent;
            dataGrid.RaiseEvent(args);
            e.Handled = true;
        }

        public class Item
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    }
}

主窗口.xaml:

<Window x:Class="Sandbox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Sandbox"
        xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
        mc:Ignorable="d"
        Title="MainWindow"
        Width="525"
        Height="350">
    <controls:FlipView x:Name="FlipView"
                       Margin="0, 0, 10, 0"
                       Height="200"
                       IsBannerEnabled="True"
                       PreviewKeyDown="UIElement_PreviewKeyDown">
        <controls:FlipView.Items>
            <DataGrid ItemsSource="{Binding Items}"
                      AutoGenerateColumns="True" />
            <Rectangle Margin="0, 0, 10, 0"
                       Width="50"
                       Height="50"
                       Fill="Red" />
            <Rectangle Margin="0, 0, 10, 0"
                       Width="50"
                       Height="50"
                       Fill="Blue" />
        </controls:FlipView.Items>
    </controls:FlipView>
</Window>

如果您希望箭头在最左边或最右边的单元格被选中时起作用,请将 PreviewKeyDown 事件处理程序替换为:

private void UIElement_PreviewKeyDown(object sender, KeyEventArgs e)
{
    var dataGrid = FlipView.SelectedItem as DataGrid;
    if (dataGrid == null) return;
    if (!dataGrid.SelectedCells.Any()) return;

    // get the column index of the selected cell
    var columnIndex = dataGrid.SelectedCells.First().Column.DisplayIndex;

    // exit if the selected cell is left/right and the arrow is left/right
    if (columnIndex == 0 && e.Key == Key.Left ||
        columnIndex == dataGrid.Columns.Count - 1 && e.Key == Key.Right) return;

    var args = new KeyEventArgs(
        Keyboard.PrimaryDevice,
        Keyboard.PrimaryDevice.ActiveSource,
        0,
        e.Key);
    args.RoutedEvent = Keyboard.KeyDownEvent;
    dataGrid.RaiseEvent(args);
    e.Handled = true;
}

此外,DataGrid 的 XAML 应设置以下属性以确保一次只能选择一个单元格:

<DataGrid ItemsSource="{Binding Items}"
          AutoGenerateColumns="True"
          SelectionMode="Single"
          SelectionUnit="Cell"
          IsReadOnly="True" />

关于c# - 如何禁用 FlipView 键盘按键而不在子控件上禁用它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34865874/

相关文章:

c# - 数据上下文 Windows 8 应用程序

c# - 从 WPF 引用 .NET Core 1.0 库

c# - 访问控件 - 缺少 using 指令或程序集引用

c# - Windows Phone 7 文本框中的输入验证

c# - 在图书馆项目中获取 Razor 智能感知?

c# - 这个算法的空间复杂度是多少O(1)

wpf - 当 TextBox 位于非事件选项卡中时,TextBox.ScrollToEnd 不起作用

asp.net - 将 WPF 转换为 Web

wpf - DatePicker子类找不到模板

c# - 是否可以调用特定的 msconfig 选项卡?