WPF: ComboBox and Null Values

When binding a ComboBox in WPF, you don’t have access to select a null value. There is several ways to allow ComboBox to select a null value:

  1. By Code: You can create a list of items and add a null item (not a null value but and item instance representing the null value). This is not reusable.
  2. By using a Converter: This is a bit more reusable but is not the best for scenario that already needs a converter. Also, this method require a convert from and a convert back of the value.
  3. By using an Attached Property: To me, this seems the ideal way (unless it is implemented directly by the ComboBox) to manage null value and this will be the technique describe here.

Here is how to create the Attached property:

public static class ComboUtil
{
private static readonly CommandBinding DeleteCommandBinding = new CommandBinding(ApplicationCommands.Delete, HandleExecuteDeleteCommand);

private static void HandleExecuteDeleteCommand(object sender, ExecutedRoutedEventArgs e)
{
var combo = e.Source as ComboBox;
if (combo != null)
combo.SelectedIndex = -1;
}

#region AllowNull Property

public static bool GetAllowNull(ComboBox combo)
{
if (combo == null)
throw new ArgumentNullException("combo");

return (bool)combo.GetValue(AllowNullProperty);
}

public static void SetAllowNull(ComboBox combo, bool value)
{
if (combo == null)
throw new ArgumentNullException("combo");

combo.SetValue(AllowNullProperty, value);
}

public static readonly DependencyProperty AllowNullProperty =
DependencyProperty.RegisterAttached(
"AllowNull",
typeof(bool),
typeof(ComboUtil),
new UIPropertyMetadata(HandleAllowNullPropertyChanged));

private static void HandleAllowNullPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var combo = (ComboBox)o;
if (true.Equals(e.NewValue))
{
if (!combo.CommandBindings.Contains(DeleteCommandBinding))
combo.CommandBindings.Add(DeleteCommandBinding);
}
else
{
combo.CommandBindings.Remove(DeleteCommandBinding);
}
}

#endregion
}



By using the above code, you will now be able to create a nullable comboBox by xaml only:



<ComboBox local:ComboUtil.AllowNull="true">
<
ComboBoxItem>Hello</ComboBoxItem>
<
ComboBoxItem>Hi</ComboBoxItem>
</
ComboBox>





and reset the combo by hitting the <DELETE> key when the ComboBox has the input focus.



Happy WPF programming!



Dany

4 comments:

Anonymous said...

Hi Dany,

I found a lot of solutions for this problem but this is the best one I've found!

Thanks,

Jeroen

Recumbent Guy said...

far easier then other solutions i've found! Perfect!

Unknown said...

Worked for me, simple over other alternatives. Many thanks!

wei said...

Others have already expressed their appreciation. I also want to mention that this is the cleanest solution I found. An alternative to let the ComboBox assign a null value to its binding SelectedItem is to set IsEditable to true. Then when the user deletes the text from the TextBox, it automatically converts it to a null value. But the problem of it in my case is, when setting IsEditable, the TextBox doesn't use the ItemTemplate I set. Instead, it just uses ToString of the whole object, or uses the property's ToString, if TextSearch.TextPath is set. Neither is what I want because by object has multiple properties and I want the user to see all of it in the selected area by using the same ItemTemplate as the ones in the drop-down list.