diff --git a/src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs b/src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs index 4309aa9fe377..fe2242915904 100644 --- a/src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs +++ b/src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; @@ -108,7 +108,11 @@ protected override void DisconnectHandler(FrameworkElement platformView) _currentShellSection.PropertyChanged -= OnCurrentShellSectionPropertyChanged; if (_currentSearchHandler != null) + { _currentSearchHandler.PropertyChanged -= OnCurrentSearchHandlerPropertyChanged; + _currentSearchHandler.ShowSoftInputRequested -= OnShowSoftInputRequested; + _currentSearchHandler.HideSoftInputRequested -= OnHideSoftInputRequested; + } if (_shellItem?.Parent is IShellController controller) { @@ -304,6 +308,8 @@ void UpdateSearchHandler() if (_currentSearchHandler is not null) { _currentSearchHandler.PropertyChanged -= OnCurrentSearchHandlerPropertyChanged; + _currentSearchHandler.ShowSoftInputRequested -= OnShowSoftInputRequested; + _currentSearchHandler.HideSoftInputRequested -= OnHideSoftInputRequested; } _currentSearchHandler = newSearchHandler; @@ -323,6 +329,8 @@ void UpdateSearchHandler() mauiNavView.AutoSuggestBox = autoSuggestBox; } + _currentSearchHandler.ShowSoftInputRequested += OnShowSoftInputRequested; + _currentSearchHandler.HideSoftInputRequested += OnHideSoftInputRequested; autoSuggestBox.ItemsSource = CreateSearchHandlerItemsSource(); autoSuggestBox.ItemTemplate = _currentSearchHandler.ItemTemplate is null ? null : (UI.Xaml.DataTemplate)WApp.Current.Resources["SearchHandlerItemTemplate"]; autoSuggestBox.UpdateTextOnSelect = false; @@ -382,6 +390,29 @@ void OnSearchBoxLostFocus(object sender, RoutedEventArgs e) _currentSearchHandler?.SetIsFocused(false); } + void OnShowSoftInputRequested(object? sender, EventArgs e) + { + if (PlatformView is not NavigationView mauiNavView || mauiNavView.AutoSuggestBox is not { } autoSuggestBox) + return; + + autoSuggestBox.Focus(FocusState.Programmatic); + } + + void OnHideSoftInputRequested(object? sender, EventArgs e) + { + if (PlatformView is not NavigationView mauiNavView || mauiNavView.AutoSuggestBox is not { } autoSuggestBox) + return; + + if (!autoSuggestBox.IsEnabled) + return; + + var isTabStop = autoSuggestBox.IsTabStop; + autoSuggestBox.IsTabStop = false; + autoSuggestBox.IsEnabled = false; + autoSuggestBox.IsEnabled = true; + autoSuggestBox.IsTabStop = isTabStop; + } + void OnSearchBoxTextChanged(Microsoft.UI.Xaml.Controls.AutoSuggestBox sender, Microsoft.UI.Xaml.Controls.AutoSuggestBoxTextChangedEventArgs args) { if (_currentSearchHandler == null) @@ -689,4 +720,4 @@ void OnApplyTemplateFinished(object? sender, EventArgs e) UpdateAppearance(_shellAppearanceElement); } } -} \ No newline at end of file +} diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue34930.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue34930.cs new file mode 100644 index 000000000000..416b7c811d5e --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue34930.cs @@ -0,0 +1,107 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 34930, "SearchHandler ShowSoftInputAsync does not focus the SearchHandler", PlatformAffected.UWP)] +public class Issue34930 : Shell +{ + public Issue34930() + { + var flyoutItem = new FlyoutItem + { + Route = "home", + FlyoutDisplayOptions = FlyoutDisplayOptions.AsSingleItem + }; + + flyoutItem.Items.Add(new Tab + { + Title = "Home", + Route = "hometab", + Items = + { + new ShellContent + { + Title = "Home", + Route = "homepage", + ContentTemplate = new DataTemplate(typeof(_34930TestPage)) + } + } + }); + + Items.Add(flyoutItem); + } + + public class _34930TestPage : ContentPage + { + public _34930TestPage() + { + Title = "Home"; + + var isFocusedLabel = new Label + { + Text = "IsFocused: False", + AutomationId = "IsFocusedLabel" + }; + + var focusedEventLabel = new Label + { + Text = "FocusedEvent: False", + AutomationId = "FocusedEventLabel" + }; + + var searchHandler = new SearchHandler + { + AutomationId = "SearchHandler", + Placeholder = "Search...", + SearchBoxVisibility = SearchBoxVisibility.Expanded, + ShowsResults = false + }; + + searchHandler.Focused += (s, e) => + { + isFocusedLabel.Text = "IsFocused: True"; + focusedEventLabel.Text = "FocusedEvent: True"; + }; + + searchHandler.Unfocused += (s, e) => + { + isFocusedLabel.Text = "IsFocused: False"; + }; + + var showKeyboardButton = new Button + { + Text = "Show Soft Input", + AutomationId = "ShowKeyboardButton" + }; + + showKeyboardButton.Clicked += (s, e) => + { + searchHandler.ShowSoftInputAsync(); + }; + + var hideKeyboardButton = new Button + { + Text = "Hide Soft Input", + AutomationId = "HideKeyboardButton" + }; + + hideKeyboardButton.Clicked += (s, e) => + { + searchHandler.HideSoftInputAsync(); + }; + + Shell.SetSearchHandler(this, searchHandler); + + Content = new VerticalStackLayout + { + Spacing = 15, + Padding = 20, + Children = + { + showKeyboardButton, + hideKeyboardButton, + isFocusedLabel, + focusedEventLabel + } + }; + } + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34930.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34930.cs new file mode 100644 index 000000000000..97ffae1950de --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34930.cs @@ -0,0 +1,45 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues +{ + public class Issue34930 : _IssuesUITest + { + public override string Issue => "SearchHandler ShowSoftInputAsync does not focus the SearchHandler"; + + public Issue34930(TestDevice testDevice) : base(testDevice) + { + } + + [Test] + [Category(UITestCategories.SoftInput)] + public void SearchHandlerShowSoftInputShouldFocusSearchHandlerOnWindows() + { + App.WaitForElement("ShowKeyboardButton"); + App.Tap("ShowKeyboardButton"); + + App.WaitForTextToBePresentInElement("IsFocusedLabel", "IsFocused: True"); + var isFocused = App.WaitForElement("IsFocusedLabel").GetText(); + Assert.That(isFocused, Is.EqualTo("IsFocused: True")); + + App.WaitForTextToBePresentInElement("FocusedEventLabel", "FocusedEvent: True"); + var focusedEvent = App.WaitForElement("FocusedEventLabel").GetText(); + Assert.That(focusedEvent, Is.EqualTo("FocusedEvent: True")); + } + + [Test] + [Category(UITestCategories.SoftInput)] + public void SearchHandlerHideSoftInputShouldUnfocusSearchHandlerOnWindows() + { + App.WaitForElement("ShowKeyboardButton"); + App.Tap("ShowKeyboardButton"); + App.WaitForTextToBePresentInElement("IsFocusedLabel", "IsFocused: True"); + + App.Tap("HideKeyboardButton"); + App.WaitForTextToBePresentInElement("IsFocusedLabel", "IsFocused: False"); + var isFocused = App.WaitForElement("IsFocusedLabel").GetText(); + Assert.That(isFocused, Is.EqualTo("IsFocused: False")); + } + } +}