WPF DataGrid在ItemsSource更新后如何聚焦选中的DataGridRow?
问题根因
ViewModel_ItemsSourceChanged事件触发时,ItemsSource更新触发的DataGrid行容器生成、布局重绘流程还未完成,此时设置的焦点会被后续的UI渲染逻辑覆盖- 若DataGrid开启了UI虚拟化,不在可视区域的行通过
ContainerFromItem会返回null,无法完成后续焦点操作
可行解决方案
把焦点逻辑通过Dispatcher排队到UI渲染完成后执行,同时先把选中行滚动到可视区域,修改后的代码如下:
private void ViewModel_ItemsSourceChanged(object sender, ItemsSourceChangedEventArgs e) { if (e.Index > 0) { MainDataGrid.SelectedIndex = e.Index; MainDataGrid.SelectedItem = MainDataGrid.Items[e.Index]; // 先将选中行滚动到可视区域,解决虚拟化场景下拿不到行容器的问题 MainDataGrid.ScrollIntoView(MainDataGrid.SelectedItem); } // 把焦点操作排队到UI布局、渲染完成后执行 Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => { var dataGridRow = (DataGridRow)MainDataGrid.ItemContainerGenerator.ContainerFromItem(MainDataGrid.SelectedItem); if (dataGridRow != null) { MainDataGrid.Focus(); dataGridRow.Focus(); // 若需要聚焦到行的第一个单元格可保留此行,仅需要聚焦到行则可以删除 dataGridRow.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); } })); }
额外验证点
- 确认
MainDataGrid的Focusable属性为true,父容器没有强制拦截焦点 - 如果上述代码仍不生效,可以把
DispatcherPriority调整为DispatcherPriority.Background,确保所有UI渲染逻辑执行完成后再操作焦点
内容的提问来源于stack exchange,提问作者Tzwenni
相关产品推荐
相关产品推荐

