Click here to Skip to main content
15,880,469 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.1K   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

 
GeneralRe: Wild Card Not working - Fixed Pin
Serge Weinstock7-Jun-14 23:26
Serge Weinstock7-Jun-14 23:26 
GeneralRe: Wild Card Not working - Fixed Pin
VandyLTD9-Jun-15 8:49
VandyLTD9-Jun-15 8:49 
QuestionGetting an error when trying to download the sample Pin
Jonathan Reis19-May-14 14:14
Jonathan Reis19-May-14 14:14 
AnswerRe: Getting an error when trying to download the sample Pin
Serge Weinstock26-May-14 6:39
Serge Weinstock26-May-14 6:39 
GeneralRe: Getting an error when trying to download the sample Pin
ahamedgad28-May-14 12:12
ahamedgad28-May-14 12:12 
GeneralRe: Getting an error when trying to download the sample Pin
Serge Weinstock28-May-14 17:31
Serge Weinstock28-May-14 17:31 
GeneralRe: Getting an error when trying to download the sample Pin
ahamedgad4-Jun-14 11:19
ahamedgad4-Jun-14 11:19 
Generalnice Pin
Cosmic_Spy10-Apr-14 19:06
Cosmic_Spy10-Apr-14 19:06 
Big Grin | :-D nice job~
QuestionA good attempt but... Pin
i0010-Apr-14 1:35
i0010-Apr-14 1:35 
QuestionNicely done! Pin
Ravi Bhavnani9-Apr-14 16:49
professionalRavi Bhavnani9-Apr-14 16:49 
QuestionBuild .dll ? Pin
Member 107298747-Apr-14 22:40
Member 107298747-Apr-14 22:40 
AnswerRe: Build .dll ? Pin
Serge Weinstock8-Apr-14 7:43
Serge Weinstock8-Apr-14 7:43 
QuestionCombox - Web Pin
pradeepvpanzade7-Apr-14 4:03
pradeepvpanzade7-Apr-14 4:03 
AnswerRe: Combox - Web Pin
Serge Weinstock7-Apr-14 7:45
Serge Weinstock7-Apr-14 7:45 
GeneralMy vote of 5 Pin
Polinia7-Apr-14 1:49
Polinia7-Apr-14 1:49 

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.