Click here to Skip to main content
12,406,342 members (65,944 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

41.8K views
6K downloads
36 bookmarked
Posted

AutoComplete TextBox with SubString search, similar to SQL Like or Contains

, 12 Sep 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
A TextBox with autocomplete capabilities in the manner of SQL's Like command
AutoCompleteTextBoxSample.jpg

Introduction

I was searching for a TextBox with autocomplete capabilities considering substring matches. The solutions I found were little clumsy, so here is my rather simple, but stable solution.

Background

This is my first article, so don't expect this to be perfect. The code comments are overkill, I think, but this makes the source self explaining.

Well, there are a few differences between other approaches. At first, we use a Panel instead of a Form to display a list of suggestions. Secondly, we use IndexOf instead of Linq to find the matches. Thirdly, we use pure safe .NET code only, no Win32 Calls and no sloppy threading, e.g. sleep(), or other stuff.

Behind the Scenes

In the main Form's Load event, we read a text file called "en-EN.dic", which is a dictionary with more than 50,000 entries. It is to be stored it in the component's AutoCompleteList property, which is a List<string>.

While the AutoCompleteList is used as "database" and remains unchanged, the CurrentAutoCompleteList property contains a subset of appropriate candidates to be shown as suggestions in a ListBox beneath.

The main work is done in a method called ShowSuggests() which calls a time critical method named UpdateCurrentAutoCompleteList() that calls the second time critical method UpdateListBoxItems(). I mention this because the internal list of elements to be shown and the list finally added to the image box are both time consuming operations that may cause laggy responses. So why are we using two lists for our data? Well, this is not the last word spoken, but I found DataSource/ DataContext to be faster than adding single items to the listbox in the substring query (see if ((Str.IndexOf(this.Text) > -1)) ).

Using the Code

The component is used like a normal TextBox, except that it has some "special" properties that can be set (CaseSensitive, MinTypedCharacters and the AutoCompleteList). A sample of the usage can be found in the Form's Load event. In brief: Drop it into a Form and assign a List<string> of phrases to the AutoCompleteList property.

Some Things to be Mentioned

I have done some performance measuring and alternative implementations, so you may switch between an ArrayList or a List<string> basis. I have chosen the second one because it is a generic type. However I found the ArrayList to perform a little better on large data (dictionary at about 10MB size). Maybe you would like to take this further, see the comments.

You will find two digressions, named excursions (bad English), like this in the source:

#region Digression: Performance measuring of Linq queries
// This is a simple example of speedmeasurement for Linq queries
/*
CurrentAutoCompleteList.Clear();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// using Linq query seems to be slower (twice as slow)
var query =
    from expression in this.AutoCompleteList
    where expression.ToLower().Contains(this.Text.ToLower())
    select expression;
foreach (string searchTerm in query)
{
    CurrentAutoCompleteList.Add(searchTerm);
}
stopWatch.Stop();
// method (see below) for printing the performance values to console
PrintStopwatch(stopWatch, "Linq - Contains");
*/
#endregion Digression: Performance measuring of Linq queries

The code within these regions is uncommented and meant for comparison of alternative implementations in the case shown above, to measure the performance of an alternative Linq query.

The other digression is about switching to a method using AddRange to fill the list of suggestions. In the example code, the default method used is a manual update of the BindingContext. If you experience problems with that, just feel free to choose the other approach.

Here is how the manual updating of the BindingContext of the ListBox works:

// bind the data in the constructor
listBox.DataSource = CurrentAutoCompleteList;

// later on, use the CurrencyManager to update the BindingContext manually
((CurrencyManager)listBox.BindingContext[CurrentAutoCompleteList]).Refresh();
// note that Panel and ListBox have to be added to the ParentForm for this to work!!!

The rest is just about correct timing and knowing when to show components and how to handle key and mouse events for two components in one. So we take care of KeyDown for PageUp and PageDown keys, MouseClick and MouseDoubleClick events. And we ensure the component to fit into the ParentForm, avoid flickering and overlapping and so on.

Happy coding!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionBug Pin
krahmanali23-Dec-15 6:58
memberkrahmanali23-Dec-15 6:58 
Question"Improvment" on class Pin
Member 120998942-Nov-15 1:38
memberMember 120998942-Nov-15 1:38 
QuestionDatagridview textbox column Pin
Member 84196013-Mar-15 1:28
memberMember 84196013-Mar-15 1:28 
GeneralMy vote of 5 Pin
Member 1146617619-Feb-15 22:30
memberMember 1146617619-Feb-15 22:30 
QuestionWhat is the Point of this If Block? Pin
SkiGeek8216-Dec-14 14:22
memberSkiGeek8216-Dec-14 14:22 
AnswerRe: What is the Point of this If Block? Pin
HansHammel18-Dec-14 23:45
memberHansHammel18-Dec-14 23:45 
GeneralMy vote of 1 Pin
Agent_Spock2-Oct-14 0:19
professionalAgent_Spock2-Oct-14 0:19 
GeneralRe: My vote of 1 Pin
HansHammel3-Oct-14 5:26
memberHansHammel3-Oct-14 5:26 
GeneralRe: My vote of 1 Pin
Agent_Spock21-Oct-14 4:14
professionalAgent_Spock21-Oct-14 4:14 
GeneralRe: My vote of 1 Pin
HansHammel27-Nov-14 13:20
memberHansHammel27-Nov-14 13:20 
GeneralRe: My vote of 1 Pin
Eddy Vluggen12-Jun-15 0:25
professionalEddy Vluggen12-Jun-15 0:25 
QuestionBug when AutoCompleteTextBox are inside tabcontrol Pin
Member 108523911-Aug-14 12:13
memberMember 108523911-Aug-14 12:13 
AnswerRe: Bug when AutoCompleteTextBox are inside tabcontrol Pin
HansHammel4-Aug-14 9:05
memberHansHammel4-Aug-14 9:05 
GeneralRe: Bug when AutoCompleteTextBox are inside tabcontrol Pin
Member 108523915-Aug-14 4:38
memberMember 108523915-Aug-14 4:38 
GeneralRe: Bug when AutoCompleteTextBox are inside tabcontrol Pin
HansHammel6-Aug-14 1:13
memberHansHammel6-Aug-14 1:13 
Questionthis works !!!! Pin
syahirul faiz4-Mar-14 23:42
membersyahirul faiz4-Mar-14 23:42 
GeneralMy vote of 5 Pin
Brian A Stephens8-Jan-14 2:17
professionalBrian A Stephens8-Jan-14 2:17 
QuestionUnicode Problem Pin
AxeScript6-Nov-13 7:41
memberAxeScript6-Nov-13 7:41 
GeneralMy vote of 5 Pin
Pablo Aliskevicius22-Aug-13 2:01
memberPablo Aliskevicius22-Aug-13 2:01 
SuggestionAbout Linq performances Pin
Captain Stifu17-Jul-13 3:45
memberCaptain Stifu17-Jul-13 3:45 
GeneralRe: About Linq performances Pin
ricoohh9-Jan-14 3:32
memberricoohh9-Jan-14 3:32 
GeneralRe: About Linq performances Pin
HansHammel4-Aug-14 9:20
memberHansHammel4-Aug-14 9:20 
GeneralMy vote of 5 Pin
MD. Mohiuddin Ahmed8-Apr-13 10:01
memberMD. Mohiuddin Ahmed8-Apr-13 10:01 
QuestionSeems to work well enough Pin
neminem14-Sep-12 8:56
memberneminem14-Sep-12 8:56 
GeneralMy vote of 1 Pin
heurcito2-Apr-12 20:54
memberheurcito2-Apr-12 20:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160730.1 | Last Updated 13 Sep 2011
Article Copyright 2011 by Oliver Bleckmann
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid