Search Wiki:
Resource Page Description
WPF seems to have a problem databinding to nullable value types, this page shows a couple of workarounds.

The problem
When you try to apply TwoWay DataBinding between a WPF control dependency property (e.g. the SelectedValue property of a ComboBox) and a property of your data item
which is a nullable type, it doesn't always work as expected.
Specifically, if the initial value of the data property is null then WPF appears to 'lose' the binding - e.g.

<ComboBox Name="cboVehicleType"
	  SelectedValue="{Binding Path=VehicleTypeId, Mode=TwoWay}" 
	  SelectedValuePath="Tag">
    <ComboBoxItem Tag="1">Car</ComboBoxItem>
    <ComboBoxItem Tag="2">Motorbike</ComboBoxItem>
    <ComboBoxItem Tag="3">Lorry</ComboBoxItem>
</ComboBox>

If the initial value of VehicleTypeId (a nullable int) is set to 1 then the initial selected item is 'Car' and when you select another item then the VehicleTypeId changes appropriately (e.g. if you select 'Motorbike' then VehicleTypeId will get set to 2 via databinding) - as expected.
If the initial value of VehicleTypeId is set to null then the initial SelectedIndex is -1 (i.e. no item selected) - as expected.
However, when you select another item then the VehicleTypeId does not change - it always stays as null.

The workaround
Use a ValueConverter to convert the null value into an intermediate value which WPF likes (which you can later convert back from in TwoWay databinding mode).
e.g. the following example converts a null int to -1 (and -1 back to null):

using System;
using System.Globalization;
using System.Windows.Data;
 
namespace WpfNullableSamples
{
    [ValueConversion(typeof(int?), typeof(int))]
    public class NullableIntToNegativeOneConverter : IValueConverter
    {
 
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                return -1;
            }
            else
            {
                return value;
            }
        }
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int i;
 
            if (value == null)
            {
                return null;
            }
            else
            {
                if (int.TryParse(value.ToString(), out i))
                {
                    if (i == -1)
                    {
                        return null;
                    }
                    else
                    {
                        return value;
                    }
                }
                else
                {
                    return value;
                }
            }
        }
 
    }
}
The above converter can be used like so:

<Window x:Class="WpfNullableSamples.NullableWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfNullableSamples"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    Title="Nullable Window" SizeToContent="WidthAndHeight">
    <Window.Resources>
        <local:NullableIntToNegativeOneConverter x:Key="nullableIntToNegativeOneConverter"/>
    </Window.Resources>
    <StackPanel>
        <ComboBox Name="cboVehicleType"
                  SelectedValue="{Binding Path=VehicleTypeId, Mode=TwoWay, Converter={StaticResource nullableIntToNegativeOneConverter}}" 
                  SelectedValuePath="Tag">
            <ComboBoxItem Tag="1">Car</ComboBoxItem>
            <ComboBoxItem Tag="2">Motorbike</ComboBoxItem>
            <ComboBoxItem Tag="3">Lorry</ComboBoxItem>
        </ComboBox>
    </StackPanel>
</Window>
The following example converts a null boolean to '[[NullString]]' (and back from '[[NullString]]' to null):

using System;
using System.Globalization;
using System.Windows.Data;
 
namespace WpfNullableSamples
{
    [ValueConversion(typeof(bool?), typeof(string))]
    public class NullableBooleanConverter : IValueConverter
    {
        private const string NullString = "[[NullString]]";
 
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool parsedValue;
 
            if (value == null)
            {
                return NullString;
            }
            else
            {
                if (bool.TryParse(value.ToString(), out parsedValue))
                {
                    return parsedValue ? bool.TrueString : bool.FalseString;
                }
                else
                {
                    return NullString;
                }
            }
        }
        
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool parsedValue;
            if (value == null)
            {
                return null;
            }
            else
            {
                if (bool.TryParse(value.ToString(), out parsedValue))
                {
                    return parsedValue;
                }
                else
                {
                    return null;
                }
            }
        }
    }
}
An example of using this nullable boolean converter with a RadioButtonList can be found here
Last edited Apr 1 2008 at 8:07 PM  by hortha, version 15
Comments
c10_panda wrote  May 26 2008 at 6:14 AM  
I had to write a comboxbox.selectionChanged event handler to make it work. Is this bug fixed in .net 3.5 sp1?

hortha wrote  May 28 2008 at 10:29 PM  
In Scott Guthrie's blog (http://weblogs.asp.net/scottgu/archive/2008/05/12/visual-studio-2008-and-net-framework-3-5-service-pack-1-beta.aspx) it says the WPF Data Improvements include 'Better handling and conversion support for null values in editable controls' so let's hope so!
I haven't dared install SP1 yet so I can't say conclusively!

Updating...
Page view tracker