8

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.

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:

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.

Any ideas?

Anders
  • 1,401
  • 3
  • 16
  • 20
  • just store the selected row's index ,set selectedIndex after refresh – Hukam Mar 26 '11 at 14:16
  • Why not just invoke PropertyChanged asynchronously in the bound entity's definition and have the timer (or some logic in the partial entity class) invoke property changed. Then you can just use UpdateSource.OnPropertyChanged for your DataGridColumn binding, which should (in theory) prevent the whole DG from refreshing and only refresh changed entities (and thus solve your focus issue AND lead to, in thoery, better performance). Am I missing something? – William Dec 14 '12 at 01:25

3 Answers3

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:

<DataGridTextColumn Binding="{Binding xyz, Mode=TwoWay}"/>
Alex Maker
  • 1,529
  • 2
  • 19
  • 27
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 :

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:

  • 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
  • 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.

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.

Community
  • 1
  • 1
Sebastian Edelmeier
  • 4,095
  • 3
  • 39
  • 60
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

Afnan Bashir
  • 7,319
  • 20
  • 76
  • 138
  • 1
    How do you get the index initially? – Anders Mar 26 '11 at 15:14
  • if i am correct you are asking for getting index before refresh,If that is the case then what i do is i declare a variable and maintain it in leftmousedown or up event handler and check that if `datagrid.SelectedIndex >=0` then update the variable in this way i would have updated index – Afnan Bashir Mar 26 '11 at 17:21