C# Winforms Combobox Dynamic Autocomplete

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 a TextBox to Suggest, Append or SuggestAppend
  • Set AutoCompleteSource property to CustomSource.
  • Assign a custom source to AutoCompleteCustomSource property of TextBox.

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



Leave a reply



Submit