刷新 WPF DataGrid 时不丢失单元格焦点

8
我有一个WPF DataGrid,其中绑定了一些数据到LINQ to SQL实体类。其中一列是一个时钟,显示给定航班的空中时间,这是使用Flight的partial class中的逻辑计算出来的。我设置了一个定时器,每2秒钟调用datagrid.Items.Refresh来更新时钟。
刷新正常工作,但现在我要添加键盘快捷方式。使用键盘箭头浏览单元格在关闭定时器的情况下可以正常工作,但启用刷新定时器后,焦点单元格(实际上是整个数据网格)会失去焦点。
我需要保持焦点(首选)或在DataGrid获得焦点时禁用定时器。我甚至无法似乎使后者工作。我尝试过:
if (!dataGrid.IsFocused)
    dataGrid.Items.Refresh();

并且

if (!dataGrid.IsKeyboardFocused)
        dataGrid.Items.Refresh();

对于计时器,但是即使数据网格获得焦点,这些属性也会返回false。
有什么想法吗?

只需存储所选行的索引,在刷新后设置selectedIndex即可。 - Hukam
为什么不在绑定实体的定义中异步调用PropertyChanged,并让计时器(或部分实体类中的某些逻辑)调用属性更改。然后,您可以只使用UpdateSource.OnPropertyChanged来绑定DataGridColumn,这应该(理论上)防止整个DG刷新并仅刷新更改的实体(从而解决焦点问题并在理论上导致更好的性能)。我有什么遗漏吗? - William
3个回答

2

最好的方法不是使用dataGrid.Items.Refresh()作为更新机制。这听起来像底层对象已经单独更新了。如果它们实现了INotifyPropertyChanged,您应该尝试将列的绑定模式设置为TwoWay Binding:

<DataGridTextColumn Binding="{Binding xyz, Mode=TwoWay}"/>

0

我认为你可以获取当前焦点,然后在刷新网格后将选定的单元格重新聚焦,类似于以下操作:

int index = 11;
myDataGrid.SelectedItem = myDataGrid.Items[index];
myDataGrid.ScrollIntoView(myDataGrid.Items[index]);
DataGridRow dgrow = (DataGridRow)myDataGrid.ItemContainerGenerator.ContainerFromItem(myDataGrid.Items[index]);
dgrow.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));

同时也可以查看this,它可能会对你有所帮助。


1
你最初如何获取索引? - Anders
如果我理解正确的话,您想在刷新前获取索引。 如果是这种情况,那么我的做法是声明一个变量并在“leftmousedown”或“up”事件处理程序中维护它,并检查是否 datagrid.SelectedIndex >=0 ,然后以这种方式更新变量,从而更新索引。 - Afnan Bashir

0

你的单元格失去焦点是因为你改变了底层集合(ItemsSource)。据我所知,没有什么好的方法可以获取单元格。对于行:

如果你使用MVVM,你可以记住你的SelectedItemSelectedIndex,并在绑定完成后恢复它。这将让你进入正确的行。两者都有不同的缺点:

  • SelectedItem需要更多的工作。如果你使用它,请确保在底层对象中重写EqualsGetHashCode。如果你的项目在集合中是第5个,在重新加载期间出现了另一行,你仍然会进入正确的行。
  • SelectedIndex是最快的解决方案,但只是一个数字位置。如果你选择了第5个条目,并且重新加载合并了它之前的行,你将得到错误的选定行。

正如我所说,我没有尝试过单元格,但你可以阅读this以开始解决你的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接