如何禁用 FlipView 键盘按键而不在子控件上禁用它
How to disable FlipView keyboard keypress without disabling it on child control
故事,我在我的 window 中使用 MahApps.Metro FlipView,FlipView 包含一个 GridView,这工作得很好,但我有一个问题,我不能使用键盘箭头来在 GridView 单元格中导航,Up
和 Down
箭头有效,但 Left
和 Right
箭头无效,当我按下它时,翻转视图会更改页面。
我尝试这样处理 OnPreviewKeyPress,
private void FlipView_PreviewKeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
}
但是 GridView 也没有收到按键。
您尝试处理 PreviewKeyDown
的方向是正确的。诀窍是,您需要手动触发 DataGrid
.
的 KeyDown
事件
这是适用于我的测试用例的实现:
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
}
假设: 您只想抑制移动 FlipView
forward/backward 的能力,当 (1) 所选项目是 DataGrid
和 (2) DataGrid
有一个或多个选定的单元格。 (否则,您希望箭头键像往常一样工作。)
这是我的测试用例的完整代码:
MainWindow.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; }
}
}
}
MainWindow.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" />
故事,我在我的 window 中使用 MahApps.Metro FlipView,FlipView 包含一个 GridView,这工作得很好,但我有一个问题,我不能使用键盘箭头来在 GridView 单元格中导航,Up
和 Down
箭头有效,但 Left
和 Right
箭头无效,当我按下它时,翻转视图会更改页面。
我尝试这样处理 OnPreviewKeyPress,
private void FlipView_PreviewKeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
}
但是 GridView 也没有收到按键。
您尝试处理 PreviewKeyDown
的方向是正确的。诀窍是,您需要手动触发 DataGrid
.
KeyDown
事件
这是适用于我的测试用例的实现:
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
}
假设: 您只想抑制移动 FlipView
forward/backward 的能力,当 (1) 所选项目是 DataGrid
和 (2) DataGrid
有一个或多个选定的单元格。 (否则,您希望箭头键像往常一样工作。)
这是我的测试用例的完整代码:
MainWindow.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; }
}
}
}
MainWindow.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" />