Something trivial that's currently not possible with the
ComboBox or
DataGridComboBoxColumn (Toolkit) controls of WPF is adding a "none"-option on top op their dropdown without having to add it to the
ItemsSource, which would be really bad design. So this is how I implemented this common requirement:
The converter
A
converter is needed to make sure the none-option actualy sets the bound property to null. Without it the property would simply not change.
I created one called
NullObjectConverter. It's
Convert-method simply returns the
value-parameter.
The
ConvertBack-method does this:
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
if (value == null || value.GetType() != targetType)
return null;
else
return value;
}
I've put the resource for it in the resources of the
App-class, so I don't have to do that in every XAML-file that needs it:
<this:NullObjectConverter x:Key="convNull" />
The XAML
This is my XAML for a
DataGridComboBoxColumn. Notice how it uses the converter above. Important is that it's
ItemsSource is a
CompositeCollection composed from the none-option and the actual list of options:
<toolkit:DataGridComboBoxColumn Header="Store"
SelectedValueBinding="{Binding Store,
Converter={StaticResource convNull}}">
<toolkit:DataGridComboBoxColumn.ItemsSource>
<CompositeCollection>
<ListBoxItem>(none)</ListBoxItem>
<CollectionContainer x:Name="cboStoreCollection" />
</CompositeCollection>
</toolkit:DataGridComboBoxColumn.ItemsSource>
</toolkit:DataGridComboBoxColumn>
The
none-option will arrive in the converter as a
ListBoxItem while the target type will be the type of the bound object, and therefore the converter will send
NULL to the bindings' source when it's selected.
Finally, notice that the
CollectionContainer that contains the actual list of options gets it's items in the code-behind, and therefore has a name:
cboStoreCollection.Collection = mStores;