I implemented a SearchTextBox and it works finally however it is pretty slow (Autosuggestions show up after 5-7 seconds). I read from a CSV file and create an object type Observable Collection and dump that into SuggestionSource then filter the results as SearchBox text change. Altogether there are about 700 suggestions and each suggestion has 50-100 characters. Is it normal to be slow under these circumstances or what I am doing wrong?
XAML :
<controls:SearchTextBox x:Name="SearchLayersBox" Height="23" Margin="5,5,10,10" VerticalAlignment="Top" InfoText="Search" SearchMode="Auto" ShowHistory="True" Search="SearchTextBox_Search" Initialized="SearchLayersBox_Initialized" TextChanged="SearchLayersBox_TextChanged" SuggestionListMax="15" />
C#
public void LayersListSearchBox()
{
LayerDict.Clear();
DataListBoxSource.Clear();
var path = @"\\nrdsmnt6\mine maps\DMP_Database\Layer_Properties_spc_CSV.csv";
using (TextFieldParser csvParser = new TextFieldParser(path))
{
csvParser.SetDelimiters(new string[] { "*%&" });
csvParser.HasFieldsEnclosedInQuotes = false;
//Skip the row with the column names
csvParser.ReadLine();
while (!csvParser.EndOfData)
{
string[] fields = csvParser.ReadFields();
string LayerDisplayName = fields[3].Substring(1);
SearchSuggestCollection.Add(LayerDisplayName);
}
}
SearchLayersBox.SuggestionSource = SearchSuggestCollection;
}
private void SearchLayersBox_TextChanged(object sender, TextChangedEventArgs e)
{
string searchString = SearchLayersBox.Text;
ObservableCollection<object> filteredCollection = new ObservableCollection<object>(from objectL in SearchSuggestCollection where objectL.ToString().Contains(searchString) select objectL);
SearchLayersBox.SuggestionSource = filteredCollection;
}
private void SearchLayersBox_Initialized(object sender, EventArgs e)
{
LayersListSearchBox();
}
UPDATE 1
After reading comments I switched to ICollectionView to filter the ObservableCollection
public ICollectionView SearchView
{
get { return CollectionViewSource.GetDefaultView(SearchSuggestCollection); }
}
and inserted binding to SearchView as @Bandook and @ASh suggest by following ASh's answer
<controls:SearchTextBox x:Name="SearchLayersBox" SuggestionSource="{Binding SearchView, UpdateSourceTrigger=PropertyChanged}" Height="23" Margin="5,5,10,10" VerticalAlignment="Top" InfoText="Search" SearchMode="Auto" ShowHistory="True" Search="SearchTextBox_Search" Initialized="SearchLayersBox_Initialized" TextChanged="SearchLayersBox_TextChanged" SuggestionListMax="15" />
Also, I required at least three letters entered before autosuggestion show up.
private void SearchLayersBox_TextChanged(object sender, TextChangedEventArgs e)
{
string searchString = SearchLayersBox.Text;
if (searchString.Length >= 3)
{
SearchView.Filter = item =>
{
return item.ToString().Contains(searchString);
};
}
}
I think the binding to SearchView does not work. Is this not right way to create the binding?
SuggestionSource="{Binding SearchView, UpdateSourceTrigger=PropertyChanged}"
UPDATE 2
After trying too many attempts much frustration I could not find the solution in the proper way however I make it pretty fast after removing initial SuggestSource assignments and requiring at least 3 letters before firing the suggestions
XAML:
<controls:SearchTextBox x:Name="SearchLayersBox" Height="23"
Margin="5,5,10,10" VerticalAlignment="Top" InfoText="Search here"
SearchMode="Auto" ShowHistory="True" Search="SearchTextBox_Search"
Initialized="SearchLayersBox_Initialized"
TextChanged="SearchLayersBox_TextChanged" SuggestionListMax="15" />
C#
private ObservableCollection<object> _searchSuggestionCollection;
public ObservableCollection<object> SearchSuggestCollection
{
get { return _searchSuggestionCollection; }
set
{
if (_searchSuggestionCollection != value)
{
_searchSuggestionCollection = value;
OnPropertyChanged();
}
}
}
void LayersListSearchBox()
{
LayerDict.Clear();
DataListBoxSource.Clear();
var path = @"\\nrdsmnt6\mine maps\DMP_Database\Layer_Properties_spc_CSV.csv";
SearchSuggestCollection = new ObservableCollection<object>();
using (TextFieldParser csvParser = new TextFieldParser(path))
{
csvParser.SetDelimiters(new string[] { "*%&" });
csvParser.HasFieldsEnclosedInQuotes = false;
//Skip the row with the column names
csvParser.ReadLine();
while (!csvParser.EndOfData)
{
string[] fields = csvParser.ReadFields();
string LayerDisplayName = fields[3].Substring(1);
SearchSuggestCollection.Add(LayerDisplayName);
}
}
}
private void SearchLayersBox_Initialized(object sender, EventArgs e)
{
LayersListSearchBox();
}
private void SearchLayersBox_TextChanged(object sender, TextChangedEventArgs e)
{
string searchString = SearchLayersBox.Text;
SearchLayersBox.SuggestionSource = null;
if (searchString.Length >= 3)
{
ObservableCollection<object> filteredCollection = new ObservableCollection<object>(from objectL in SearchSuggestCollection where objectL.ToString().Contains(searchString) select objectL);
SearchLayersBox.SuggestionSource = filteredCollection;
}
}