Click here to Skip to main content
15,881,882 members
Articles / Desktop Programming / Windows Forms
Tip/Trick

ComboBox with Suggestions Based on Loose Character Search

Rate me:
Please Sign up or sign in to vote.
4.78/5 (34 votes)
26 May 2014LGPL34 min read 150.3K   4.3K   42   61
A ComboBox whose suggestion list is based on loose character search

Introduction

I wanted to have a ComboBox with completion as powerful as the ones found in SublimeText or in Resharper.

As with the standard AutoComplete feature, the suggestion list is based on the items of the combo. But instead of displaying the items in which text begins with the search string, it displays the items in which text contains all the characters of the search string but not consecutively.

The list is updated as the search text changes and in each suggestion, the matched characters are displayed in bold.

Image 1

For example, in the screenshot above, "johns" is matched against:

  • Eyvind Johnson
  • Johannes Vilhelm Jensen
  • John Galsworthy
  • John Steinbeck
  • ...

Another available way of matching combo items against user input, is to match all the characters of the input string consecutively and to allow the wildcard '*'. This wildcard matches any sequence of characters.

Image 2

For example, in the screenshot above, "john*s" is matched against:

  • Eyvind Johnson
  • John Galsworthy
  • John Steinbeck
  • Saint-John Perse

A third available matching method simply use native .NET Regexs:

Image 3

For example, in the screenshot above, "john[^a]*s" is matched against:

  • Eyvind Johnson
  • John Steinbeck
  • Saint-John Perse

Background

I've borrowed a lot of code from the following two CodeProject articles:

Using the Code

This ComboBox can be used as any standard WinForm ComboBox. Just build the DLL and in the form designer, drag the combo from the Toolbox to your form.

The algorithm used for matching ComboBox items is set with the property MatchingMethod. It can take the values:

  • StringMatchingMethod.NoWildcards
  • StringMatchingMethod.UseWildcards
  • StringMatchingMethod.UseRegexs

The following properties should not be set:

  • DropDownStyle
  • AutoCompleteSource, AutoCompleteMode, ...

The maximum height of the dropdown is based on the property ItemHeight . Its width is based on the property DropDownWidth. Unless overridden, DropDownWidth is set to the width of the combo.

I recommend to use another font than the standard "Microsoft Sans Serif". There is no bold version of "Microsoft Sans Serif" and so the rendering of bold characters is quite poor. "Segoe UI" is a very good substitute.

Points of Interest

The EasyCompletionComboBox is a control derived from the standard ComboBox. Every time, the user modifies the contents of the edit control of the combobox, a custom dropdown is shown or updated.

The custom dropdown is derived from ToolStripDropDown and contains a standard ListBox.

The combo text is matched against all the items of the combo and a list of StringMatch is built. This list is used as the items of the dropdown's listbox.

C#
public class StringMatch
{
    /// <summary>
    /// The original source
    /// </summary>
    public string Text { get; private set; }
    /// <summary>
    /// The source decomposed on matches/non matches against the pattern
    /// </summary>
    internal List<string> Segments { get; private set; }
    /// <summary>
    /// Is the first segment a match?
    /// </summary>
    internal bool StartsOnMatch { get; private set; }
} 

As the search is done, the strings are split into segments. These segments are used when rendering the strings in the listbox for alternating bold and non-bold portions.

C#
private void onSuggestionListDrawItem(object sender, DrawItemEventArgs e)
{
    StringMatch sm = (StringMatch) m_suggestionList.Items[e.Index];
    e.DrawBackground();
    
    bool isBold = sm.StartsOnMatch;
    Rectangle rBounds = e.Bounds;
    foreach (string s in sm.Segments)
    {
        Font f = isBold ? m_boldFont : Font;
        DrawString(e.Graphics, e.ForeColor, ref rBounds, s, f);
        isBold = !isBold;
    }
    e.DrawFocusRectangle();
} 

The keyboard focus is set to the combo and not to the dropdown. So special keys like arrows or escape are translated into commands for the dropdown.

The automatic closing of the dropdown is a little tricky. I would have expected to use the AutoClose property of ToolStripDropDown, but unfortunately ToolStripManager steals the keyboard events when AutoClose is set. So an application IMessageFilter is set in order to detect when the user clicks outside the control and then the dropdown is closed.

