Introduction
We all use VisualStudio's autocomplete menu, aka IntelliSense. This is very useful, is not it? Unfortunately, .NET FW does not contain built-in component for autocomplete menu. The proposed control fills this gap.
AutocompleteMenu
allows you to easily embed drop-down hints into any TextBox
or RichTextBox
on your form.
Implementation
The component contains several classes. Below summarizes the main classes and their functions:
AutocompleteMenu
- main component of which contains the basic functions. It subscribes to the events of TextBox
, looks for suitable variants, shows a drop-down menu and inserts new text into textbox
.
Below are basic properties of the AutocompleteMenu
:
AllowTabKey
- Allows TAB for select menu item AppearInterval
- Interval of menu appear (ms) ImageList
- Image list used for items Items
- List of text of menu items (simplest variant of usage of AutocompleteMenu
) MaximumSize
- Maximum size of popup menu MinFragmentLength
- Minimum fragment length for menu appearing. AutocompleteMenu
appears only if current fragment around caret has no less than MinFragmentLength
symbols SearchPattern
- Regex pattern for search fragment around caret
AutocompleteMenuHost
- visual component that derived from ToolStripDropDown
. This control allows you to display the menu without losing focus on the main form.
AutocompleteListView
- visual component that inherited from UserControl
. With GDI+, it draws the items of the drop-down menu. This component is similar to ListView
but it allows you to display a large number of elements with a good performance.
AutocompleteItem
- menu item. This class contains all the necessary information about menu item. You can extend menu features, inheriting your elements from AutocompleteItem
and overriding its virtual methods. Below are basic properties of AutocompleteItem
:
Text
- text for inserting into textbox
MenuText
- this text will displayed in popup menu ImageIndex
- index of image for this item ToolTipTitle
- title for tooltip. If ToolTipTitle
is null
, tooltip will not appear for this item ToolTipText
- text of tooltip Tag
- you can store any data here
Below are some methods you can override:
GetTextForReplace
- returns inserting text. You can dynamically change inserting text. For example, you can insert current date. Compare
- this method defines whether this item will be visible in menu or not. By default, this method make visible only items beginning with a given fragment. But you can override this behaviour. For example, you can compare by substring, or make fuzzy comparison. OnSelected
- this method is called when text was inserted in textbox
. Here, you can make some additional operations with text. For example, you can move caret into some position.
The library also contains a few useful classes derived from AutocompleteItem
: SnippetAutocompleteItem
(can be used for inserting of code snippets), MethodAutocompleteItem
(can be used for inserting of method name after dot), SubstringAutocompleteItem
(compares text by substring), MulticolumnAutocompleteItem
(draws multicolumn menu).
Using the Code
Easy Usage
- Throw
AutocompleteMenu
component on your form. - Type text of the menu items in
AutocompleteMenu.Items
:
- Set the
AutocompleteMenu
property of your TextBox
:
- That's all folks!
Advanced Usage
- Throw
AutocompleteMenu
component on your form. - Create a list of items, and add to the menu, using the methods
SetAutocompleteItems()
or AddItem()
. For example:
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);
}
Also, you can add own items, inherited from AutocompleteItem
. For example:
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;
}
}
For more details, see the example AdvancedSample
of demo application.
Shortcuts
You can use the following shortcuts:
- Ctrl+Space - forcibly opens
AutocompleteMenu
- Up, Down, PgUp, PgDown - navigates across menu
- Enter, Tab, DblClick on the item - inserts selected item into text (Tab works only if
AllowTabKey
is true). - Esc - closes menu
Note that these keys are working, despite the fact that the focus is in the textbox
.
Item's tooltip appears if you click on the item.
Custom ListView
You can use the custom controls for displaying AutocompleteMenu
(like ListView
, ListBox
, DataGridView
, TreeView
, etc.). For this, create own control (derived from Control
) and implement interface
IAutocompleteListView
. For more details, see in CustomListViewSample
.
Dynamic Context Menu
It is frequently necessary that the menu display not a fixed set of items, but is changing dynamically, depending on the text. This task can be solved.
Note that method SetAutocompleteItems()
of menu takes IEnumerable
as collection of displayed items.
So, you do not generate a list of items at the start of the program, and generate it dynamically at the time of the call the enumerator from the menu.
The following code demonstrates this idea:
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);
}
}
For a fully implemented sample, see in DynamicMenuSample
.
Compatibility
Autocomplete
menu is compatible with TextBox
, RichTextBox
, MaskedTextBox
, FastColoredTextBox[^] and other controls derived from TextBoxBase
.
Also, Autocomplete
Menu is compatible with any control supports following properties and methods:
string SelectedText{get;set;}
int SelectionLength{get;set;}
int SelectionStart{get;set;}
Point GetPositionFromCharIndex(int charPos)
Even if your control does not support these methods, you can create your own wrapper for it. For this, you must create your own wrapper class and implement there interface ITextBoxWrapper
.
Below described methods and properties of ITextBoxWrapper
:
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;
}
So, when you made wrapper, you can simply attach AutocompleteMenu
to your control. Something like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
autocompleteMenu1.TargetControlWrapper = new MyControlWrapper(myControl1);
}
}
internal class MyControlWrapper : ITextBoxWrapper
{
private MyControl tb;
public MyControlWrapper(MyControl tb)
{
this.tb = tb;
}
.....
}
Samples
Demo application contains several samples:
SimplestSample
- shows how to use the control in the simplest way. CustomItemSample
- shows how to create own class derived from AutocompleteItem
. AdvancedSample
- shows how to create custom autocomplete menu with keywords, snippets, method suggestions, text correctors, etc. ExtraLargeSample
- demonstrates performance of the component with extra large list of menu items (one million). ComboboxSample
- shows how to create analog of Combobox
, but with very large dropdown list and with searching by substring. MulticolumnSample
- shows how to make multicolumn autocomplete menu:
CustomListViewSample
- shows how to make custom ListView
, hosted in autocomplete
menu:
DynamicMenuSample
- This example shows how to create dynamic context-sensitive autocomplete menu. DataGridViewSample
- shows how to attach AutocompleteMenu
to DataGridView
:
History
- 13 Apr, 2012 - First release
- 21 Apr, 2012 - The control is refactored. Added support of the
FastColoredTextBox
[^] and other controls - 9 May, 2012 - The control is refactored. Some samples were added
- 3 Dec, 2014 - Property Colors was added
- 8 Feb, 2015 - Small bugs were fixed
- 19 Mar, 2015 - Small bugs were fixed