Flynn1179
Flynn1179

Reputation: 12075

How do you get a Combobox to set a value of null when bound to 'SelectedItem'?

I have a combobox with which I'm adding in a <x:Null/> at the beginning, as 'null' is a perfectly valid value for the bound property, but WPF doesn't seem willing to set it. Here's the XAML:

<ComboBox SelectedItem="{Binding PropertyName}">
    <ComboBox.ItemsSource>
        <CompositeCollection>
            <x:Null/>
            <CollectionContainer Collection="{Binding (available items)}"/>
        </CompositeCollection>
    </ComboBox.ItemsSource>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name, FallbackValue='(None)'}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

The collection in (available items) has objects with a Name property. The combobox correctly displays (None) when the current value of PropertyName is null, and it sets to an item in the collection when I selected one, but when I select (None), it doesn't set the property to null. Is there any way I can make it do this?

Upvotes: 2

Views: 509

Answers (2)

mm8
mm8

Reputation: 169220

Replace <x:Null> with an actual instance of something and use a converter:

public class Converter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => value;

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
        value is short ? null : value;
}

XAML:

<ComboBox>
    <ComboBox.SelectedItem>
        <Binding Path="PropertyName">
            <Binding.Converter>
                <local:Converter />
            </Binding.Converter>
        </Binding>
    </ComboBox.SelectedItem>
    <ComboBox.ItemsSource>
        <CompositeCollection xmlns:sys="clr-namespace:System;assembly=mscorlib">
            <sys:Int16 />
            <CollectionContainer Collection="{Binding Source={StaticResource items}}"/>
        </CompositeCollection>
    </ComboBox.ItemsSource>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name, FallbackValue='(None)'}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Upvotes: 1

RQDQ
RQDQ

Reputation: 15569

I recently ran into this... One way to approach this is to have a view model that can expose a null value property:

public class ListItemValue<T>
{
   public ListItemValue(string name, T value)
   {
      Name = name;
      Value = value;
   }

   public string Name { get; }

   public T Value { get; }
}

Upvotes: 0

Related Questions