C# WinForms带分隔符的TextBox邮箱自动补全异常求助
我太懂这个坑了!默认的TextBox自动补全是盯着整个输入框的文本做匹配的,当你输入分号后的第二个邮箱时,它会把前面的所有内容(比如test1@example.com;)加上你刚敲的字符一起去匹配自定义源里的项,这肯定找不到匹配结果啊,自然就弹不出建议列表了。
下面是我常用的解决思路,亲测有效:
自定义分号分隔邮箱的自动补全逻辑
我们得绕过默认的AutoComplete机制,手动处理输入片段,自己做匹配和建议弹窗。
1. 先关掉默认的自动补全模式
首先把TextBox的默认AutoCompleteMode改成None,避免和我们的自定义逻辑打架:
this.receiverInput.AutoCompleteMode = AutoCompleteMode.None;
2. 手动处理输入事件,提取当前邮箱片段
我们可以用KeyUp或者TextChanged事件,在每次输入时,提取分号之后的那段正在输入的邮箱文本,单独去匹配你的自定义源。然后用ToolStripDropDown做一个自定义的建议下拉框。
给你一段完整的示例代码,直接改改就能用:
// 先声明一个类级别的下拉框变量,用来存建议列表 private ToolStripDropDown _emailSuggestionDropDown; private void receiverInput_KeyUp(object sender, KeyEventArgs e) { var inputBox = sender as TextBox; if (inputBox == null) return; // 拿到当前光标位置,提取分号之后的输入片段 int cursorPos = inputBox.SelectionStart; string currentTextSegment = inputBox.Text.Substring(0, cursorPos); int lastSemicolonPos = currentTextSegment.LastIndexOf(';'); string currentEmailPart = lastSemicolonPos == -1 ? currentTextSegment : currentTextSegment.Substring(lastSemicolonPos + 1).Trim(); // 如果当前没输入内容,直接隐藏建议框 if (string.IsNullOrWhiteSpace(currentEmailPart)) { _emailSuggestionDropDown?.Hide(); return; } // 从自定义源里筛选匹配的邮箱 var matchedEmails = inputBox.AutoCompleteCustomSource.Cast<string>() .Where(email => email.StartsWith(currentEmailPart, StringComparison.OrdinalIgnoreCase)) .ToList(); if (matchedEmails.Count == 0) { _emailSuggestionDropDown?.Hide(); return; } // 初始化并填充建议下拉框 if (_emailSuggestionDropDown == null) { _emailSuggestionDropDown = new ToolStripDropDown(); _emailSuggestionDropDown.ItemClicked += EmailSuggestion_ItemClicked; } _emailSuggestionDropDown.Items.Clear(); matchedEmails.ForEach(email => _emailSuggestionDropDown.Items.Add(email)); // 把下拉框定位到输入框下方的正确位置 Point dropDownPos = inputBox.PointToScreen(new Point(0, inputBox.Height)); _emailSuggestionDropDown.Show(dropDownPos); } // 处理建议项点击事件,把选中的邮箱插入到输入框里 private void EmailSuggestion_ItemClicked(object sender, ToolStripItemClickedEventArgs e) { var inputBox = receiverInput; int cursorPos = inputBox.SelectionStart; string currentTextSegment = inputBox.Text.Substring(0, cursorPos); int lastSemicolonPos = currentTextSegment.LastIndexOf(';'); // 替换当前输入的片段为选中的邮箱 string newInputText = lastSemicolonPos == -1 ? e.ClickedItem.Text : inputBox.Text.Substring(0, lastSemicolonPos + 1) + " " + e.ClickedItem.Text; inputBox.Text = newInputText; inputBox.SelectionStart = newInputText.Length; _emailSuggestionDropDown.Hide(); } // 窗体关闭时记得释放下拉框资源,避免内存泄漏 private void YourForm_FormClosing(object sender, FormClosingEventArgs e) { _emailSuggestionDropDown?.Dispose(); }
3. 几个可以优化的小细节
- 加个
LostFocus事件,当输入框失去焦点时自动隐藏建议框 - 支持按Enter或Tab键快速选中高亮的建议项
- 匹配逻辑可以改成
Contains,如果需要模糊匹配的话
这样改完之后,不管你输入多少个分号分隔的邮箱,每一段都能正常触发自动补全了。
内容的提问来源于stack exchange,提问作者ARX
相关产品推荐
相关产品推荐

