Skip to content

Commit aabf8cd

Browse files
authored
"fix" AutoSuggestBox has weird tab behavior (#3765)
* -prevent Selection in AutoSuggestBox if the DropDown-List is not open -do not mark event as handled to enable "normal" TAB and Shift+TAB behavior * mark the event as handled if an item was selected by pressing TAB so that the base.OnPreviewKeyDown does not move focus to the next element * added a first test case * added some comments and Assertions in unit test
1 parent 6ae4ff6 commit aabf8cd

File tree

2 files changed

+58
-7
lines changed

2 files changed

+58
-7
lines changed

src/MaterialDesignThemes.Wpf/AutoSuggestBox.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,29 +145,37 @@ public override void OnApplyTemplate()
145145

146146
protected override void OnPreviewKeyDown(KeyEventArgs e)
147147
{
148-
base.OnPreviewKeyDown(e);
149148
if (_autoSuggestBoxList is null) return;
150149
switch (e.Key)
151150
{
152151
case Key.Down:
153152
IncrementSelection();
153+
e.Handled = true;
154154
break;
155155
case Key.Up:
156156
DecrementSelection();
157+
e.Handled = true;
157158
break;
158159
case Key.Enter:
159160
CommitValueSelection();
161+
e.Handled = true;
160162
break;
161163
case Key.Escape:
162164
CloseAutoSuggestionPopUp();
165+
e.Handled = true;
163166
break;
164167
case Key.Tab:
165-
CommitValueSelection();
168+
bool wasItemSelected = CommitValueSelection();
169+
// Only mark the event as handled if the SuggestionList is open and therefore the Selection was successful
170+
if (wasItemSelected)
171+
{
172+
e.Handled = true;
173+
}
166174
break;
167175
default:
168176
return;
169177
}
170-
e.Handled = true;
178+
base.OnPreviewKeyDown(e);
171179
}
172180

173181
protected override void OnLostFocus(RoutedEventArgs e)
@@ -230,11 +238,16 @@ private void CloseAutoSuggestionPopUp()
230238
IsSuggestionOpen = false;
231239
}
232240

233-
private void CommitValueSelection()
241+
private bool CommitValueSelection()
234242
=> CommitValueSelection(_autoSuggestBoxList?.SelectedValue);
235243

236-
private void CommitValueSelection(object? selectedValue)
244+
private bool CommitValueSelection(object? selectedValue)
237245
{
246+
if (IsSuggestionOpen == false)
247+
{
248+
return false;
249+
}
250+
238251
string oldValue = Text;
239252
Text = selectedValue?.ToString();
240253
if (Text != null)
@@ -247,6 +260,7 @@ private void CommitValueSelection(object? selectedValue)
247260
RoutedEvent = SuggestionChosenEvent
248261
};
249262
RaiseEvent(args);
263+
return true;
250264
}
251265

252266
private void DecrementSelection()

tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using MaterialDesignThemes.UITests.Samples.AutoSuggestBoxes;
1+
using System.ComponentModel;
2+
using MaterialDesignThemes.UITests.Samples.AutoSuggestBoxes;
23
using MaterialDesignThemes.UITests.Samples.AutoSuggestTextBoxes;
34
using Xunit.Sdk;
45

@@ -47,7 +48,7 @@ public async Task CanFilterItems_WithSuggestionsAndDisplayMember_FiltersSuggesti
4748
public async Task CanChoiceItem_FromTheSuggestions_AssertTheTextUpdated()
4849
{
4950
await using var recorder = new TestRecorder(App);
50-
51+
5152
//Arrange
5253
IVisualElement<AutoSuggestBox> suggestBox = (await LoadUserControl<AutoSuggestTextBoxWithTemplate>()).As<AutoSuggestBox>();
5354
IVisualElement<Popup> popup = await suggestBox.GetElement<Popup>();
@@ -122,6 +123,42 @@ public async Task CanFilterItems_WithCollectionView_FiltersSuggestions()
122123
recorder.Success();
123124
}
124125

126+
[Fact]
127+
[Description("Issue 3761")]
128+
public async Task AutoSuggestBox_MovesFocusToNextElement_WhenPopupIsClosed()
129+
{
130+
await using var recorder = new TestRecorder(App);
131+
132+
// Arrange
133+
string xaml = """
134+
<StackPanel>
135+
<local:AutoSuggestTextBoxWithCollectionView x:Name="AutoSuggestBoxSample" />
136+
<TextBox x:Name="NextTextBox" />
137+
</StackPanel>
138+
""";
139+
140+
IVisualElement<StackPanel> stackPanel = await LoadXaml<StackPanel>(xaml, ("local", typeof(AutoSuggestTextBoxWithCollectionView)));
141+
var suggestBoxSample = await stackPanel.GetElement<AutoSuggestTextBoxWithCollectionView>("AutoSuggestBoxSample");
142+
IVisualElement<AutoSuggestBox> suggestBox = await suggestBoxSample.GetElement<AutoSuggestBox>();
143+
IVisualElement<TextBox> nextTextBox = await stackPanel.GetElement<TextBox>("NextTextBox");
144+
145+
// Act
146+
await suggestBox.MoveKeyboardFocus();
147+
await Task.Delay(50);
148+
await suggestBox.SendInput(new KeyboardInput("B")); // Open the popup
149+
await Task.Delay(50);
150+
await suggestBox.SendInput(new KeyboardInput(Key.Escape)); // Close the popup
151+
await Task.Delay(50);
152+
await suggestBox.SendInput(new KeyboardInput(Key.Tab)); // Press TAB to focus the next element
153+
await Task.Delay(50);
154+
155+
// Assert
156+
Assert.False(await suggestBox.GetIsFocused());
157+
Assert.True(await nextTextBox.GetIsFocused());
158+
159+
recorder.Success();
160+
}
161+
125162
private static async Task AssertExists(IVisualElement<ListBox> suggestionListBox, string text, bool existsOrNotCheck = true)
126163
{
127164
try

0 commit comments

Comments
 (0)