I am seeking a WinForm control that would provide an autocomplete behavior for multiple space-separated - exactly ala del.icio.us (or stackoverflow.com for that matter).
Does anyone knows how to do that within a .NET 2.0 WinForm application?
-
ComboBox can autocomplete, but only one word at a time.
If you want to have each word separately autocompleted, you have to write your own.
I already did, hope it's not too long. It's not 100% exactly what you want, this was used for autocompleting in email client when typing in email adress.
/// <summary> /// Extended TextBox with smart auto-completion /// </summary> public class TextBoxAC: TextBox { private List<string> completions = new List<string>(); private List<string> completionsLow = new List<string>(); private bool autocompleting = false; private bool acDisabled = true; private List<string> possibleCompletions = new List<string>(); private int currentCompletion = 0; /// <summary> /// Default constructor /// </summary> public TextBoxAC() { this.TextChanged += new EventHandler(TextBoxAC_TextChanged); this.KeyPress += new KeyPressEventHandler(TextBoxAC_KeyPress); this.KeyDown += new KeyEventHandler(TextBoxAC_KeyDown); this.TabStop = true; } /// <summary> /// Sets autocompletion data, list of possible strings /// </summary> /// <param name="words">Completion words</param> /// <param name="wordsLow">Completion words in lowerCase</param> public void SetAutoCompletion(List<string> words, List<string> wordsLow) { if (words == null || words.Count < 1) { return; } this.completions = words; this.completionsLow = wordsLow; this.TabStop = false; } private void TextBoxAC_TextChanged(object sender, EventArgs e) { if (this.autocompleting || this.acDisabled) { return; } string text = this.Text; if (text.Length != this.SelectionStart) { return; } int pos = this.SelectionStart; string userPrefix = text.Substring(0, pos); int commaPos = userPrefix.LastIndexOf(","); if (commaPos == -1) { userPrefix = userPrefix.ToLower(); this.possibleCompletions.Clear(); int n = 0; foreach (string s in this.completionsLow) { if (s.StartsWith(userPrefix)) { this.possibleCompletions.Add(this.completions[n]); } n++; } if (this.possibleCompletions.Count < 1) { return; } this.autocompleting = true; this.Text = this.possibleCompletions[0]; this.autocompleting = false; this.SelectionStart = pos; this.SelectionLength = this.Text.Length - pos; } else { string curUs = userPrefix.Substring(commaPos + 1); if (curUs.Trim().Length < 1) { return; } string trimmed; curUs = this.trimOut(curUs, out trimmed); curUs = curUs.ToLower(); string oldUs = userPrefix.Substring(0, commaPos + 1); this.possibleCompletions.Clear(); int n = 0; foreach (string s in this.completionsLow) { if (s.StartsWith(curUs)) { this.possibleCompletions.Add(this.completions[n]); } n++; } if (this.possibleCompletions.Count < 1) { return; } this.autocompleting = true; this.Text = oldUs + trimmed + this.possibleCompletions[0]; this.autocompleting = false; this.SelectionStart = pos; this.SelectionLength = this.Text.Length - pos + trimmed.Length; } this.currentCompletion = 0; } private void TextBoxAC_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) { this.acDisabled = true; } if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) { if ((this.acDisabled) || (this.possibleCompletions.Count < 1)) { return; } e.Handled = true; if (this.possibleCompletions.Count < 2) { return; } switch (e.KeyCode) { case Keys.Up: this.currentCompletion--; if (this.currentCompletion < 0) { this.currentCompletion = this.possibleCompletions.Count - 1; } break; case Keys.Down: this.currentCompletion++; if (this.currentCompletion >= this.possibleCompletions.Count) { this.currentCompletion = 0; } break; } int pos = this.SelectionStart; string userPrefix = this.Text.Substring(0, pos); int commaPos = userPrefix.LastIndexOf(","); if (commaPos == -1) { pos--; userPrefix = this.Text.Substring(0, pos); this.autocompleting = true; this.Text = userPrefix + this.possibleCompletions[this.currentCompletion].Substring(userPrefix.Length); this.autocompleting = false; this.SelectionStart = pos + 1; this.SelectionLength = this.Text.Length - pos; } else { string curUs = userPrefix.Substring(commaPos + 1); if (curUs.Trim().Length < 1) { return; } string trimmed; curUs = this.trimOut(curUs, out trimmed); curUs = curUs.ToLower(); string oldUs = userPrefix.Substring(0, commaPos + 1); this.autocompleting = true; this.Text = oldUs + trimmed + this.possibleCompletions[this.currentCompletion]; this.autocompleting = false; this.SelectionStart = pos; this.SelectionLength = this.Text.Length - pos + trimmed.Length; } } } private void TextBoxAC_KeyPress(object sender, KeyPressEventArgs e) { if (!Char.IsControl(e.KeyChar)) { this.acDisabled = false; } } private string trimOut(string toTrim, out string trim) { string ret = toTrim.TrimStart(); int pos = toTrim.IndexOf(ret); trim = toTrim.Substring(0, pos); return ret; } }
From Jakub Kotrla
0 comments:
Post a Comment