Drop-down composite controls with WPF Elements
Everybody is familiar with the traditional Windows combo box. Combo boxes are a convenient compromise between list boxes and text boxes because, like a text box, they don’t take up much space on screen, but like a list box, they provide a safe and discoverable user interface for choosing a value — users don’t have to remember what values they’re allowed to type.
The limitation of combo boxes is that they are what WPF calls “items controls.” They’re specifically about selecting from a restricted set of items. So if you want the compact presentation of a combo box, but your data can’t be restricted to a list, you’re out of luck. Examples include a date picker — you can’t provide a list of every date in history, but users like being able to pick the date off a calendar rather than typing it in — or a colour picker — again, you can’t put every possible colour in a list, but users like to select from swatches or colour wheels or using sliders, rather than having to type RGB or CMYK codes.
WPF Elements includes a simple control called the DropDownEditBox which addresses this situation. DropDownEditBox enables you to combine a compact presentation with a more expansive “chooser”, which is usually hidden away but can be dropped down when required. In fact, WPF Elements uses DropDownEditBox to build its own DropDownDatePicker control.
DropDownEditBox is a deliberately dumb control. It doesn’t make any assumptions about the kinds of data that its children are dealing with. This means that, unlike the combo box, it can’t give them any help either. It’s entirely up to the user of DropDownEditBox to appropriate “compact” and “chooser” user interfaces and synchronise their data.
In this example, we’ll build a location selector using DropDownEditBox. Our users will be able to type a location into a text box, or can drop down a map and click on the location they want.
We start out with the skeleton of a DropDownEditBox:
<ms:DropDownEditBox Content="{Binding}"> <ms:DropDownEditBox.HeaderTemplate> <DataTemplate /> </ms:DropDownEditBox.HeaderTemplate> <ms:DropDownEditBox.DropDownTemplate> <DataTemplate /> </ms:DropDownEditBox.DropDownTemplate> </ms:DropDownEditBox>
Notice that DropDownEditBox has a Content property. This is the data source that the “compact” and “chooser” templates bind to. In this case, my local data context is a Treasure object, which has Latitude and Longitude properties. If Treasure instead had a Location property, I could use that as the Content instead.
Now we create the “compact” presentation:
<ms:DropDownEditBox.HeaderTemplate> <DataTemplate> <TextBox> <TextBox.Text> <MultiBinding Converter="{StaticResource CoordinateConverter}" UpdateSourceTrigger="PropertyChanged"> <Binding Path="Latitude" /> <Binding Path="Longitude" /> </MultiBinding> </TextBox.Text> </TextBox> </DataTemplate> </ms:DropDownEditBox.HeaderTemplate>
This is a plain old text box, with an IMultiValueConverter to translate between the Latitude/Longitude property pair and a textual representation of the form “77 W, 18 N.” The converter is two-way, so that the user can enter coordinates in latitude and longitude format.
Finally, we create the “chooser” presentation. We could go to town on designing a map control, with panning and zooming and all those good good things, but that’s for another day; for this example we’ll assume we have something which has X and Y properties, displays an “X marks the spot” icon at their location and updates them in response to a mouse click. (I’m even going to mostly ignore coordinate translation because the map control isn’t the point of this discussion.) We use this simple control to create our “chooser” drop-down template:
<ms:DropDownEditBox.DropDownTemplate> <DataTemplate> <local:CoordinateSelector X="{Binding Latitude}" Y="{Binding Longitude}" Background="{StaticResource map}" /> </DataTemplate> </ms:DropDownEditBox.DropDownTemplate>
All of this is of course standard WPF data binding: there’s nothing specific to the DropDownEditBox about these templates. What the DropDownEditBox does is link the two together in a combo box-like way. Here’s what the DropDownEditBox looks like when it’s first displayed:
And when the user clicks on the down arrow:
And as the user clicks on the map or edits the location in the text box, they can see the results of their action in the other pane. The user gets the familiar combo-box-like experience, but without the restrictions of the combo box data model.
One Response to “Drop-down composite controls with WPF Elements”
Leave a Reply
Categories
BrainDump (1)
Community Code (4)
Events (15)
F# (11)
General (50)
Lab Samples (2)
LightSpeed (249)
MegaPack (7)
News (68)
NHibernate Designer (18)
Nightly news (40)
Phone Elements (22)
Products (87)
Projects (5)
Screencast (6)
SharePoint (3)
Silverlight (14)
Silverlight Elements (59)
SimpleDB Management Tools (20)
Visual Studio (9)
VS File Explorer (7)
Web Workbench (20)
WPF (43)
WPF Diagrams (53)
WPF Elements (91)
WPF Property Grid (32)


Tagged as

Posted by Ivan Towlson on 10 April 2008 



[...] In a previous post we built a handy treasure locator which allowed users to type in coordinates as well as find them on a map. In that example we relied on users’ good sense not to type in garbage. Sometimes, however, it’s helpful to restrict what users can type. WPF Elements provides several controls to support this. For our example, we can make use of the NumericTextBox. This allows users only to enter decimal numbers: all other input is prevented. [...]