History

  • 07 April 2014: First release
  • 09 April 2014: Version 1.0.1
    • Bug fix: When the "standard" dropdown was visible and the user has entered text in the edit box of the combo, this text was incorrectly replaced by something else
    • Bug fix: Incorrect test for the visibility of the dropdown
  • 13 April 2014: Version 1.0.2
    • Bug fix: Now the completion dropdown is only shown when the user enters text in the edit control of the combobox
  • 19 April 2014: Version 1.1.1
    • Bug fix: The tab key is now correctly handled
    • New feature: Added two ways of matching combo items against user input
      • Simple matching with '*' wildcards
      • Regex matching
  • 23 April 2014: Version 1.1.2
    • Bug fix: Fixed bug in the "Wildcard" string matching algorithm
  • 24 April 2014: Version 1.1.3
    • Bug Fix: Completely rewritten the "Wildcard" string matching algorithm
  • 26 May 2014: Version 1.1.4
    • Bug Fix: Better handling of when to show the completion list
  • 8 June 2014: version 1.1.5
    • Bug Fix: Uploaded incorrect version of wildcard completion in previous release
    • Bug Fix: Correct handling of clicking in non-client areas of the suggestion list box
    • Bug Fix: Ampersands are now correctly displayed
    • Bug Fix: The suggestion list box now uses the control font
    • Thanks to omzig for his bug reports and suggestions

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionUse the comboBox in Datagridview Pin
fcis201022-Jul-22 12:48
fcis201022-Jul-22 12:48 
AnswerRe: Use the comboBox in Datagridview Pin
Ka Toryo13-Oct-22 17:53
Ka Toryo13-Oct-22 17:53 
GeneralRe: Use the comboBox in Datagridview Pin
fcis201015-Oct-22 9:56
fcis201015-Oct-22 9:56 
QuestionThank you very much! Fantastic! Pin
Member 128720317-Jun-22 0:41
Member 128720317-Jun-22 0:41 
BugProblem with Unicode Language Pin
a-erfani18-Apr-21 18:48
a-erfani18-Apr-21 18:48 
GeneralRe: Problem with Unicode Language Pin
Panayotis Kouvarakis26-Sep-23 2:10
Panayotis Kouvarakis26-Sep-23 2:10 
QuestionI am new in c#. unable to use this Pin
Muhammad Tallha Waris26-Oct-20 20:54
Muhammad Tallha Waris26-Oct-20 20:54 
PraiseGreat combo box search and it is a Game changer Pin
Member 1329498010-Jul-20 2:34
Member 1329498010-Jul-20 2:34 
QuestionHow can we apply the Easy Completion ComboBox in DataGridView ComboBox Column Pin
Member 1418692430-Aug-19 22:47
Member 1418692430-Aug-19 22:47 
QuestionOverlapping issue Pin
Member 1365177414-Feb-18 1:09
Member 1365177414-Feb-18 1:09 
QuestionHow to Use above customized combobox in datagridview control? Pin
hareshpatel199018-Sep-17 4:29
hareshpatel199018-Sep-17 4:29 
GeneralMy vote of 5 Pin
Simpson@@73-Jan-16 20:03
Simpson@@73-Jan-16 20:03 
Questionhow add to Data Grid view Pin
Althaf Alfazin21-Jul-15 9:07
Althaf Alfazin21-Jul-15 9:07 
Questionhow could using for Arabic (Right to left) language? Pin
hongylover23-May-15 11:29
hongylover23-May-15 11:29 
Questionhow to use it? Pin
Member 115154803-Apr-15 2:46
Member 115154803-Apr-15 2:46 
SuggestionVariation of buildNoWildcard that "prefers" longer runs of text Pin
BrianARice8-Mar-15 4:40
BrianARice8-Mar-15 4:40 
BugRe: Variation of buildNoWildcard that "prefers" longer runs of text Pin
JayantaChatterjee27-Jun-15 5:41
professionalJayantaChatterjee27-Jun-15 5:41 
Questionfor Mr.Serge Weinstock please replay to me or any one can help me Pin
ahamedgad20-Nov-14 13:54
ahamedgad20-Nov-14 13:54 
GeneralMy vote of 5 Pin
k0m0k17-Nov-14 2:41
k0m0k17-Nov-14 2:41 
QuestionEvent SelectedIndexChanged Pin
Peixoto1-Oct-14 13:42
Peixoto1-Oct-14 13:42 
AnswerRe: Event SelectedIndexChanged Pin
Serge Weinstock4-Oct-14 21:59
Serge Weinstock4-Oct-14 21:59 
SuggestionAdded another string comparing method Pin
Dasiths30-Jul-14 17:47
Dasiths30-Jul-14 17:47 
GeneralRe: Added another string comparing method Pin
Serge Weinstock31-Jul-14 8:30
Serge Weinstock31-Jul-14 8:30 
QuestionHow do I host this in a menu item? Pin
Dasiths29-Jul-14 15:57
Dasiths29-Jul-14 15:57 
AnswerRe: How do I host this in a menu item? Pin
Serge Weinstock31-Jul-14 8:34
Serge Weinstock31-Jul-14 8:34 

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.