Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: AutoSuggestBox should keep focus when popup is opened #7736

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/articles/feature-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ This can be changed using `Uno.UI.FeatureConfiguration.Style.UseUWPDefaultStyles
By default, Uno automatically enables accessibility text scaling on iOS and Android devices however to have more control an option has been added to disable text scaling.

Use `Uno.UI.FeatureConfiguration.Font.IgnoreTextScaleFactor` to control this.

## Popups

In older versions of Uno Platforms, the `Popup.IsLightDismissEnabled` dependency property defaulted to `true`. In UWP/WinUI and Uno 4.1 and newer, it correctly defaults to `false`. If your code depended on the old behavior, you can set the `Uno.UI.FeatureConfiguration.Popup.EnableLightDismissByDefault` property to `true` to override this.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Input;
using static Private.Infrastructure.TestServices;

namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls
Expand Down Expand Up @@ -54,5 +56,45 @@ public async Task When_Text_Changed_And_Focused_Should_Open_Suggestion_List()
SUT.IsSuggestionListOpen.Should().BeTrue();
}
#endif

[TestMethod]
public async Task When_Typing_Should_Keep_Focus()
{
static void GettingFocus(object sender, GettingFocusEventArgs e)
{
if (e.NewFocusedElement is Popup)
{
Assert.Fail();
}
}
Button button = null;
try
{
var SUT = new AutoSuggestBox();
button = new Button();
var stack = new StackPanel()
{
Children =
{
button,
SUT
}
};
SUT.ItemsSource = new List<string>() { "ab", "abc", "abcde" };
WindowHelper.WindowContent = stack;
await WindowHelper.WaitForIdle();

SUT.Focus(FocusState.Programmatic);
FocusManager.GettingFocus += GettingFocus;
SUT.Text = "a";
await WindowHelper.WaitForIdle();
}
finally
{
FocusManager.GettingFocus -= GettingFocus;
button?.Focus(FocusState.Programmatic); // Unfocus the AutoSuggestBox to ensure popup is closed.
await WindowHelper.WaitForIdle();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls_Primitives.PopupPages;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;
using static Private.Infrastructure.TestServices;

Expand Down Expand Up @@ -55,6 +56,13 @@ public async Task Check_Can_Reach_Main_Visual_Tree_Alternate_Mode()
}
#endif

[TestMethod]
public void When_IsLightDismissEnabled_Default()
{
var popup = new Popup();
Assert.IsFalse(popup.IsLightDismissEnabled);
}

private static bool CanReach(DependencyObject startingElement, DependencyObject targetElement)
{
var currentElement = startingElement;
Expand Down
9 changes: 9 additions & 0 deletions src/Uno.UI/FeatureConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,15 @@ public static class Popup
/// </summary>
public static bool UseNativePopup { get; set; } = true;
#endif

/// <summary>
/// By default, light dismiss is disabled in UWP/WinUI unless
/// <see cref="Windows.UI.Xaml.Controls.Primitives.Popup.IsLightDismissEnabled"/> is explicitly set to true.
/// In earlier versions of Uno Platform, this property defaulted
/// to true, which was an incorrect behavior. If your code depends on this
/// legacy behavior, use this property to override it.
/// </summary>
public static bool EnableLightDismissByDefault { get; set; } = false;
MartinZikmund marked this conversation as resolved.
Show resolved Hide resolved
}

public static class ProgressRing
Expand Down
8 changes: 7 additions & 1 deletion src/Uno.UI/UI/Xaml/Controls/AutoSuggestBox/AutoSuggestBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,16 @@ protected override void OnApplyTemplate()
_suggestionsList = GetTemplateChild("SuggestionsList") as ListView;
_queryButton = GetTemplateChild("QueryButton") as Button;

// Uno specific: If the user enabled the legacy behavior for popup light dismiss default
// we force it to false explicitly to make sure the AutoSuggestBox works correctly.
if(FeatureConfiguration.Popup.EnableLightDismissByDefault)
{
_popup.IsLightDismissEnabled = false;
}

#if __ANDROID__
_popup.DisableFocus();
#endif
_popup.IsLightDismissEnabled = true;

UpdateQueryButton();
UpdateTextBox();
Expand Down
10 changes: 10 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/Popup/Popup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ public Popup()
Initialize();
}

internal override bool GetDefaultValue2(DependencyProperty property, out object defaultValue)
{
if (property == IsLightDismissEnabledProperty)
{
defaultValue = FeatureConfiguration.Popup.EnableLightDismissByDefault;
return true;
}
return base.GetDefaultValue2(property, out defaultValue);
}

private void Initialize()
{
InitializePartial();
Expand Down