C# winforms combobox dynamic autocomplete
Here is my final solution. It works fine with a large amount of data. I use Timer
to make sure the user want find current value. It looks like complex but it doesn't.
Thanks to Max Lambertini for the idea.
private bool _canUpdate = true;
private bool _needUpdate = false;
//If text has been changed then start timer
//If the user doesn't change text while the timer runs then start search
private void combobox1_TextChanged(object sender, EventArgs e)
{
if (_needUpdate)
{
if (_canUpdate)
{
_canUpdate = false;
UpdateData();
}
else
{
RestartTimer();
}
}
}
private void UpdateData()
{
if (combobox1.Text.Length > 1)
{
List<string> searchData = Search.GetData(combobox1.Text);
HandleTextChanged(searchData);
}
}
//If an item was selected don't start new search
private void combobox1_SelectedIndexChanged(object sender, EventArgs e)
{
_needUpdate = false;
}
//Update data only when the user (not program) change something
private void combobox1_TextUpdate(object sender, EventArgs e)
{
_needUpdate = true;
}
//While timer is running don't start search
//timer1.Interval = 1500;
private void RestartTimer()
{
timer1.Stop();
_canUpdate = false;
timer1.Start();
}
//Update data when timer stops
private void timer1_Tick(object sender, EventArgs e)
{
_canUpdate = true;
timer1.Stop();
UpdateData();
}
//Update combobox with new data
private void HandleTextChanged(List<string> dataSource)
{
var text = combobox1.Text;
if (dataSource.Count() > 0)
{
combobox1.DataSource = dataSource;
var sText = combobox1.Items[0].ToString();
combobox1.SelectionStart = text.Length;
combobox1.SelectionLength = sText.Length - text.Length;
combobox1.DroppedDown = true;
return;
}
else
{
combobox1.DroppedDown = false;
combobox1.SelectionStart = text.Length;
}
}
This solution isn't very cool. So if someone has another solution please share it with me.
AutoComplete ComboBox C#
On your form, you need to set two properties for your ComboBox:
AutoCompleteMode should be Suggest, Append, or SuggestAppend. I recommend SuggestAppend.
AutoCompleteSource should be ListItems.
C# WinForms ComboBox: AutoComplete does not sort descending
Example using a ToolStripDropDown
:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
String[] data = "012-0020-00,010-0070-00,010-0069-00,010-0068-00,008-1018-00".Split(',');
ComboBox combo = new ComboBox();
//ToolStripDropDownMenu menu = new ToolStripDropDownMenu(); // has image/icon border
ToolStripDropDown menu = new ToolStripDropDown(); // plain menu, no image/icon border
menu.AutoClose = false;
bool isAdjusting = false;
combo.LostFocus += delegate {
if (!isAdjusting)
menu.Close();
};
menu.ItemClicked += (o, e) => {
isAdjusting = true;
combo.Text = e.ClickedItem.Text;
menu.Close();
isAdjusting = false;
};
combo.TextChanged += delegate {
if (isAdjusting)
return;
isAdjusting = true;
String prefix = combo.Text;
menu.SuspendLayout();
for (int i = menu.Items.Count - 1; i >= 0; i--) {
var item = menu.Items[i];
menu.Items.RemoveAt(i);
item.Dispose();
}
foreach (String part in data) {
if (part.StartsWith(prefix))
menu.Items.Add(new ToolStripMenuItem(part));
}
menu.ResumeLayout();
menu.Show(combo, 0, combo.Height);
combo.Focus();
combo.SelectionStart = prefix.Length;
isAdjusting = false;
};
Form f7 = new Form();
f7.Controls.Add(combo);
Application.Run(f7);
Auto Complete feature in C# win forms dynamic
You can config a TextBox
to use a custom source for auto complete:
- Set
AutoCompleteMode
property of aTextBox
toSuggest
,Append
orSuggestAppend
- Set
AutoCompleteSource
property toCustomSource
. - Assign a custom source to
AutoCompleteCustomSource
property ofTextBox
.
Example
In the below example, I set list of month names as auto complete source. You can use any string[]
as auto complete custom source.
textBox1.AutoCompleteMode = AutoCompleteMode.Suggest;
textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
var source = new AutoCompleteStringCollection();
source.AddRange(System.Globalization.CultureInfo
.InvariantCulture.DateTimeFormat.MonthNames);
textBox1.AutoCompleteCustomSource = source;
Why does autocomplete in my Winforms ComboBox change the cursor location when typing?
As another hack you can play with ComboBox's SelectionStart
property:
int i = comboBox1.SelectionStart;
comboBox1.DataSource = new System.Collections.Generic.List<string>(){"aaaaaa", "bbbbbb", "ccccccc"};
comboBox1.SelectionStart = i;
This code changes the DataSource and retain the cursor position. If you want cursor to be always at end - set SelectionStart
to comboBox1.Text.Length
.
UPD: To fight against the "first item selection" you may use another hack:
private bool cbLock = false;
private void comboBox1_TextChanged(object sender, EventArgs e)
{
// lock is required, as this event also will occur when changing the selected index
if (cbLock)
return;
cbLock = true;
int i = comboBox1.SelectionStart;
// store the typed string before changing DS
string text = comboBox1.Text.Substring(0, i);
List<string> ds = new System.Collections.Generic.List<string>() { "aaaaaa", "aaabbb", "aaacccc" };
comboBox1.DataSource = ds;
// select first match manually
for (int index = 0; index < ds.Count; index++)
{
string s = ds[index];
if (s.StartsWith(text))
{
comboBox1.SelectedIndex = index;
break;
}
}
// restore cursor position and free the lock
comboBox1.SelectionStart = i;
cbLock = false;
}
When typing "aaab" it selects the "aaabbb" string.
Problem with ComboBox autocomplete when adding values dynamically
It seems you may have to use Win32 API (using PInvoke) here by sending appropriate message to the Combo box to show the search result "after" the event handling is done
Please refer to the below URL and you may find the what you are looking for:
http://msdn.microsoft.com/en-us/library/bb775792(VS.85).aspx
Related Topics
What Is the Equivalent of the Java Bigdecimal Class in C#
Automatically Set Appsettings.JSON for Dev and Release Environments in ASP.NET Core
No Overflow Exception for Int in C#
C# "Parameter Is Not Valid." Creating New Bitmap
Does C# Optimize the Concatenation of String Literals
Authorize by Group in Azure Active Directory B2C
How to Directly Execute SQL Query in C#
How to Read an Entire File to a String Using C#
Replace Multiple Characters in a C# String
Close a Messagebox After Several Seconds
Get All Inherited Classes of an Abstract Class
Difference Between "\N" and Environment.Newline
Metadata File '.Dll' Could Not Be Found
When Should I Use Async Controllers in ASP.NET MVC
How to Check for a Network Connection
Benchmarking Small Code Samples in C#, Can This Implementation Be Improved