Skip to content

Commit 1dba625

Browse files
committed
Improve JsonNavigationService
1 parent 8f54b6b commit 1dba625

3 files changed

Lines changed: 115 additions & 39 deletions

File tree

dev/DevWinUI/Services/NavigationService/Contracts/IJsonNavigationService.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ public interface IJsonNavigationService
1010
event NavigatedEventHandler FrameNavigated;
1111
IList<object>? MenuItems { get; }
1212
object? SettingsItem { get; }
13-
IEnumerable<DataItem> SearchNavigationViewItems(IEnumerable<DataItem> items, string query);
14-
1513
bool CanGoBack { get; }
1614
Frame? Frame { get; set; }
1715
Window? Window { get; set; }

dev/DevWinUI/Services/NavigationService/Services/JsonNavigationService/JsonNavigationService.Service.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public bool Navigate(Type pageType, object? parameter = null, bool clearNavigati
9090
_mainBreadcrumb.AddNewItem(pageType, null, parameter, parameter, _allowDuplication, null);
9191
}
9292

93-
var frameContentBeforeNavigationAOTSafe = _frame?.Content;
93+
var frameContentBeforeNavigationAOTSafe = _frame.Content;
9494

9595
var navigated = _frame.Navigate(pageType, parameter, transitionInfo);
9696
if (navigated)

dev/DevWinUI/Services/NavigationService/Services/JsonNavigationService/JsonNavigationService.cs

Lines changed: 114 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -145,57 +145,68 @@ public void UnregisterEvents()
145145

146146
private void OnAutoSuggestBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
147147
{
148-
if (args.ChosenSuggestion != null)
148+
if (args.ChosenSuggestion != null && args.ChosenSuggestion is DataItem infoDataItem)
149149
{
150-
if (args.ChosenSuggestion is DataItem)
150+
var hasChangedSelection = EnsureItemIsVisibleInNavigation(infoDataItem.Title);
151+
152+
// In case the menu selection has changed, it means that it has triggered
153+
// the selection changed event, that will navigate to the page already
154+
if (!hasChangedSelection)
151155
{
152-
var infoDataItem = args.ChosenSuggestion as DataItem;
153156
NavigateTo(infoDataItem.UniqueId, infoDataItem);
154157
}
155158
}
156159
}
157160

