Something missing from WPF (and the toolkit and even the extended toolkit) is a good reusable search box control. Well, now you too can have a pretty good one (if I dare say so). The need for one is so apparent that even Microsoft singles it out as a specific control in their guidelines*, which I used extensively to design the look and behavior of this control.
Too busy to read the details? That’s fine.
(Don’t forget to change the namespaces and image paths!)
See another of my custom WPF controls here.
Updated (9/27/2011): Added
Classic.xaml files for XP and classic theme support.
I based my work on that of David Owens’ post back in 2009, wherein he attempted to address this same issue. His control is perfectly usable, I must point out, but I wanted something a bit different and closer to the official guidelines and, hey, let’s not pass up an opportunity to learn, right? (And I did ask nicely before releasing this obvious plagiarism!)
Many of my changes from his design are semantic in nature, renaming “delayed” to “regular” for instance, in accordance with the terminology used by the guidelines. The first real major difference is that his relies a lot on mouse events and other code to provide the visual functionality, which I eschewed in favor of doing as much of that as possible in XAML presentation code.
- Instant and regular search modes
- Command or click event support, whichever you prefer
- Easy delayed search support (instant mode only)
- Prompt text overlay when empty
- Single convenient switch for allow/disallow empty text searches
I’m not going to detail every line of code here, but I will point out some of the more interesting bits. A lot of the parts David handled in events I’ve replaced with triggers and such. This keeps it in the XAML (where presentation code belongs, in my opinion) plus it simplifies things as only a few are really needed. I’ve also split out the regular and instant mode templates. This reduces the complexity considerably, too, as it prevents me having to support two totally different views of the control by splitting them into their own templates. A lot of the trigger logic hinges on the HasText property which, I admit, largely exists for templating-ease and little else. Honestly, I don’t mind “polluting” the control logic code with this stuff if it makes the templating much easier.
The search delay is made possible by a simple DispatcherTimer, ripped straight out of David’s original code. It works off of the underlying TextChanged event to reset the timer on each keypress, so that you can reduce the hammering on your database or whatever.
The command code is actually a bit yucky, as I had to do a lot of plumbing to keep changes to the command properties in sync with the button’s. Due to the way templating works, it’s possible that the applied template has no search button and so lots of null checks exist to guard against that case. I admit I didn’t test it extensively to confirm it would work with odd templates, but hey that’s why you’ve got the entire source to modify if need be.
I tried to make the defaults sensible. If you only define the control with no parameter settings, you’ll get an Instant search box with no delay (so really and truly instant!) and a simple “Search” prompt text overlay.
For the future
Some things to improve on would be better built-in templating support for simple changes. Right now, if you want the look and feel changed you have to re-template the whole control. That’s doable, but it kinda sucks frankly as it isn’t a simple template. Sometimes it might be necessary for radical differences, but if you only want to change the icons or something like that it’s kinda irksome. A few simple exposed template properties would be a nice and relatively simple addition.
And speaking of the templates, I kind of want to go back and replace a lot of the triggers with VisualStateGroups and such. Not only does this make porting to Silverlight easier but it does allow for better semantic control of the visual state stuff. It also makes it easier to add more complex state changing animations in Blend.
The AllowEmptySearches boolean property is convenient but a bit clumsy in its approach (and implementation, actually). It’s an awkwardly named property that might take a second to click on why it even exists and it would probably do better as something like MinimumNumOfChars. That way you could still set it to 1 and get the same effect but also set it to 2 or 3 or whatever you want. Much more useful. You can obviously enforce this in the logic that handles the search click event or command execution, but this gives you the added benefit of UI enforcement (it disables the search button in regular search mode, for instance) which makes the rule more apparent to the user.
Lastly I’m not sure I ever got the designer support exactly how I wanted. For some reason my VS2010 always displays the instant search mode wrong, with the clear X button visible. When running in the program it displays correctly, of course, but not design. Couldn’t ever figure out what I was doing wrong or if it was VS2010 and not me.
Okay, enough yapping from me. You can download the entire source below as four files (.cs and .xaml plus two .png icons). The code is free for use, however you see fit, I don’t care. I like attribution, though — more for the hard-working smart people I ripped a lot of this off of than myself (as you can see in the source files).
Important! Some things to note as it won’t exactly be a perfect drop-in file. Change the namespaces to whatever you like. Also, you’ll want to modify the image file paths to match however you added them to your project.
I may decide to update this post and add a simple solution file with example demo project or something. We’ll see.
If you like this, I’ve got several more neat controls up my sleeve, but I’d have to polish them up a bit before releasing as they’re not quite cleaned up enough for the camera. Suffice it to say, whether I release them or not will depend on when I have some time.