none
.NET 4.5及之后版本WPF绑定浮点数小数点不能输入

    问题

  • .NET 4.0中正常,.NET 4.5及之后的版本均存在此问题。

    在使用WPF的时候,TextBox绑定浮点数类型,并且ViewModel实现INotifyPropertyChanged,Binding的UpdateSourceTrigger为PropertyChanged时,TextBox中不能输入小数点,请问是BUG吗?

    2016年5月18日 1:07

答案

全部回复

  • 目前仅能通过自己写Converter解决,但是是有缺陷的,返回 DependencyProperty.UnsetValue 会导致TextBox显示红框,导致Validate错误。
        public class NullableDecimalConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                return value;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                string strValue = value as string;
                if (string.IsNullOrEmpty(strValue))
                {
                    return null;
                }
                decimal result;
                if (strValue.IndexOf('.') == strValue.Length - 1 || !decimal.TryParse(strValue, out result))
                {
                    return DependencyProperty.UnsetValue;
                }
                return result;
            }
        }

    2016年5月18日 1:35
  • Hi Never,

    因为你的问题是与WPF有关,我会帮忙把你的帖子移到那个版块来提高更好的支持,感谢你的谅解。

    Regards,

    Moonlight


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.



    2016年5月19日 6:55
  • 您好 Never772,

    >>"TextBox中不能输入小数点,请问是BUG吗?"

    这不是BUG, 当绑定的数据类型不是String的时候,系统会提供一个默认的Converter。不能输入小数点的原因是, 当用户输入“1.” 的时候, 在Convert里会把“1.”转换为浮点类型1,然后把1显示在文本框中,给我以没有输入小数点的错觉。

    >>"目前仅能通过自己写Converter解决,但是是有缺陷的,返回 DependencyProperty.UnsetValue 会导致TextBox显示红框,导致Validate错误。"

    只要返回DependencyProperty.UnsetValue, TextBox中就会有红框。我们可以在Convert中加入一个标志位,表明TextBox中是否有合法的小数点。然后在Convert方法中显示出来。下面是您的Converter的改良版。供您参考。

    public class NullableDecimalConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
    
            return value == null ? string.Empty : _hasDot ? value.ToString() + "." : value.ToString();
        }
    
        private bool _hasDot = false;
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string strValue = value as string;
            if (string.IsNullOrEmpty(strValue))
            {
                return null;
            }
            decimal result;
            if (!decimal.TryParse(strValue, out result))
            {
                return DependencyProperty.UnsetValue;
            }
            _hasDot = strValue.IndexOf('.') == strValue.Length - 1;
            return result;
        }
    }
    Best Regards,
    Li Wang

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    2016年5月20日 3:13
  • 感谢您关注我的问题,这个方法我试过,但是考虑到性能问题,在Convert方法中加入小数点会再次触发一系列事件。
    2016年5月20日 9:32
  • 您好 Never772,

    >>"但是考虑到性能问题,在Convert方法中加入小数点会再次触发一系列事件。"

    ConvertBack有可能会出发一系列事件,但是这都发生在输入的时候。输入的时候不涉及大数量的操作。所以对性能不会造成什么影响。

    Best Regards,
    Li Wang


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2016年5月20日 9:49
  • 您好,又碰到新问题了,就是小数点后末位为0的情况,如果不使用DependencyProperty.UnsetValue,实现会更复杂,真希望官方能把这些相关代码换回.NET 4.0的,因为4.0中没有这个问题,以下是我修改的代码。

        public class NullableDecimalConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return value;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                string strValue = value as string;
                if (string.IsNullOrEmpty(strValue))
                {
                    return null;
                }
                decimal result;
                if (strValue.IndexOf('.') == strValue.Length - 1 || strValue.IndexOf('0') == strValue.Length - 1 || !decimal.TryParse(strValue, out result))
                {
                    return DependencyProperty.UnsetValue;
                }
                return result;
            }
        }

    2016年5月23日 10:43
  • 您好 Never772,

    感谢您的建议。 我们还可以在Binding里设置StringFormat来避免这个问题。以下代码供您参考。

    <TextBox Text="{Binding Path=Price, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,StringFormat=N2}"></TextBox>
    Best Regards,
    Li Wang

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2016年5月24日 2:38
  • 感谢您的回复,此方案之前测试过,体验不好,必须手动把光标点到开始位置,小数点位置必须手动跳过,使用右方向键或使用鼠标。
    2016年5月24日 11:03
  • 有BUG,再次修改.

        public class NullableDecimalConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return value;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                string strValue = value as string;
                if (string.IsNullOrEmpty(strValue))
                {
                    return null;
                }
                decimal result;
                if (strValue.IndexOf('.') == strValue.Length - 1 || (strValue.IndexOf('0') == strValue.Length - 1 && strValue.IndexOf('.') != -1) || !decimal.TryParse(strValue, out result))
                {
                    return DependencyProperty.UnsetValue;
                }
                return result;
            }
        }

    2016年5月25日 8:35
  • 又发现问题,当绑定类型为Nullable<T>,并且TextBox的Text为空时,不会返回null给ViewModel,这些在.NET 4.0中都正常,4.5及之后都有这些问题。
    2016年5月27日 3:40
  • ?????
    • 已建议为答案 [-] 2016年5月31日 7:43
    • 已标记为答案 CaillenModerator 2016年6月2日 5:38
    • 已编辑 [-] 2018年1月11日 13:03
    2016年5月27日 16:59