I like the tagging control in Evernote (windows version) and was wondering if there is something similar out there? I have only been able to find tag cloud controls.
Specifically, I like the free format typing like in a text box that looks up and presents Intellisense style the tags that match what I have typed. When I select a tag, the text is replaced with a button representing the tag with the text of the button being the tag text.
Update: adding screenshots
Adding a new tag
viewing existing tags and click 'x' to delete tag
This seemed like a really nice exercise, so I tried to build this control. I didn't test it thoroughly, let me know if you want to work with it and need further help.
Example usage:
ViewModel:
EvernoteTagControl:
EvernoteTagItem:
Themes/generic.xaml:
Here's how I would go about creating this control.
High Level Overview:
This control will contain the following main components: (1) an
AutoCompleteTextBox
orAutoCompleteComboBox
(2) the "button" control that you describe (3) A UI collection to hold applied tags. TheAutoCompleteTextBox
and the collection to hold applied tags would be positioned ahead of time in a layout container of your choice.First, we can leverage an
AutoCompleteTextBox
orAutoCompleteComboBox
to give us the Intellisense-style options as the user types. Next, we "listen" for the user selecting a presented tag from the drop-down list and dynamically create a new "button" control (we could create a UserControl/CustomControl for it ahead of time but we'd need to "new" one up at least). The "button" will contain as its text the text of theAutoCompleteTextBox
. Finally, we insert the new "button" into a ListBox (or other relavant UI collection type) that holds all the currently applied tags.Details:
There are a few
AutoCompleteTextBox
controls out there, but I'll describe how you could use this CodeProject one. This sample project shows how you can use either a regularTextBox
, anAutoCompleteComboBox
orAutoCompleteTextBox
to achieve the intellisense-style options. The core pieces of this project are really theAutoCompleteManager
and a DataProvider, of typeIAutoCompleteDataProvider
, along with theIAutoAppendDataProvider
.Before describing further details, here's some screenshots of this
AutoCompleteTextBox
control in action (note I'm using a different Style for the ListBoxItems than the original author supplies). TheAutoAppend
property of this control is a nice touch (it is turned on for this example so after I start typing the current match automatically "finishes" my word for me). After typing just an "I":After hovering my mouse over "Indiana":
After clicking on "Indiana":
Since the code from this project handles the drop-down options for us, we now need to "listen" for when the user selects an item from the drop-down list and create the new "button" control accordingly. There are two main cases that I'm thinking of for this that we need to handle.
The first case is when the user selects an item from the list with their mouse. To handle this, we could insert the code to create the new "button" control in the
MouseLeftButtonUp
handler in theAutoCompleteManager.cs
, which is around line 451:The second case is when the user selects an item from the list by hitting the enter key. To handle this we could insert similar new code in the
TextBox_PreviewKeyDown
handler inAutoCompleteManager.cs
, around line 291:Fine-Print Details
If you decide to use the
AutoCompleteTextBox
from the CodeProject that I mentioned, you may need to apply a couple of fixes. I ran into two small things after I imported everything into a larger project (they did not happen when just running the included sample project). The first one was this Binding error:Others have experienced this problem with ListBoxes, described here. As one of the answers to that post suggests, I was able to include an explicit style setting for the HorizontalContentAligment and VerticalContentAlignment in my Style to solve this problem.
The second issue occurred after the
AutoCompleteTextBox
was in an app that included tabs. When you have controls in a TabControl, the nested controls will get their Loaded event raised quite often - at least once for every time that the tab that contains the control is clicked on. This caused unexpected extra calls to theAutoCompleteManager's AttachTextBox()
method, causingdebug.Assert()
to fail and exceptions to occur (the original author was assuming that the Loaded event would only be raised one time). So far the only fix I needed to do to handle that has been inAutoCompeteTextBox.cs
. I just added an_isInitialized
flag to ensure thatAttachTextBox
only gets called once:Using this approach should allow you to create a control that behaves like what you describe.