Skip to content

Commit 04ed451

Browse files
committed
dialogs restore focus correctly fixes #232
1 parent d03a85d commit 04ed451

File tree

2 files changed

+55
-4
lines changed

2 files changed

+55
-4
lines changed

MaterialDesignThemes.Wpf/DialogHost.cs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public class DialogHost : ContentControl
6565
private DialogOpenedEventHandler _attachedDialogOpenedEventHandler;
6666
private DialogClosingEventHandler _attachedDialogClosingEventHandler;
6767
private object _closeDialogExecutionParameter;
68+
private IInputElement _restoreFocus;
69+
private Action _closeCleanUp = () => { };
6870

6971
static DialogHost()
7072
{
@@ -204,7 +206,7 @@ public DialogHost()
204206
Unloaded += OnUnloaded;
205207

206208
CommandBindings.Add(new CommandBinding(CloseDialogCommand, CloseDialogHandler, CloseDialogCanExecute));
207-
CommandBindings.Add(new CommandBinding(OpenDialogCommand, OpenDialogHandler));
209+
CommandBindings.Add(new CommandBinding(OpenDialogCommand, OpenDialogHandler));
208210
}
209211

210212
public static readonly DependencyProperty IdentifierProperty = DependencyProperty.Register(
@@ -220,7 +222,7 @@ public object Identifier
220222
}
221223

222224
public static readonly DependencyProperty IsOpenProperty = DependencyProperty.Register(
223-
"IsOpen", typeof (bool), typeof (DialogHost), new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsOpenPropertyChangedCallback));
225+
"IsOpen", typeof (bool), typeof (DialogHost), new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsOpenPropertyChangedCallback));
224226

225227
private static void IsOpenPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
226228
{
@@ -229,12 +231,18 @@ private static void IsOpenPropertyChangedCallback(DependencyObject dependencyObj
229231
ValidationAssist.SetSuppress(dialogHost._popupContentControl, !dialogHost.IsOpen);
230232
VisualStateManager.GoToState(dialogHost, dialogHost.SelectState(), !TransitionAssist.GetDisableTransitions(dialogHost));
231233

232-
if (!dialogHost.IsOpen)
234+
235+
if (dialogHost.IsOpen)
236+
{
237+
WatchWindowActivation(dialogHost);
238+
}
239+
else
233240
{
234241
dialogHost._asyncShowWaitHandle.Set();
235242
dialogHost._attachedDialogClosingEventHandler = null;
236243
dialogHost._session.IsEnded = true;
237244
dialogHost._session = null;
245+
dialogHost._closeCleanUp();
238246

239247
return;
240248
}
@@ -265,7 +273,7 @@ private static void IsOpenPropertyChangedCallback(DependencyObject dependencyObj
265273
//totally not happy about this, but on immediate validation we can get some wierd looking stuff...give WPF a kick to refresh...
266274
Task.Delay(300).ContinueWith(t => child.Dispatcher.BeginInvoke(new Action(() => child.InvalidateVisual())));
267275
}));
268-
}
276+
}
269277

270278
public bool IsOpen
271279
{
@@ -470,6 +478,14 @@ internal void Close(object parameter)
470478
_closeDialogExecutionParameter = parameter;
471479
}
472480

481+
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
482+
{
483+
var window = Window.GetWindow(this);
484+
if (window != null && !window.IsActive)
485+
window.Activate();
486+
base.OnPreviewMouseDown(e);
487+
}
488+
473489
private void OpenDialogHandler(object sender, ExecutedRoutedEventArgs executedRoutedEventArgs)
474490
{
475491
if (executedRoutedEventArgs.Handled) return;
@@ -541,5 +557,38 @@ private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
541557
{
542558
LoadedInstances.Add(this);
543559
}
560+
561+
private static void WatchWindowActivation(DialogHost dialogHost)
562+
{
563+
var window = Window.GetWindow(dialogHost);
564+
if (window != null)
565+
{
566+
window.Activated += dialogHost.WindowOnActivated;
567+
window.Deactivated += dialogHost.WindowOnDeactivated;
568+
dialogHost._closeCleanUp = () =>
569+
{
570+
window.Activated -= dialogHost.WindowOnActivated;
571+
window.Deactivated -= dialogHost.WindowOnDeactivated;
572+
};
573+
}
574+
else
575+
{
576+
dialogHost._closeCleanUp = () => { };
577+
}
578+
}
579+
580+
private void WindowOnDeactivated(object sender, EventArgs eventArgs)
581+
{
582+
_restoreFocus = _popupContentControl != null ? FocusManager.GetFocusedElement(_popupContentControl) : null;
583+
}
584+
585+
private void WindowOnActivated(object sender, EventArgs eventArgs)
586+
{
587+
if (_restoreFocus != null)
588+
{
589+
Dispatcher.BeginInvoke(new Action(() => Keyboard.Focus(_restoreFocus)));
590+
591+
}
592+
}
544593
}
545594
}

MaterialDesignThemes.Wpf/Themes/Generic.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,8 @@
608608
TextOptions.TextRenderingMode="Auto"
609609
Foreground="{DynamicResource MaterialDesignBody}"
610610
FontFamily="{StaticResource MaterialDesignFont}"
611+
FocusManager.IsFocusScope="True"
612+
KeyboardNavigation.TabNavigation="Contained"
611613
IsTabStop="False"
612614
Opacity="0"
613615
RenderTransformOrigin=".5,.5"

0 commit comments

Comments
 (0)