Aug 16, 2011

A WPF SearchTextBox control

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 Luna.NormalColor.xaml and Classic.xaml files for XP and classic theme support.

Genesis

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.

Features

  • 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

Code highlights

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.

Source

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.

* Speaking of which, if you are doing WPF work (or even WinForms) and you aren’t reading their guidelines you need to. Just remember that they are guidelines, not rules.

4 comments:

  1. I like this implementation of a search bar but would like to know how to wire it up to an ObservableCollection or other collection. I tried setting the DataContext of the search bar to that of an ObservableCollection but obviously there is something I am missing. Do you by chance have a test program that shows the search box working?

    ReplyDelete
  2. This crashes my VS2010 Framework 3.5 Changed the Image location and the Namespace but I can't even place the control in my xaml and at that point it crashes VS2010

    ReplyDelete
  3. Hi Brian,

    How to bind your control to main xaml page of my application? When i am adding your project as a dll to my main application, it is not reflecting anything infact throwing error. PLease help
    Thanks

    ReplyDelete
  4. Hello Sean,
    Do you have the demo project?. For some reason I am not able to see the control once I use it on the window. Is there something to be set/unset before using other than changing the imagepath and namespace change
    Thanks

    ReplyDelete