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.
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.
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:
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
.
public class StringMatch
{
public string Text { get; private set; }
internal List<string> Segments { get; private set; }
internal bool StartsOnMatch { get; private set; }
}
As the search is done, the string
s are split into segments. These segments are used when rendering the string
s in the listbox
for alternating bold and non-bold portions.
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