如何在WPF DataGrid中编程设置当前单元格且不破坏Tab键功能?
我之前做项目时也踩过这个坑!你现在写的代码虽然能把指定单元格设为当前项并进入编辑模式,但大概率是没处理好焦点同步和DataGrid的内部UI逻辑,才导致Tab键的导航功能出问题——要么Tab直接跳出DataGrid,要么在单元格里按Tab没反应,对吧?
先给你拆解下问题根源:直接设置CurrentCell然后调用BeginEdit(),WPF可能还没来得及完成DataGrid的布局更新和焦点状态同步,这时候焦点要么还停留在上面的搜索TextBox,要么只到了DataGrid本身,没真正落到单元格内的编辑控件上,Tab键自然就按原有逻辑走,不跟着你的预期来了。
下面是我实测有效的解决步骤,你可以一步步改:
先把焦点切到DataGrid本身
这步很关键!如果焦点还在搜索TextBox上,后续的单元格操作都会有延迟或状态不同步:MyDataGrid.Focus();确保目标行可见(可选但推荐)
如果目标行不在当前视图范围内,直接设置CurrentCell可能会导致滚动异常,先滚动到该行:MyDataGrid.ScrollIntoView(myViewModel);设置当前单元格(你原来的代码这部分没问题)
MyDataGrid.CurrentCell = new DataGridCellInfo(myViewModel, PunktzahlColumn);异步触发编辑模式并传递焦点到编辑控件
直接同步调用BeginEdit()可能赶不上UI布局更新,用Dispatcher异步调用,同时把焦点落到单元格内的编辑控件(比如TextBox)上,这样Tab键就能正常识别当前编辑状态:Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => { MyDataGrid.BeginEdit(); // 找到当前单元格内的编辑控件并设置焦点 var row = MyDataGrid.ItemContainerGenerator.ContainerFromItem(myViewModel) as DataGridRow; if (row != null) { var cell = row.Cells.FirstOrDefault(c => c.Column == PunktzahlColumn); if (cell != null) { cell.Focus(); var editor = FindVisualChild<TextBox>(cell); if (editor != null) { editor.Focus(); // 可选:把光标定位到文本末尾 editor.CaretIndex = editor.Text.Length; } } } }));辅助方法:查找可视化子元素
上面用到的FindVisualChild是用来定位单元格内的编辑控件的,需要在你的窗口/用户控件里加这个私有方法:private T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { var child = VisualTreeHelper.GetChild(parent, i); if (child is T typedChild) return typedChild; var nestedChild = FindVisualChild<T>(child); if (nestedChild != null) return nestedChild; } return null; }
这样处理后,焦点会完整地从搜索TextBox转移到DataGrid的目标编辑单元格,Tab键也会遵循DataGrid的内部导航逻辑——按Tab时会跳到下一个可编辑单元格,而不是直接跳出DataGrid或者失效。
内容来源于stack exchange

