Introduction
I had the need to create a combo box control that auto completes as the user types into it. I scoured the fantastic resources available at Code Project, and found a great example in MFC, by Chris Maunder.
My requirements were that I wanted to use completely managed code for my project, and, as Chris's control was written with MFC, I decided to roll my own, based on his. I have added an additional property to this control, which limits the control to the list of items.
All the magic of the control happens in the OnTextChanged
event. The _inEditMode
field is set in the OnKeyDown
event, based on whether or not the backspace or delete key was pressed. If this field is true
, then the code finds the partial string, selecting the portion that the user has already typed.
OnValidating
is overridden to fire a NotInList
event in the case that the LimitToList
property is true, allowing the user to perform some action if the user enters some text that is not in the list of item.
OnNotInList
is also provided as a protected
virtual
method so that derived classes may call the event handler without subscribing to receive its events.
The source code
using System;
using System.Windows.Forms;
using System.ComponentModel;
namespace MattBerther.Controls
{
public class AutoCompleteComboBox : System.Windows.Forms.ComboBox
{
public event System.ComponentModel.CancelEventHandler NotInList;
private bool _limitToList = true;
private bool _inEditMode = false;
public AutoCompleteComboBox() : base()
{
}
[Category("Behavior")]
public bool LimitToList
{
get { return _limitToList; }
set { _limitToList = value; }
}
protected virtual void
OnNotInList (System.ComponentModel.CancelEventArgs e)
{
if (NotInList != null)
{
NotInList(this, e);
}
}
protected override void OnTextChanged(System.EventArgs e)
{
if (_inEditMode)
{
string input = Text;
int index = FindString(input);
if (index >= 0)
{
_inEditMode = false;
SelectedIndex = index;
_inEditMode = true;
Select(input.Length, Text.Length);
}
}
base.OnTextChanged(e);
}
protected override void
OnValidating(System.ComponentModel.CancelEventArgs e)
{
if (this.LimitToList)
{
int pos = this.FindStringExact(this.Text);
if (pos == -1)
{
OnNotInList(e);
}
else
{
this.SelectedIndex = pos;
}
}
base.OnValidating(e);
}
protected override void
OnKeyDown(System.Windows.Forms.KeyEventArgs e)
{
_inEditMode =
(e.KeyCode != Keys.Back && e.KeyCode != Keys.Delete);
base.OnKeyDown(e);
}
}
}
Using this control
Use this control in the same manner as you would a regular System.Windows.Forms.ComboBox
. Add it to your form, via the designer or programmatically as detailed below.
protected override void OnLoad(System.EventArgs e)
{
base.OnLoad(e);
MattBerther.Controls.AutoCompleteComboBox cb = new
MattBerther.Controls.AutoCompleteComboBox();
cb.Items.Add("Apples");
cb.Items.Add("Oranges");
cb.Items.Add("Grapefruits");
cb.LimitToList = true;
cb.NotInList += new CancelEventHandler(combobox_NotInList);
this.Controls.Add(cb);
}
private void combobox_NotInList(object sender, CancelEventArgs e)
{
MessageBox.Show("You entered a value that was not
consistent with the list provided. Please try again.");
e.Cancel = true;
}
Many thanks again to Chris Maunder for providing an excellent starting point for implementing my own auto complete combo box in completely managed code.
History
- 1.0 - 04.15.2003 - First release version