AutoComplete 菜单控件 for .NET
自动完成菜单
[乌克兰]Pavel Torgashov
自定义用于
codeproject.com
简介
我们所有人都用过
AutocompleteMenu
实现
该组件包含了数个类
AutocompleteMenu - 包含基本功能的主要组件
下面是
- AllowTabKey - 允许使用
- AppearInterval - 菜单显示的间隔
毫秒( ) - ImageList - 保存菜单项用到的图片
- Items - 菜单项列表
AutocompleteMenu( ) - MaximumSize - 弹出菜单最大尺寸
- MinFragmentLength - 菜单显示的最小片段长度
只有当光标处当前片段长度不低于。 。 - SearchPattern - 搜索光标处片段的正则表达式
AutocompleteMenuHost - 从
AutocompleteListView - 从
AutocompleteItem - 菜单项
- Text - 要插入文本框的文本
- MenuText - 显示在弹出菜单上的文本
- ImageIndex - 菜单项的图片索引
- ToolTipTitle - 工具提示标题
如果。 则不会显示工具提示, - ToolTipText - 工具提示文本
- Tag - 你可在此附加任何数据
下面是一些你可以重写的方法
- GetTextForReplace - 返回要插入的文本
你可以动态修改要插入的文本。 例如。 你可以插入当前日期, 。 - Compare - 这个方法定义了菜单项显示与否
默认情况下。 只有菜单项以给定的片段开头, 才会显示该项, 但是你可以重写这个方法的行为。 比如。 你可以用子字符串来比较, 或是进行一些模糊比较, 。 - OnSelected - 这个方法会在文本插入文本框的时候调用
你可以在这里对文本进行一些额外的操作。 比如。 你可以把光标移动到某处, 。
控件库里还提供了几个从
使用源代码
简单用法
1) 把
2) 在
就像这样
3) 设置你的文本框的
就像这样
4) 搞定收工
高级用法
1) 把
2) 创建一个菜单项列表
1 2 3 4 5 6 7 8 9 10 11 12 | string [] snippets = { "if(^)\n{\n}" , "if(^)\n{\n}\nelse\n{\n}" , "for(^;;)\n{\n}" , "while(^)\n{\n}" , "do${\n^}while();" , "switch(^)\n{\n\tcase : break;\n}" }; private void BuildAutocompleteMenu() { var items = new List<AutocompleteItem>(); foreach ( var item in snippets) items.Add( new SnippetAutocompleteItem(item) { ImageIndex = 1 }); //设置为自动完成源 autocompleteMenu1.SetAutocompleteItems(items); } |
同样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | internal class EmailSnippet : AutocompleteItem { public EmailSnippet( string email): base (email) { ImageIndex = 0; ToolTipTitle = "Insert email:" ; ToolTipText = email; } public override CompareResult Compare( string fragmentText) { if (fragmentText == Text) return CompareResult.VisibleAndSelected; if (fragmentText.Contains( "@" )) return CompareResult.Visible; return CompareResult.Hidden; } } |
更多详细内容请参考
快捷键
你可以使用以下的快捷键
- Ctrl+Space - 强制打开
- 上
下、 上翻页、 下翻页 - 在菜单中来回移动、 - 回车
Tab、 鼠标双击 - 插入选中的文本、 Tab( ) - Esc - 关闭菜单
注意
当你点选了菜单项
自定义
你可以用自定义控件来显示
动态上下文菜单
如果你要显示的菜单并非固定内容
请注意菜单的
所以
下面的代码演示了这个思路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | autocompleteMenu1.SetAutocompleteItems( new DynamicCollection(tb)); .... internal class DynamicCollection : IEnumerable<AutocompleteItem> { public IEnumerator<AutocompleteItem> GetEnumerator() { return BuildList().GetEnumerator(); } private IEnumerable<AutocompleteItem> BuildList() { //找到文本中所有单词 var words = new Dictionary< string , string >(); foreach (Match m in Regex.Matches(tb.Text, @"\b\w+\b" )) words[m.Value] = m.Value; //返回自动完成项 foreach ( var word in words.Keys) yield return new AutocompleteItem(word); } } |
完整的实现代码请参考
兼容性
自动完成菜单可以兼容
同样
- string SelectedText{get;set;}
- int SelectionLength{get;set;}
- int SelectionStart{get;set;}
- Point GetPositionFromCharIndex(int charPos)
即使你的控件不支持这些方法
下面是
1 2 3 4 5 6 7 8 9 10 11 12 13 | public interface ITextBoxWrapper { Control TargetControl { get ; } string Text { get ; } string SelectedText { get ; set ; } int SelectionLength { get ; set ; } int SelectionStart { get ; set ; } Point GetPositionFromCharIndex( int pos); event EventHandler LostFocus; event ScrollEventHandler Scroll; event KeyEventHandler KeyDown; event MouseEventHandler MouseDown; } |
做好了包装器之后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public partial class Form1 : Form { public Form1() { InitializeComponent(); //把<h-hws hidden=""> </h-hws>myControl1<h-hws hidden=""> </h-hws>附加到<h-hws hidden=""> </h-hws>autocompleteMenu1 autocompleteMenu1.TargetControlWrapper = new MyControlWrapper(myControl1); } } internal class MyControlWrapper : ITextBoxWrapper { private MyControl tb; public MyControlWrapper(MyControl tb) { this .tb = tb; } //在这里实现<h-hws hidden=""> </h-hws>ITextBoxWrapper //(略) } |
示例
Demo
SimplestSample - 展示最简单的使用控件方法
CustomItemSample - 展示了怎样创建从
AdvancedSample - 展示了怎样创建自定义的带关键字
ExtraLargeSample - 演示了在极大量
ComboboxSample - 展示了怎样创建模拟
MulticolumnSample - 展示了怎样制作多列自动完成菜单
CustomListViewSample - 展示了怎样在自动完成菜单中制作自定义
DynamicMenuSample - 这个例子展示了怎样创建动态的上下文敏感的自动完成菜单
DataGridViewSample - 展示了怎样把
历史
2012
2012
2012
许可
本文及相关源代码和文件
© Written by Pavel Torgashov 2012, translated by Conmajia 2012
if(jQuery('#no-reward').text() == 'true') jQuery('.bottom-reward').addClass('hidden');
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构