diff --git a/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.cs b/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.cs index f5128a000a5e..c9bad6489962 100644 --- a/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.cs @@ -1,7 +1,10 @@ using System; +using System.Threading; using System.Threading.Tasks; using Microsoft.Maui.Controls; +using Microsoft.Maui.DeviceTests.Stubs; using Microsoft.Maui.Handlers; +using Microsoft.Maui.Hosting; using Xunit; namespace Microsoft.Maui.DeviceTests @@ -52,6 +55,67 @@ await InvokeOnMainThreadAsync(() => Assert.True(platformControl.IsReadOnly); }); } + + + [Fact(DisplayName = "Unfocus will work when page is shown a 2nd time")] + public async Task UnFocusOnEntryAfterPagePop() + { + int unfocused = 0; + EnsureHandlerCreated(builder => + { + builder.ConfigureMauiHandlers(handlers => + { + handlers.AddHandler(typeof(Toolbar), typeof(ToolbarHandler)); + handlers.AddHandler(typeof(NavigationPage), typeof(NavigationViewHandler)); + handlers.AddHandler(); + handlers.AddHandler(typeof(Window), typeof(WindowHandlerStub)); + handlers.AddHandler(typeof(Entry), typeof(EntryHandler)); + + }); + }); + AutoResetEvent _focused = new AutoResetEvent(false); + AutoResetEvent _unFocused = new AutoResetEvent(false); + var entry = new Entry(); + entry.Unfocused += (s, e) => + { + if (!e.IsFocused) + { + unfocused++; + } + _unFocused.Set(); + }; + var navPage = new NavigationPage(new ContentPage { Content = entry }); + var window = new Window(navPage); + + await CreateHandlerAndAddToWindow(window, async (handler) => + { + await Task.Run(() => + { + InvokeOnMainThreadAsync(() => + { + entry.Focused += (s, e) => _focused.Set(); + entry.Focus(); + }); + _focused.WaitOne(); + _focused.Reset(); + InvokeOnMainThreadAsync(async () => + { + entry.Unfocus(); + await navPage.PushAsync(new ContentPage()); + await navPage.PopAsync(); + entry.Focus(); + }); + _focused.WaitOne(); + _unFocused.Reset(); + InvokeOnMainThreadAsync(() => + { + entry.Unfocus(); + }); + _unFocused.WaitOne(); + Assert.True(unfocused == 2); + }); + }); + } #endif [Theory(DisplayName = "CursorPosition Initializes Correctly")] diff --git a/src/Core/src/Platform/Windows/ViewExtensions.cs b/src/Core/src/Platform/Windows/ViewExtensions.cs index 2120a2c944e9..5b71fba725c4 100644 --- a/src/Core/src/Platform/Windows/ViewExtensions.cs +++ b/src/Core/src/Platform/Windows/ViewExtensions.cs @@ -19,8 +19,6 @@ namespace Microsoft.Maui.Platform { public static partial class ViewExtensions { - internal static Page? ContainingPage; // Cache of containing page used for unfocusing - public static void TryMoveFocus(this FrameworkElement platformView, FocusNavigationDirection direction) { if (platformView?.XamlRoot?.Content is UIElement elem) @@ -361,39 +359,11 @@ internal static void UnfocusControl(Control control) if (control == null || !control.IsEnabled) return; - // "Unfocusing" doesn't really make sense on Windows; for accessibility reasons, - // something always has focus. So forcing the unfocusing of a control would normally - // just move focus to the next control, or leave it on the current control if no other - // focus targets are available. This is what happens if you use the "disable/enable" - // hack. What we *can* do is set the focus to the Page which contains Control; - // this will cause Control to lose focus without shifting focus to, say, the next Entry - - if (ContainingPage == null) - { - // Work our way up the tree to find the containing Page - DependencyObject parent = control; - - while (parent != null && parent is not Page) - { - parent = VisualTreeHelper.GetParent(parent); - } - - ContainingPage = parent as Page; - } - - if (ContainingPage != null) - { - // Cache the tabstop setting - var wasTabStop = ContainingPage.IsTabStop; - - // Controls can only get focus if they're a tabstop - ContainingPage.IsTabStop = true; - ContainingPage.Focus(FocusState.Programmatic); - - // Restore the tabstop setting; that may cause the Page to lose focus, - // but it won't restore the focus to Control - ContainingPage.IsTabStop = wasTabStop; - } + var isTabStop = control.IsTabStop; + control.IsTabStop = false; + control.IsEnabled = false; + control.IsEnabled = true; + control.IsTabStop = isTabStop; } internal static IWindow? GetHostedWindow(this IView? view)