| Printable Version
ComboBox with AutoComplete 1.1
By James Williams
I wrote the original ComboBox with AutoComplete about a year ago for
a project I was working on at the time. Well, I updated it a few times
after I posted it here. I have received several e-mails from programmers
telling me that the original code had some serious problems, especially
when the ACComboBox was databound, and asking for a solution.
Well, I decided to re-write the control to make it function properly.
Please note the following:
- The AutoComplete feature is sequential, i.e., if "James"
comes before "Jack" in your list, then the AutoComplete will select
"James" when you type "J". If you select the control's Sorted
attribute as True, then "Jack" will be selected.
Basically, it finds the first match in the list and selects it.
- The AutoComplete feature is not case-sensitive. It uses
the ComboBox's FindString method which is not case-sensitive.
I think most would prefer it this way anyhow.
I have zipped up the Visual Studio solution files. Also, the final
compiled DLL is within the the Release folder.
The main code is below.
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace DigitalCult
{
/// <summary>
/// Summary description for ACComboBox.
/// </summary>
public class ACComboBox : System.Windows.Forms.ComboBox
{
private bool autoComplete;
[DefaultValue(true),
Description("Auto-completes text if a match is found in the items collection."),
Category("Behavior")]
public bool AutoComplete
{
get { return autoComplete; }
set { autoComplete = value; }
}
/// <summary>
/// Required designer variable.
/// </summary>
private Container components = null;
/// <summary>
/// Default constructor.
/// </summary>
public ACComboBox()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
// Add any initialization after the InitComponent call
this.autoComplete = true;
this.KeyPress += new KeyPressEventHandler( this.OnKeyPress );
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}
private void OnKeyPress( object sender, KeyPressEventArgs e )
{
if ( autoComplete )
{
ACComboBox acComboBox = (ACComboBox)sender;
if ( !e.KeyChar.Equals( (char)8 ) )
{
SearchItems( acComboBox, ref e );
}
else
e.Handled = false;
}
else
e.Handled = false;
}
/// <summary>
/// Searches the combo box item list for a match and selects it.
/// If no match is found, then selected index defaults to -1.
/// </summary>
///
///
private void SearchItems( ACComboBox acComboBox, ref KeyPressEventArgs e )
{
int selectionStart = acComboBox.SelectionStart;
int selectionLength = acComboBox.SelectionLength;
int selectionEnd = selectionStart + selectionLength;
int index;
StringBuilder sb = new StringBuilder();
sb.Append( acComboBox.Text.Substring( 0, selectionStart ) )
.Append( e.KeyChar.ToString() )
.Append( acComboBox.Text.Substring( selectionEnd ) );
index = acComboBox.FindString( sb.ToString() );
if ( index == -1 )
e.Handled = false;
else
{
acComboBox.SelectedIndex = index;
acComboBox.Select( selectionStart+1, acComboBox.Text.Length-(selectionStart+1) );
e.Handled = true;
}
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}
Download Source
|