'WPF binding not working properly with properties of int type

I am having a property of int type in my view model which is bound to a TextBox. Everything works properly, TwoWay binding works fine except in one case -

If I clear the value of TextBox, property setter doesn't gets called and although value is cleared in TextBox, property still holds the previous value.

has anyone faced similar issue? is there any workaround for this?

Here is the property -

public int MaxOccurrences
{
    get
    {
        return this.maxOccurrences;
    }
    set
    {
        if (this.maxOccurrences != value)
        {
            this.maxOccurrences = value;
            base.RaisePropertyChanged("MaxOccurrences");
        }
    }
}

Here is how I am binding the property in xaml -

<TextBox Text="{Binding Path=MaxOccurrences, Mode=TwoWay, 
    NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" 
    HorizontalAlignment="Center" Width="30" Margin="0,0,5,0"/>


Solution 1:[1]

If you don't want to use a Nullable integer, you can use a converter that converts the empty string to 0, see the code below:

public class EmptyStringToZeroConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value == null || string.IsNullOrEmpty(value.ToString())
            ? 0
            : value;
    }

    #endregion
}

Solution 2:[2]

This is partially a guess (I haven't got VS handy right now to try it out), but I think it's because a cleared text box is an empty string (""), which can't be implicitly converted to an int. You should probably implemented a type converter to provide the conversion for you. (you probably want to do something like convert "" to 0)

Solution 3:[3]

Akjoshi, I have a working solution!

You need to change your integer property to Naullable<int> (i.e. int? ), see the following snippet:

private int? _maxOccurrences;
public int? MaxOccurrences
{
    get { return _maxOccurrences; }
    set { _maxOccurrences = value; }
}

You also need to add a value converter to convert the empty string to null value, see the following code snippet:

public class EmptyStringToNullConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value == null || string.IsNullOrEmpty(value.ToString())
            ? null
            : value;
    }

    #endregion
}

The XAML code:

<Window x:Class="ProgGridSelection.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:System="clr-namespace:System;assembly=mscorlib" 
    xmlns:local="clr-namespace:ProgGridSelection"
    Title="MainWindow"
    Height="136" Width="525"
    Loaded="OnWindowLoaded">
<Window.Resources>
    <local:EmptyStringToNullConverter x:Key="EmptyStringToNullConverter"/>
</Window.Resources>
<StackPanel>
    <Button Content="Using Empty String to Null Converter"/>
    <TextBox Name="empNameTextBox"
             Text="{Binding Mode=TwoWay, Path=MaxOccurrences,
                RelativeSource={RelativeSource FindAncestor, AncestorType=Window},
                Converter={StaticResource EmptyStringToNullConverter}}"/>
</StackPanel>

[Note: this is just a proof of concept, and for the sake of simplicity I didn't use any patterns or best practices]

Solution 4:[4]

I have the same problem, but I need to handle and not numeric value to. I use the following converter for this:

public class StringFormatToIntConverter : IValueConverter
{            
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
          return value.ToString();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
       if(value is string)
       {
           var inttext = 
            System.Text.RegularExpressions.Regex.Replace((string)value, "[^.0-9]", "");

           int number;
           return Int32.TryParse(inttext, out  number) ? number : 0;
       }
       else
       {
           return value;
       }
    }
}

Solution 5:[5]

It's because an int value can't be null. It's best to use a string property that converts the value for you within your code to the required int property field.

That way you can perform a

if(string.IsNullOrEmpty(text))
{
  this.intValue = 0;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 akjoshi
Solution 2 akjoshi
Solution 3 akjoshi
Solution 4 akjoshi
Solution 5 akjoshi