Set value to null in WPF binding
Asked Answered
T

3

123

Please take a look at the following line

<TextBox Text="{Binding Price}"/>

This Price property from above is a Decimal? (Nullable decimal).

I want that if user deletes the content of the textbox (i.e. enters an empty string), it should automatically update the data source (the target of the binding) with null (Nothing in VB).

Any ideas on how I can do it in XAML?

Toed answered 13/12, 2009 at 3:15 Comment(0)
T
239

I am using .NET 3.5 SP1 so it's very simple:

<TextBox Text="{Binding Price, TargetNullValue=''}"/>

Which stands for (thanks Gregor for your comment):

<TextBox Text="{Binding Price, TargetNullValue={x:Static sys:String.Empty}}"/>

sys is the imported xml namespace for System in mscorlib:

xmlns:sys="clr-namespace:System;assembly=mscorlib"

Hope that helped.

Toed answered 13/12, 2009 at 3:40 Comment(7)
Actually TargetNullValue works just fine. What it does is set an equivalence between the given value and null. So in this case when the bound value is null it will display an empty string and when the target's value is the empty string it will set the bound value to null.Toothed
The TargetNullValue works. I got same results when using the value converter. You can also simplify the expression: <TextBox Text="{Binding Price, TargetNullValue=''}"/>Nara
I'm confused - the OP says: "..it should automatcally update source with null [when Target is an empty string].", but TargetNullValue updates the Target, not the Source!Idleman
You're not the only confused one - there are confused comments on the other answer too. The OP also is slightly confused, when he says update the source, he actually means the Target in WPF speak (the source is the Text property on the TextBox). TargetNullValue says what value to set the Source to when the Target is null. The reverse of this, which is what we're taking advantage of here, is that when the source is updated to this specified value, then the target will be set to null.Approximal
@Idleman While TargetNullValue is indeed intended to updated the Target and not the Source, this solution still does the trick for some reason (I could not quite figure out why).Clari
@Idleman I made a new question regarding TargetNullValue: #36402791Clari
a virtual pint from me! Cheers man!Pazice
W
12

This value converter should do the trick :

public class StringToNullableDecimalConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, 
        CultureInfo culture)
    {
        decimal? d = (decimal?)value;
        if (d.HasValue)
            return d.Value.ToString(culture);
        else
            return String.Empty;
    }

    public object ConvertBack(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        string s = (string)value;
        if (String.IsNullOrEmpty(s))
            return null;
        else
            return (decimal?)decimal.Parse(s, culture);
    }
}

Declare an instance of this converter in the ressources :

<Window.Resources>
    <local:StringToNullableDecimalConverter x:Key="nullDecimalConv"/>
</Window.Resources>

And use it in your binding :

<TextBox Text="{Binding Price, Converter={StaticResource nullDecimalConv}}"/>

Note that TargetNullValue is not appropriate here : it is used to define which value should be used when the source of the binding is null. Here Price is not the source, it's a property of the source...

Wool answered 13/12, 2009 at 3:28 Comment(4)
A converter is the proper way to do this, and you can't define these converters in XAML. Converters allow you to change the default "object to object" conversion behavior in data-binding, which is what you're wanting to do.Conformist
The problem in my case is that I already use a convereter here that does another thing. I posted an answer, please take a look.Toed
might want to use IsNullOrWhiteSpace() to allow " " to be counted as null (most probably what you want)Discountenance
+1 However: Price is your source here but you are correct TargetNullValue is not appropriate here - TargetNullValue sets the target when the source is null - whereas we want to set the source (to null) when the target is a certain value (an empty string) - which your converter does.Idleman
T
5

You can try using a ValueConverter (IValueConverter) http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx

Of the back of my head here, something like:

public class DoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        return (double)value;
    }

    public object ConvertBack(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
    var doubleValue = Convert.ToDouble(value);

    return (doubleValue == 0 ? null : doubleValue);
    }
}

(Might need some tweaking though)

Thing answered 13/12, 2009 at 3:20 Comment(1)
I would prefer a Xamly way, but I can't think of anythingToed

© 2022 - 2024 — McMap. All rights reserved.