I have an XamDataGrid with the ActiveDataItem two-way bound to a view model. When I change the ActiveDataItem in the view model, it changes in the view just find.
If I manually select a row, the application looses focus, the ActiveDataItem is updated in the view model, the row selects just fine and I can see the newly highlighted row. However, when I return focus back to the application the ActiveDataItem switches back to the previous DataItem (without me actually clicking that row).
How do I prevent this behavoir?
Hello Ben,
I am just checking the progress of this issue and was wondering if you managed to achieve your goal or if you need any further assistance on the matter.
This is really just built-in behavior/functionality of the WPF framework. When a WPF window loses keyboard focus the internal HwndKeyboardInputProvider stores a reference to the element that had the keyboard focus. Then when the associated window gets focus (e.g. when you activate the window) it automatically focuses that element. That is what is happening here. When you clicked on the record presenter at the top you gave that keyboard focus. When you clicked on another app you took keyboard focus away from the WPF window and so it stored a reference to that RecordPresenter. When you clicked on the window to activate it it focused that cached element - the rp on top. This isn't something that the DataPresenter has any knowledge about or control over so its not something we could change within the control; it is just how the WPF framework is implemented.
In terms of working around this I suppose you could either try to use reflection to manipulate the HwndKeyboardInputProvider or you could try to intercept when WPF is trying to refocus that element. You'll have to verify this in your app and possibly have to make adjustments based on what you find but something like the following might get you started:
static MainWindow(){ EventManager.RegisterClassHandler(typeof(RecordPresenter), Keyboard.PreviewGotKeyboardFocusEvent, new KeyboardFocusChangedEventHandler((o, e) => { // assuming keyboard focus wasn't in the wpf window (note this could mean it was within an hwndhost, etc.) if (e.OldFocus == null) { var newFocus = e.NewFocus as DependencyObject; var focusScope = FocusManager.GetFocusScope(newFocus); var focusedElement = FocusManager.GetFocusedElement(focusScope) as DependencyObject; // if the element being focused isn't the currently logically focused element of the focus scope and its // not a descendant then we could cancel the focus change if (focusedElement != newFocus && !Infragistics.Windows.Utilities.IsDescendantOf(newFocus, focusedElement)) { e.Handled = true; } } }));}
I am afraid this does not work. Still suffers from the same problem.
I modified the sample you have sent me, so now it works as you want. Basically I handled the Window’s Activating and XamDataGrid RecordDeactivating events in order to be able to cancel the activation of the wrong Record in the scenario you described. Please let me know if this helps you or you need further assistance on this matter.
Looking forward for your reply.
Apologies, I thought I had already uploaded a reproduction. See attached.
Instructions:
1. There is a timer that automatically adds items to the grid. Wait for a few items to be added. You'll notice it selects the latest added item.
2. After a few items are added. Quickly after a further item has been added, select the top item and move your focus out of the application window (by clicking your desktop etc...). Make sure you can still see the window!
You will notice that the top item is selected and active (as it should be) until the next item automatically comes in, which gets selected and made the active record automatically.
3. Move your focus back to the window (without selecting a record). You will now notice that the selection/active record will switch back to the top record you selected.This is undesirable. It should be the last record.
Note that I am using an old version. I am unable to upgrade as its a production system, so I am looking for a work-around/hack.