C# Autocomplete

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



Leave a reply



Submit