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

Adding Controls Search Bar #661

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
11 changes: 11 additions & 0 deletions Sample Applications/WPFGallery/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,17 @@
KeyUp="SearchBox_KeyUp"
LostFocus="SearchBox_LostFocus" />-->

<!--ItemsSource="{Binding ViewModel.FilteredSearchItems}"-->

<ComboBox x:Name="SearchBox"
IsEditable="True"
Text="{Binding ViewModel.SearchBoxText, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding ViewModel.FilteredSearchItems}"
Margin="10"
IsTextSearchEnabled="False"
PreviewKeyDown="SearchBox_PreviewKeyDown"
GotFocus="SearchBox_GotFocus"
DropDownClosed="SearchBox_DropDownClosed" />

<TreeView
x:Name="ControlsList"
Expand Down
45 changes: 34 additions & 11 deletions Sample Applications/WPFGallery/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ public MainWindow(MainWindowViewModel viewModel, IServiceProvider serviceProvide

SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
this.StateChanged += MainWindow_StateChanged;

ChangeSearchBoxStyle();
}

private void ChangeSearchBoxStyle()
{
var template = SearchBox.Template;
}

private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
Expand Down Expand Up @@ -134,17 +141,6 @@ private void Toggle_TitleButtonVisibility()
}
}

//private void SearchBox_KeyUp(object sender, KeyEventArgs e)
//{
// ViewModel.UpdateSearchText(SearchBox.Text);
//}

//private void SearchBox_LostFocus(object sender, RoutedEventArgs e)
//{
// SearchBox.Text = "";
// ViewModel.UpdateSearchText(SearchBox.Text);
//}

private void MinimizeWindow(object sender, RoutedEventArgs e)
{
this.WindowState = WindowState.Minimized;
Expand Down Expand Up @@ -250,4 +246,31 @@ private void ControlsList_Loaded(object sender, RoutedEventArgs e)
}
}
}

private void SearchBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
var comboBox = sender as ComboBox;

if(!string.IsNullOrWhiteSpace(comboBox.Text))
{
comboBox.IsDropDownOpen = true;
}
}

private void SearchBox_DropDownClosed(object sender, EventArgs e)
{
var comboBox = sender as ComboBox;

if (comboBox.SelectedItem != null)
{
_navigationService.Navigate(comboBox.SelectedItem.ToString());
}
}

private void SearchBox_GotFocus(object sender, RoutedEventArgs e)
{
var comboBox = sender as ComboBox;

comboBox.IsDropDownOpen = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the behavior when we navigate on the drop down using arrow keys ? For A11y, we will have to avoid selection, but I am guessing that's working correctly. I will try to run the changes and check it out. Overall, good work.

}
}
20 changes: 20 additions & 0 deletions Sample Applications/WPFGallery/Models/ControlsInfoDataSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,25 @@ public ICollection<ControlInfoDataItem> GetGroupedControlsInfo()
{
return ControlsInfo.Where(x => x.IsGroup == true && x.UniqueId != "Design Guidance" && x.UniqueId != "Samples").ToList();
}

public ObservableCollection<string> GetAllPagesForSearch()
{
ObservableCollection<string> allPagesForSearch = new ObservableCollection<string>();

ICollection<ControlInfoDataItem> allPages = ControlsInfoDataSource.Instance.ControlsInfo;

foreach (ControlInfoDataItem item in allPages)
{
allPagesForSearch.Add(item.Title);

foreach (ControlInfoDataItem individualItem in item.Items)
{
allPagesForSearch.Add(individualItem.Title);
}
}

return allPagesForSearch;

}
}
}
35 changes: 33 additions & 2 deletions Sample Applications/WPFGallery/Navigation/NavigationService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections;
using System.Windows.Navigation;
using WPFGallery.Models;

namespace WPFGallery.Navigation;

Expand All @@ -10,6 +9,8 @@ public interface INavigationService
{
void Navigate(Type type);

void Navigate(string str);

void NavigateTo(Type type);

void SetFrame(Frame frame);
Expand Down Expand Up @@ -40,12 +41,33 @@ public class NavigationService : INavigationService

public event EventHandler<NavigatingEventArgs> Navigating;

private Dictionary<string, Type> _pageNameToTypeMapping;


public NavigationService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
_history = new Stack<Type>();
_future = new Stack<Type>();

InitializeMapping();
}

private void InitializeMapping()
{
ICollection<ControlInfoDataItem> allPages = ControlsInfoDataSource.Instance.ControlsInfo;

_pageNameToTypeMapping = new();

foreach (ControlInfoDataItem item in allPages)
{
_pageNameToTypeMapping[item.Title] = item.PageType;

foreach (ControlInfoDataItem individualItem in item.Items)
{
_pageNameToTypeMapping[individualItem.Title] = individualItem.PageType;
}
}
}

public void SetFrame(Frame frame)
Expand Down Expand Up @@ -73,6 +95,15 @@ public void Navigate(Type type)
}
}

public void Navigate(string? pageName)
{
if (!string.IsNullOrEmpty(pageName) && _pageNameToTypeMapping.ContainsKey(pageName))
{
Type currentPage = _pageNameToTypeMapping[pageName];
Navigate(currentPage);
}
}

public void NavigateBack()
{
if(_history.Count > 0)
Expand Down
47 changes: 47 additions & 0 deletions Sample Applications/WPFGallery/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,39 @@ public partial class MainWindowViewModel : ObservableObject
[ObservableProperty]
private string _applicationTitle = "WPF Gallery Preview";

private ObservableCollection<string> SearchItems { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the need for search items ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It contains the list of all pages in string format. This is then used to filter out from this whole set without changing the original FilteredSearchItems.


public ObservableCollection<string> FilteredSearchItems { get; set; }

private string _searchBoxText;

public string SearchBoxText
{
get => _searchBoxText;
set
{
_searchBoxText = value;
OnPropertyChanged(nameof(SearchBoxText));
FilterItems();
}
}

private void FilterItems()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should go in ControlsInfoDataSource.cs .

{
if (string.IsNullOrEmpty(SearchBoxText))
{
FilteredSearchItems = new ObservableCollection<string>(SearchItems);
}
else
{
FilteredSearchItems = new ObservableCollection<string>(
SearchItems.Where(item => item.ToLower().Contains(SearchBoxText.ToLower()))
);
}

OnPropertyChanged(nameof(FilteredSearchItems));
}

private readonly DispatcherTimer _timer;

private string _searchText = string.Empty;
Expand Down Expand Up @@ -56,6 +89,20 @@ public MainWindowViewModel(INavigationService navigationService)
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(400);
_timer.Tick += PerformSearchNavigation;

SearchItems = new();

foreach (ControlInfoDataItem mainPage in Controls)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even this should go in ControlsInfoDataSource.cs
Reasoning being, it is not related to MainWindow, and it may be needed by multiple viewmodels.

{
SearchItems.Add(mainPage.ToString());

foreach (ControlInfoDataItem controlsPage in mainPage.Items)
{
SearchItems.Add(controlsPage.ToString());
}
}

FilteredSearchItems = new ObservableCollection<string>(SearchItems);
}

public void UpdateSearchText(string searchText)
Expand Down
Loading