C# create autocomplete with LIKE
You have to override the following method:
dataGridView1_EditingControlShowing
Here is a further explanation: http://csharp.net-informations.com/datagridview/autogridview.htm
Making a perfect auto complete TextBox in c#
It seems that the issue comes from the database type of cust_name
.
A quick workaround is trimming the result fetched from the database
autoComplete.Add(dr.GetString(0).Trim());
Customize TextBox autocomplete
Looking at your code you have everything you need but 1 line of code. That line is:
This will only work if the start of a string is entered
//Suggestion only
textBoxName.AutoCompleteMode = AutoCompleteMode.Suggest;
//Suggest and autocomplete
textBoxName.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
This will work as a contains
method but works with a custom control
You can also make a custom textbox control that fits your needs.
Custom textbox class:
public class AutoCompleteTextBox : TextBox
{
private ListBox _listBox;
private bool _isAdded;
private String[] _values;
private String _formerValue = String.Empty;
public AutoCompleteTextBox()
{
InitializeComponent();
ResetListBox();
}
private void InitializeComponent()
{
_listBox = new ListBox();
this.KeyDown += this_KeyDown;
this.KeyUp += this_KeyUp;
}
private void ShowListBox()
{
if (!_isAdded)
{
Parent.Controls.Add(_listBox);
_listBox.Left = Left;
_listBox.Top = Top + Height;
_isAdded = true;
}
_listBox.Visible = true;
_listBox.BringToFront();
}
private void ResetListBox()
{
_listBox.Visible = false;
}
private void this_KeyUp(object sender, KeyEventArgs e)
{
UpdateListBox();
}
private void this_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Enter:
case Keys.Tab:
{
if (_listBox.Visible)
{
Text = _listBox.SelectedItem.ToString();
ResetListBox();
_formerValue = Text;
this.Select(this.Text.Length, 0);
e.Handled = true;
}
break;
}
case Keys.Down:
{
if ((_listBox.Visible) && (_listBox.SelectedIndex < _listBox.Items.Count - 1))
_listBox.SelectedIndex++;
e.Handled = true;
break;
}
case Keys.Up:
{
if ((_listBox.Visible) && (_listBox.SelectedIndex > 0))
_listBox.SelectedIndex--;
e.Handled = true;
break;
}
}
}
protected override bool IsInputKey(Keys keyData)
{
switch (keyData)
{
case Keys.Tab:
if (_listBox.Visible)
return true;
else
return false;
default:
return base.IsInputKey(keyData);
}
}
private void UpdateListBox()
{
if (Text == _formerValue)
return;
_formerValue = this.Text;
string word = this.Text;
if (_values != null && word.Length > 0)
{
string[] matches = Array.FindAll(_values,
x => (x.ToLower().Contains(word.ToLower())));
if (matches.Length > 0)
{
ShowListBox();
_listBox.BeginUpdate();
_listBox.Items.Clear();
Array.ForEach(matches, x => _listBox.Items.Add(x));
_listBox.SelectedIndex = 0;
_listBox.Height = 0;
_listBox.Width = 0;
Focus();
using (Graphics graphics = _listBox.CreateGraphics())
{
for (int i = 0; i < _listBox.Items.Count; i++)
{
if (i < 20)
_listBox.Height += _listBox.GetItemHeight(i);
// it item width is larger than the current one
// set it to the new max item width
// GetItemRectangle does not work for me
// we add a little extra space by using '_'
int itemWidth = (int)graphics.MeasureString(((string)_listBox.Items[i]) + "_", _listBox.Font).Width;
_listBox.Width = (_listBox.Width < itemWidth) ? itemWidth : this.Width; ;
}
}
_listBox.EndUpdate();
}
else
{
ResetListBox();
}
}
else
{
ResetListBox();
}
}
public String[] Values
{
get
{
return _values;
}
set
{
_values = value;
}
}
public List<String> SelectedValues
{
get
{
String[] result = Text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
return new List<String>(result);
}
}
}
Usage:
string[] nameArray = { "name1", "name2", "name3", "bla name" };
AutoCompleteTextBox tb = new AutoCompleteTextBox();
tb.Values = nameArray;
tb.Location = new Point(10,10);
tb.Size = new Size(25,75);
this.Controls.Add( tb );
I got the code for the custom control from: SO Question - Autocomplete contains
C# AutoComplete
The existing AutoComplete functionality only supports searching by prefix. There doesn't seem to be any decent way to override the behavior.
Some people have implemented their own autocomplete functions by overriding the OnTextChanged
event. That's probably your best bet.
For example, you can add a ListBox
just below the TextBox
and set its default visibility to false. Then you can use the OnTextChanged
event of the TextBox
and the SelectedIndexChanged
event of the ListBox
to display and select items.
This seems to work pretty well as a rudimentary example:
public Form1()
{
InitializeComponent();
acsc = new AutoCompleteStringCollection();
textBox1.AutoCompleteCustomSource = acsc;
textBox1.AutoCompleteMode = AutoCompleteMode.None;
textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
}
private void button1_Click(object sender, EventArgs e)
{
acsc.Add("[001] some kind of item");
acsc.Add("[002] some other item");
acsc.Add("[003] an orange");
acsc.Add("[004] i like pickles");
}
void textBox1_TextChanged(object sender, System.EventArgs e)
{
listBox1.Items.Clear();
if (textBox1.Text.Length == 0)
{
hideResults();
return;
}
foreach (String s in textBox1.AutoCompleteCustomSource)
{
if (s.Contains(textBox1.Text))
{
Console.WriteLine("Found text in: " + s);
listBox1.Items.Add(s);
listBox1.Visible = true;
}
}
}
void listBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
textBox1.Text = listBox1.Items[listBox1.SelectedIndex].ToString();
hideResults();
}
void listBox1_LostFocus(object sender, System.EventArgs e)
{
hideResults();
}
void hideResults()
{
listBox1.Visible = false;
}
There's a lot more you could do without too much effort: append text to the text box, capture additional keyboard commands, and so forth.
Unity/C# autocomplete not working in Visual Studio Code for Linux with .NET version 6.x
Something that worked for me in the end was to add
"omnisharp.path": "latest",
"omnisharp.useGlobalMono": "always"
in the settings.json file of Visual Studio Code. It still started complaining after that and it turned out that I needed to install Mono still. I did that by running
sudo apt install mono-complete
in the terminal after which I restarted omnisharp and everything worked like a charm.
MS Visual Studio 2019 C# intellisense suggestions not showing up, but autocomplete when pressing tab is working
Completely uninstalling VS 2019 along with all extensions/addons, deleting any remaining files, then reinstalling seems to have solved the problem for the time being..
for the record, this was my 4th attempt at a reinstall.. not sure why it worked now and not before
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);
AutoComplete on a TextBox ignoring accentuation
There's still improvements to be done, but this code implements the solution for this, it "appends" a listBox
to the textBox
, there will be issues when multiple of these exist due to naming, but this should be a good starting point/reference for someone looking for something similar.
public class ExTextBox : TextBox
{
private bool alreadyRun = false;
ListBox suggestions = new ListBox();
int maxSize = 10;
string[] source;
public string Hint
public int MaxSuggestionBoxSize
{
get { return maxSize; }
set { maxSize = value; this.Invalidate(); }
}
protected override void OnCreateControl()
{
if (alreadyRun == false) // This is only supposed to be run once, but in some situations depending on the design of the main form,
{// this might need to be somewhere that gets called multiple times, this variable makes so this code is only run once even in those situations
suggestions.Name = "suggList_" + this.Name;
suggestions.Location = new Point(this.Location.X, (this.Location.Y + this.Size.Height));
suggestions.Size = new Size(this.Size.Width, this.Size.Height);
this.Parent.Controls.Add(suggestions);
this.Parent.Controls["suggList_" + this.Name].MouseDoubleClick += suggList_MouseDoubleClick;
this.Parent.Controls["suggList_" + this.Name].Hide();
alreadyRun = true;
}
base.OnCreateControl();
}
private void suggList_MouseDoubleClick(object sender, System.EventArgs e)
{
this.Text = this.Parent.Controls["suggList_" + this.Name].Text;
}
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
if(source != null) // Makes sure this code is only executed when the suggestion box is being used, by checking the existance of the source
{
try
{
if (this.Parent.Controls["suggList_" + this.Name].Focused == false)
{
this.Parent.Controls["suggList_" + this.Name].Hide();
}
}
catch
{
}
}
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
AutoCompleteSmart();
}
public void AutoCompleteSmart()
{
if (source != null)
{
suggestions.Items.Clear();
if (this.Text != "")
{
foreach (string a in source)
{
if (RemoveDiacritics(a.ToLower()).Contains(RemoveDiacritics(this.Text.ToLower())))
{
suggestions.Items.Add(a);
}
}
this.Parent.Controls.Remove(suggestions);
if (suggestions.Items.Count < maxSize) // Optional code, defines a limit size for the suggestion box
{
suggestions.Size = new Size(this.Size.Width, ((suggestions.ItemHeight * suggestions.Items.Count) + suggestions.ItemHeight));
}
else
{
suggestions.Size = new Size(this.Size.Width, ((suggestions.ItemHeight * maxSize) + suggestions.ItemHeight));
}
this.Parent.Controls.Add(suggestions);
this.Parent.Controls["suggList_" + this.Name].BringToFront();
this.Parent.Controls["suggList_" + this.Name].Show();
}
else
{
this.Parent.Controls["suggList_" + this.Name].Hide();
}
}
}
public void AutoCompleteSmartSource(string[] _source)
{
source = _source;
}
private static string RemoveDiacritics(string text)
{
var normalizedString = text.Normalize(NormalizationForm.FormD);
var stringBuilder = new StringBuilder();
foreach (var c in normalizedString)
{
var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
if (unicodeCategory != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}
}
Related Topics
How to Close a Streamwriter Without Closing Its Basestream
Dependency Injection in Attributes
How to Show the "Paste JSON Class" in Visual Studio 2012 When Clicking on Paste Special
In Unity (C#), Why am I Getting a Nullreferenceexception and How to Fix It
Method Cannot Be Translated into a Store Expression
How to Pass Values (Parameters) Between Xaml Pages
Finding the Default Application for Opening a Particular File Type on Windows
Getting the Http Referrer in ASP.NET
How to Rotate a Picture in Winforms
How to Seed a Random Class to Avoid Getting Duplicate Random Values
Win32 API Function to Programmatically Enable/Disable Device
Cannot Use Ref or Out Parameter in Lambda Expressions
How to Store User Settings for a .Net Application