Graeme Hill's Dev Blog

Nullable combo boxes in WPF

Star date: 2009.051

Update: Sample source code demonstrating this technique can be downloaded here: WpfNullableComboBox.zip

By default, combo boxes in WPF have some really annoying behaviour. When the control is initialized, if the SelectedItem is Nothing then the default selection will be blank, but as soon as you choose an item in the combo box, you can not reselect the blank/null option. One quick way around this is to add a null placeholder object to your ItemsSource. There are a few problems with this approach though:

  1. The null placeholder cannot actually be Nothing/null or else selecting the value will have no affect. Instead, it needs to be some object that represents "null". This means that if you want your setter on the property bound to the SelectedItem to be set to null, you need to convert the object representing null to actually be Nothing/null.
  2. Ideally, you should not have to alter the collection in your model view/controller/presenter that is bound to the ItemsSource just to add a null option. It would be better if we could just specify in XAML that this combo box should have a null option that actually sets the SelectedItem to Nothing.

Since we don't want to alter the collection in the controller and we cannot have a combo box item of Nothing (we need a null place holder object instead) but we don't want the SelectedItem property to ever have the null place holder object as its value (we want it to just be Nothing when that is chosen) we can do one of two things:

  1. Use two converters: one on the ItemsSource to add in the null place holder object and one on SelectedItem to convert the place holder to Nothing.
  2. Create a user control that acts as a wrapper around the combo box control. All the necessary logic could be handled within the user control.

Option one would look like this:

<ComboBox
    ItemsSource="{Binding MyItems, Converter={StaticResource addNullPlaceHolderConverter}}"
    SelectedItem="{Binding MySelectedItem, Converter={StaticResource placeHolderToNullConverter}}" />

In my opinion, that method really sucks. You have to add the converters in you resources section and then specify them in two places. Another issue is that we could run into some major converter explosion if it turns out that you already need some other converter on one of the properties. Then you have to make a new converter that combines the two. I don't like it.

Option two looks like this:

<local:NullableComboBox
    ItemsSource="{Binding MyItems}"
    SelectedItem="{Binding MySelectedItem}" />

Much better!

The XAML for the user control is extremely simple. You just need to create a combo box with a name:

<UserControl x:Class="NullableComboBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ComboBox x:Name="combo" />
</UserControl>

In the code-behind you need to expose two dependency properties: SelectedItem and ItemsSource so that the control has the same interface as a regular combo box.

By listening to the combo box's SelectionChanged event you can update the SelectedItem property on the NullableComboBox except with the place holder converted to Nothing.

comments powered by Disqus