Wednesday, September 26, 2012

Refactored WPF Auto-Complete ComboBox

Proper WPF Auto-Complete ComboBox

I had to use the Auto-Complete ComboBox included in the WPF Extended Toolkit recently. Now before I say anything else, I amongst many others appreciate the work done on this toolkit and am very greatful for it. I know that it is the culmination of work done by many competent individuals. However, the AC (Auto-Complete) ComboBox was a nightmare for my use-case.

I needed a ComboBox that:

- was Editable
- Sorts the items following each key stroke and keeps them up-to-date
- affords Data Binding to the selected item

Why was it a nightmare?

This was not easy because of the way the focus would jump from a list item to the text part of the combobox. Once a partial match was made (typed 'a' and the list contains "Aardvark", the text would be replaced with the first item in the list of matches (Aardvark). So if i was typing Apples, the 'a' would then change the text in the ComboBox to Aardvark and select it all. Then i strike 'p' and now the text in the ComboBox is wiped and replaced with 'p'... But my list also has "Plums". So now my selected text is "Plums".

And so on... (there were many use-cases where it would end up in a royal mess... users HATED this screen and would avoid it like the plague)

The first approach was to add the missing functionality from the out-of-the-box ACCB (Auto-Complete ComboBox) by extending the class and using a mixture of method overriding and event handlers. This helped early on but didn't quite cut it: there was always a case where the focus would get lost or the text was highlighted from an odd point. Thus in the end, the control had very odd behaviour (as described above).

That's when I restarted the control from scratch. I decided to use a ComboBox (non Editable) with a TextBox that sits above the Text part of the ComboBox and do the coupling myself.

However, I needed access to which item was highlighted in the dropdown when the user cycles through the possible matches. So I stood on the shoulders of giants (Christian Moser's WPF Tutorial to be exact) and use the LivePreviewComboBox which was conjured up for just that reason. When the user starts typing and the dropdown opens with matches, hitting the down button will then scroll through the items. Similarly, hitting the up key will bring the focus up the list and finally back into the textbox to type more text.

I have a custom theme so for me this sufficed. If you are not happy with the look of the control, apply a style to it! To do so, you can create a style for the class AutoCompleteComboBox and set the template to whatever you want. I used a LivePreviewComboBox on top of some rectangles to react to IsMouseOver and HasFocus. The choice is yours!

Go ahead and download the source code and sample project!