WPF 数据网格和 Tab 键
另一个数据网格键绑定问题
我有一个数据网格。它的选择模式设置为 FullRow 和 KeyboardNavigation.TabNavigation="Once" 我希望能得到我想要的结果,但事实并非如此。
当数据网格获得焦点时按下 Tab 键,它将一一地遍历网格中的每一列。因此,如果我按 Tab 键进入有 4 列的网格,我将必须按 Tab 键 4 次才能转到下一个 tabindex。
我想要的是让 tab 键在第一次按下时直接从数据网格中跳出,并将焦点集中到下一个 tabindex...如果这有意义的话。
我尝试像这样覆盖 keydown 事件处理程序中的 tab 键。
class BetterDataGrid : DataGrid
{
..............
protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
{
..............
if (e.Key == Key.Tab)
{
Console.WriteLine("TAB");
MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
.........
}
它确实将“TAB”写入控制台,但该选项卡仍然保留其默认行为。不确定这是否是进入下一个 tabindex 的正确方法,但这应该使 tab 键除了写入控制台或引发异常之外什么也不做。
让我觉得不可能覆盖 Tab 键的行为。
希望得到一些有用的意见。
一如既往,提前致谢。
Another datagrid keybindings question
I have a datagrid. It has selection mode set to FullRow and KeyboardNavigation.TabNavigation="Once" which I was hoping would get my desired result but it doesn't.
When the tab key is pressed when the datagrid has focus it will tab over each column in the grid one by one. So if I tab into the grid which has 4 columns, I will have to press tab 4 times to go to the next tabindex.
What I want is for the tab key to tab right out of the datagrid on first press and give focus to the next tabindex... if that makes sense.
I have tried overriding the tab key in the keydown event handler like so.
class BetterDataGrid : DataGrid
{
..............
protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
{
..............
if (e.Key == Key.Tab)
{
Console.WriteLine("TAB");
MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
}
.........
}
It does write "TAB" to the console but the tab still keeps it's default behavior. Not sure if this is the right way to go the next tabindex, but then this should make the tab key do nothing but write to the console or cause an exception.
Makes me think it's impossible to override the tab key behavior.
Hoping for some helpful input.
As always, thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我希望我的业务线软件能够做到这一点,而我发现解决这个问题的唯一方法是通过代码隐藏,使用数据网格的 PreviewKeyDown、GotKeyboardFocus 和 LostKeyboardFocus 事件。我已将这些事件处理程序放入 WPF 装饰器中,以避免对每个 DataGrid 重复它。可能可以对 DataGrid 进行子类化,但我还没有尝试过。
处理程序的代码如下(对于此示例代码,DataGrid 为 x:Name="grid"):
使用此代码,您可以使用光标键在网格内导航,然后使用 Tab 键和 Shift-Tab 键即可退出数据网格的。如果您按 Tab 键退出网格并返回到网格,您也会到达您离开的同一单元格。这就是我和我的用户想要的,恕我直言,这就是 DataGrid 控件应该提供的默认行为。
I wanted this for my line-of-business software, and the only way I have found to solve it is by codebehind, using the PreviewKeyDown, GotKeyboardFocus and LostKeyboardFocus events of the datagrid. I have put these eventhandlers in a WPF decorator, to avoid repeating it for every single DataGrid. It would probably be possible to subclass the DataGrid, but I haven't tried that.
The code for the handlers are as follows (DataGrid is x:Name="grid" for this sample code):
With this code you can navigate inside the grid using the cursor keys, and the tab key and shift-tab key gets you out of the datagrid. If you tab out of the grid and come back to the grid, you also get to the same cell that you left. This is what my users and I want, and this is IMHO what the DataGrid control should provide as default behaviour.
我也在寻找这种行为。虽然 Guge 提出的解决方案是一个好的开始,但我不喜欢它如何保存以前存储的元素,也不喜欢它的整体复杂性。最糟糕的是,无论我如何调整它,我都无法让它按照预期持续工作。最终,我决定从头开始编写自己的解决方案。通过跳出框框(字面意思)思考,我想出了一个不同的、更简单的解决方案。
在 XAML 文件中,在 DataGrid 之前和之后创建一个空控件,如下所示:
然后在代码隐藏中,为 DataGrid 的 PreviewKeyDown 事件添加一个函数,如下所示:
第一个 if 和 else-if 通过从 Tab 键切换来覆盖默认选项卡行为空控件而不是来自数据网格。下一个 else-if 语句在使用箭头键移动之前更新当前单元格。有时,当焦点移入和移出网格时,当前单元格会与所选单元格不同步。这是之前提出的解决方案以及这个解决方案的一个问题,我还没有找到解决它的方法,但是通过这样做,我可以确保在使用箭头键导航时,它相对于所选单元格进行导航,而不是当前单元格。
此方法的一些注意事项:
I was also looking for this behaviour. While the solution proposed by Guge was a good start, I did not like how it saves the previously stored element nor it's overall complexity. Worst of all, I simply couldn't get it to consistently work as expected no matter how much I tweaked it. Eventually, I decided to write my own solution from scratch. By thinking outside the box (literally) I've come up with a different, simpler solution.
In the XAML file, create an empty control before and after your DataGrid like so:
Then in the code-behind, add a function for the DataGrid's PreviewKeyDown event like so:
The first if and else-if override the default tab behavior by tabbing from the empty controls instead of from the datagrid. The next else-if statement updates the current cell before moving with the arrow keys. Sometimes the current cell becomes out of sync with the selected cell when switching focus in and out of the grid. This is an issue with the previously proposed solution as well as this one and I have not found a way to fix it, but by doing this, I can make sure that when navigating using the arrow keys, it navigates relative to the selected cell, rather than the current cell.
Some caveats to this approach:
这可能会对某人有所帮助...我想使用 Tab 键移动到下一行,但也选择或传递包含两个按钮的自定义单元格。解决方案是扩展
DataGrid
列CellStyle
并将每个列/单元格的Focusable
设置为False
。这是我的代码:This might help someone... I wanted to move to the next row using the Tab key, but also select or pass through my custom cell which contains two buttons. The solution was to extend the
DataGrid
columnCellStyle
and setFocusable
toFalse
for each column/cell. Here is my code:这个困扰我很久的问题终于得到了最好的答案。
在某些时候,我确认在 DataGrid 中按 Ctrl+Tab 会产生所需的行为。
由此,我认为我可以交换 DataGrid 中 KeyboardNavigation.TabNavigation 附加属性和 KeyboardNavigation.ControlTabNavigation 附加属性的值。
然而,这并没有奏效。
在使用 ReferenceSource 检查 DataGrid 子元素的代码后,我进一步认为应该交换 DataGridCellsPanel 中 KeyboardNavigation.TabNavigation 附加属性和 KeyboardNavigation.ControlTabNavigation 附加属性的值。
我运行它并得到了理想的行为。
更重要的是,这很棒,重新进入焦点后的当前单元格就是失去焦点时的当前单元格。
也可以通过以下附加属性来实现,参考WinForms中DataGridView的StandardTab属性。
对于 VB.net
对于 C#(未测试)
I finally got the best answer to this problem that I have been struggling with for a long time.
At some point, I confirmed that pressing Ctrl+Tab in the DataGrid would result in the desired behavior.
From this, I thought I could just swap the values of KeyboardNavigation.TabNavigation attached property and KeyboardNavigation.ControlTabNavigation attached property in the DataGrid.
However, it did not work.
After checking the code of the DataGrid's child elements with ReferenceSource, further, I thought that I should swap the values of KeyboardNavigation.TabNavigation attached property and KeyboardNavigation.ControlTabNavigation attached property in DataGridCellsPanel.
I ran it and got the ideal behavior.
What's more, and this is great, the current cell after focus is reentered is the current cell when the focus is lost.
It can also be realized with the following attached properties, referring to the StandardTab property of DataGridView in WinForms.
For VB.net
For C# (not tested)
您想要实现的不是正确的行为,每个人都期望在 DataGrid 聚焦时按 Tab 键时像 Excel 一样导航。如果您不希望用户在 DataGrid 中导航,最好通过在 DataGrid 上设置
IsTabStop="False"
来防止 DataGrid 上出现制表位。What you are trying to achive is not the right behavior, everyone expect Excel like navigation when pressing the Tab-Key while the DataGrid is focused. It's better to prevent tab stops on the DataGrid by setting
IsTabStop="False"
on the DataGrid if you don't want the user to navigate through the DataGrid.