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

时间:2022-03-22 22:17:19

I have a WPF DataGrid with some data bound to LINQ to SQL entity classes. One column is a clock showing a given flight's airborn time, which is calculated using logic in Flight's partial class. I have a timer calling datagrid.Items.Refresh every 2 seconds to update the clock.

我有一个WPF DataGrid,其中一些数据绑定到LINQ to SQL实体类。一列是显示给定航班的空中时间的时钟,它是使用Flight的部分类中的逻辑计算的。我有一个定时器,每隔2秒调用datagrid.Items.Refresh来更新时钟。

The refresh works fine, but now I'm adding keyboard shortcuts. Navigating through cells with the keyboard arrows works fine with the timer off, but with the Refresh timer enabled, the focused cell (actually the entire datagrid) loses focus.

刷新工作正常,但现在我正在添加键盘快捷键。使用键盘箭头在单元格中导航可以正常关闭计时器,但启用刷新计时器后,聚焦单元格(实际上是整个数据网格)将失去焦点。

I need to either somehow maintain focus (preferred) or disable the timer whenever the DataGrid is focused. I can't even seem to get the latter to work. I've tried:

我需要以某种方式保持焦点(首选)或在DataGrid聚焦时禁用计时器。我甚至无法让后者工作。我试过了:

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

and

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

for the timer, but these properties return false even when the datagrid is focused.

对于计时器,但即使数据网格被聚焦,这些属性也会返回false。

Any ideas?

有任何想法吗?

3 个解决方案

#1


2  

The best way is not to use dataGrid.Items.Refresh() as update mechanism. It sounds like the underlying objects are already updated separately. If they implement INotifyPropertyChanged, you should try to set the binding mode for the colum as TwoWay Binding:

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

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

#2


0  

i think you may get the present focus and after grid is refreshed give the selected cell back its focus something like

我认为你可能会得到目前的焦点,并且在网格刷新后,让选定的单元格重新回到它的焦点

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));

also check this out it may help you

也检查一下这可能会对你有所帮助

#3


0  

Your cells lose focus because you change the underlying collection (ItemsSource). There is no beautiful way, as far as I recall, to get the cell. For the row :

您的单元格失去焦点,因为您更改了基础集合(ItemsSource)。据我所知,没有美丽的方式来获得牢房。对于行:

If you work with MVVM, you can memorize your SelectedItem or SelectedIndex and restore it after the reload is done by binding. That will get you in the right row, for a start. Both have different drawbacks:

如果使用MVVM,则可以记住SelectedItem或SelectedIndex,并在通过绑定完成重新加载后恢复它。这将使你在正确的行,一开始。两者都有不同的缺点:

  • SelectedItem requires a bit more work. Make sure you override Equals and GetHashCode in the underlying objects if you use it. If your item was number 5 in the collection and during the reload another row appears before it, you will still end up in the right line
  • SelectedItem需要更多的工作。如果使用它,请确保在基础对象中重写Equals和GetHashCode。如果您的项目在集合中为5,并且在重新加载期间会出现另一行,您仍然会在最右边的行中结束
  • SelectedIndex is the quickest solution, but is only a numeric position. If you select entry number 5 and the reload merges in rows before it, you will end up with the wrong selected row.
  • SelectedIndex是最快的解决方案,但只是一个数字位置。如果选择条目号5并且重新加载在它之前的行中合并,则最终会得到错误的选定行。

As I said, I haven't tried with the cells, but you can read this for a start. Maybe you can apply it to your issue.

正如我所说,我没有尝试过细胞,但是你可以开始阅读这个细胞。也许你可以将它应用到你的问题中。

#1


2  

The best way is not to use dataGrid.Items.Refresh() as update mechanism. It sounds like the underlying objects are already updated separately. If they implement INotifyPropertyChanged, you should try to set the binding mode for the colum as TwoWay Binding:

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

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

#2


0  

i think you may get the present focus and after grid is refreshed give the selected cell back its focus something like

我认为你可能会得到目前的焦点,并且在网格刷新后,让选定的单元格重新回到它的焦点

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));

also check this out it may help you

也检查一下这可能会对你有所帮助

#3


0  

Your cells lose focus because you change the underlying collection (ItemsSource). There is no beautiful way, as far as I recall, to get the cell. For the row :

您的单元格失去焦点,因为您更改了基础集合(ItemsSource)。据我所知,没有美丽的方式来获得牢房。对于行:

If you work with MVVM, you can memorize your SelectedItem or SelectedIndex and restore it after the reload is done by binding. That will get you in the right row, for a start. Both have different drawbacks:

如果使用MVVM,则可以记住SelectedItem或SelectedIndex,并在通过绑定完成重新加载后恢复它。这将使你在正确的行,一开始。两者都有不同的缺点:

  • SelectedItem requires a bit more work. Make sure you override Equals and GetHashCode in the underlying objects if you use it. If your item was number 5 in the collection and during the reload another row appears before it, you will still end up in the right line
  • SelectedItem需要更多的工作。如果使用它,请确保在基础对象中重写Equals和GetHashCode。如果您的项目在集合中为5,并且在重新加载期间会出现另一行,您仍然会在最右边的行中结束
  • SelectedIndex is the quickest solution, but is only a numeric position. If you select entry number 5 and the reload merges in rows before it, you will end up with the wrong selected row.
  • SelectedIndex是最快的解决方案,但只是一个数字位置。如果选择条目号5并且重新加载在它之前的行中合并,则最终会得到错误的选定行。

As I said, I haven't tried with the cells, but you can read this for a start. Maybe you can apply it to your issue.

正如我所说,我没有尝试过细胞,但是你可以开始阅读这个细胞。也许你可以将它应用到你的问题中。