MaterialDesignInXamlToolkit
MaterialDesignInXamlToolkit copied to clipboard
Refocus after Dialog close triggers Tab change
The DialogHost tries to "re-focus" the item previously selected. This is the code for it: https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/blob/5533b50a6cff78cb75fbb52e16f7c9e06c62446c/MaterialDesignThemes.Wpf/DialogHost.cs#L268
This is very problematic, when the previous control was a TabItem, because Focus()ing a TabItem actually activates the respective tab.
Here is a very simple reproduction:
- Have a TabControl within a DialogHost
- Focus a given TabItem (i.e. by clicking on an already active Tab)
- In the SelectionChanging Event of the TabControl Show the Dialog (i.e. "Loading data ...")
- Click another Tab
The following happens:
- DialogHost remembers, that the first tab is currently focused
- The click on the second Tab activates this Tab
- Dialog is shown and closed again, after data is loaded
- Dialog calls Focus() on first tab => First tab will be selected again
I just created the issue as I'm not sure, what the best solution for this. My current feeling tells me to just check for if(!(dialogHost._restoreFocusDialogClose is TabItem), but there might be other elements, where a re-focus is not desired?
I'd be happy to provide a PR after we agree on a solution.
Also - for now, I'd welcome any idea for a good workaround I could place into the application to make it work for now.
For the workaround, this is btw. what I'm using right now, which seems to do the job reasonably well ...
private void RemoveTabItemFocus()
{
var window = Window.GetWindow(this);
var focusedElement = FocusManager.GetFocusedElement(window);
if (focusedElement is TabItem)
{
FocusManager.SetFocusedElement(window, null);
}
}
And than, just make sure to call this before the Dialog is opened.
I meanwhile ran into multiple other issues connected to the re-focus. Most of them are mostly relevant, when the Dialog is not used with Input elements but used as a kind of Progress Dialog.
An example would be that when Windows are opened, while the Dialog is open, the window is sent into background after Dialog closes, because the MainWindow is focused again.
For now I added this to the DialogOpened event of our progress dialog
sender.GetType().GetField("_restoreFocusDialogClose", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(sender, null);
As you can see, this is something I have to do the bad way, as this property is not available via the public interface of DialogHost.
What I'd actually love to be able to do is to disable the Re-focus functionality via a binding property, i.e. something like
<md:DialogHost RestoreFocus="False" />
Again, I'd happily send the PRs for all of this, but I'd like to have some feedback on it before I do the changes :-)