158161
private void OnAutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
159162
{
160-
var matches = SearchNavigationViewItems(DataSource.Instance.Groups.SelectMany(group => group.Items), sender.Text);
161-
162-
if (matches.Any())
163+
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
163164
{
164-
foreach (var item in matches)
165+
var suggestions = new List<DataItem>();
166+
167+
var querySplit = sender.Text.Split(" ");
168+
foreach (var group in DataSource.Instance.Groups)
165169
{
166-
if (string.IsNullOrEmpty(item.ImagePath))
170+
var matchingItems = group.Items.Where(
171+
item =>
172+
{
173+
// Idea: check for every word entered (separated by space) if it is in the name,
174+
// e.g. for query "split button" the only result should "SplitButton" since its the only query to contain "split" and "button"
175+
// If any of the sub tokens is not in the string, we ignore the item. So the search gets more precise with more words
176+
bool flag = item.IncludedInBuild;
177+
foreach (string queryToken in querySplit)
178+
{
179+
// Check if token is not in string
180+
if (item.Title.IndexOf(queryToken, StringComparison.CurrentCultureIgnoreCase) < 0)
181+
{
182+
// Token is not in string, so we ignore this item.
183+
flag = false;
184+
}
185+
}
186+
return flag;
187+
});
188+
foreach (var item in matchingItems)
167189
{
168-
item.ImagePath = _autoSuggestBoxNotFoundImagePath;
190+
if (string.IsNullOrEmpty(item.ImagePath))
191+
{
192+
item.ImagePath = _autoSuggestBoxNotFoundImagePath;
193+
}
194+
suggestions.Add(item);
169195
}
170196
}
171-
_autoSuggestBox.ItemsSource = matches.OrderByDescending(i => i.Title.StartsWith(sender.Text.ToLowerInvariant())).ThenBy(i => i.Title);
172-
}
173-
else
174-
{
175-
var noResultsItem = new DataItem();
176-
noResultsItem.Title = _autoSuggestBoxNotFoundString;
177-
noResultsItem.ImagePath = _autoSuggestBoxNotFoundImagePath;
178-
179-
var noResultsList = new List<DataItem>();
180-
noResultsList.Add(noResultsItem);
181-
_autoSuggestBox.ItemsSource = noResultsList;
182-
}
183-
}
184-
185-
public IEnumerable<DataItem> SearchNavigationViewItems(IEnumerable<DataItem> items, string query)
186-
{
187-
if (string.IsNullOrWhiteSpace(query))
188-
yield break;
189-
190-
query = query.Trim();
191-
192-
foreach (var item in items)
193-
{
194-
if (!string.IsNullOrEmpty(item.Title)
195-
&& item.Title.Contains(query, StringComparison.OrdinalIgnoreCase)
196-
&& item.UniqueId != null)
197+
if (suggestions.Count > 0)
197198
{
198-
yield return item;
199+
_autoSuggestBox.ItemsSource = suggestions.OrderByDescending(i => i.Title.StartsWith(sender.Text, StringComparison.CurrentCultureIgnoreCase)).ThenBy(i => i.Title);
200+
}
201+
else
202+
{
203+
var noResultsItem = new DataItem();
204+
noResultsItem.Title = _autoSuggestBoxNotFoundString;
205+
noResultsItem.ImagePath = _autoSuggestBoxNotFoundImagePath;
206+
207+
var noResultsList = new List<DataItem>();
208+
noResultsList.Add(noResultsItem);
209+
_autoSuggestBox.ItemsSource = noResultsList;
199210
}
200211
}
201212
}
@@ -257,4 +268,71 @@ private bool EnsureNavigationSelectionBase(object rawItem, string id, Navigation
257268
}
258269
return false;
259270
}
271+
272+
public bool EnsureItemIsVisibleInNavigation(string name)
273+
{
274+
bool changedSelection = false;
275+
foreach (object rawItem in this.AllMenuItems)
276+
{
277+
// Check if we encountered the separator
278+
if (!(rawItem is NavigationViewItem))
279+
{
280+
// Skipping this item
281+
continue;
282+
}
283+
284+
var item = rawItem as NavigationViewItem;
285+
286+
// Check if we are this category
287+
if ((string)item.Content == name)
288+
{
289+
_navigationView.SelectedItem = item;
290+
changedSelection = true;
291+
}
292+
// We are not :/
293+
else
294+
{
295+
// Maybe one of our items is?
296+
if (item.MenuItems.Count != 0)
297+
{
298+
foreach (NavigationViewItem child in item.MenuItems)
299+
{
300+
if ((string)child.Content == name)
301+
{
302+
// We are the item corresponding to the selected one, update selection!
303+
304+
// Deal with differences in displaymodes
305+
if (_navigationView.PaneDisplayMode == NavigationViewPaneDisplayMode.Top)
306+
{
307+
// In Topmode, the child is not visible, so set parent as selected
308+
// Everything else does not work unfortunately
309+
_navigationView.SelectedItem = item;
310+
item.StartBringIntoView();
311+
}
312+
else
313+
{
314+
// Expand so we animate
315+
item.IsExpanded = true;
316+
// Ensure parent is expanded so we actually show the selection indicator
317+
_navigationView.UpdateLayout();
318+
// Set selected item
319+
_navigationView.SelectedItem = child;
320+
child.StartBringIntoView();
321+
}
322+
// Set to true to also skip out of outer for loop
323+
changedSelection = true;
324+
// Break out of child iteration for loop
325+
break;
326+
}
327+
}
328+
}
329+
}
330+
// We updated selection, break here!
331+
if (changedSelection)
332+
{
333+
break;
334+
}
335+
}
336+
return changedSelection;
337+
}
260338
}

0 commit comments

Comments
 (0)