当WPF中的UpdateSourceTrigger为PropertyChanged时,用户无法在绑定到浮点值的文本框中输入“.”。

7
我在WPF中使用Float数据类型和UpdateSourceTrigger时遇到了一个有趣的问题。我有一个具有float数据类型的属性,并将其绑定到TextBox上,并将Binding的UpdateSourceTrigger设置为PropertyChanged,但是除非我将UpdateSourceTrigger更改为LostFocus,否则WPF不允许我在TextBox中输入'.' 。我认为这是因为我们无法在浮点值的末尾键入'.'。我不知道该如何解决它,因为我需要键入'.'并将UpdateSourceTrigger设置为PropertyChanged。
该属性是:
  public float? Amount
    {
        get;set;
    }

在XAML中:

    <TextBox
        Text="{Binding Amount , UpdateSourceTrigger=PropertyChanged}"/>

将文本框绑定到浮点值,无法输入点号或逗号。请参考此链接:https://dev59.com/sGUq5IYBdhLWcg3wT-yD#35942615 - xmedeko
4个回答

3
也许如果您在绑定中添加一个StringFormat语句会有所帮助:
<TextBox
    Text="{Binding Amount, StringFormat='{}{##.##}', UpdateSourceTrigger=PropertyChanged}"/>    

更新:我发现我的第一个答案会引发一些绑定错误。
另一种选择是使用转换器(虽然有点脏):
...
<Window.Resources>        
    <local:FloatConverter x:Key="FloatConverter" />
</Window.Resources>
...
<TextBox Text="{Binding Amount, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource FloatConverter}}"></TextBox>

转换器:

public class FloatConverter : 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)
  {
     // return an invalid value in case of the value ends with a point
     return value.ToString().EndsWith(".") ? "." : value;
  }

}


这个问题是Net5的一个bug,在net4.5中在浮点数中键入小数点没有问题。并且这个答案不允许用户在小数点后面键入零。 - mahboub_mo
您可以回退到以前的行为,请参见https://dev59.com/sGUq5IYBdhLWcg3wT-yD#35942615。 - xmedeko

1
这是因为绑定到浮点数据类型会自动导致WPF添加一个浮点验证器。您可以通过使用不同的DataAnnotation来解决此问题,或者编写自己的验证器来避免此问题。

http://wpf-4-0.blogspot.de/2012/12/data-annotations-in-wpf-c.html

编辑: 我看到你有一个可空浮点数,所以你也可以尝试将TargetNullValue设置为“。”。


那么,将TargetNullValue设置为“.”的优势是什么?! - mahboub_mo

1
如果您有.NET 4.5或更高版本,您可以强制使用早期的4.5行为。
System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;

使用.NET 4.5,默认情况下无法在UpdateSourceTrigger = PropertyChanged时输入分隔符(逗号或点)。

此外,您可以设置延迟:

<TextBox Width="100" Margin="10" Text="{Binding DoubleField, UpdateSourceTrigger=PropertyChanged,Delay=500, ValidatesOnDataErrors=True}">

另一种方法是使用IValueConverter:
public class DoubleToPersistantStringConverter : IValueConverter
{
    private string lastConvertBackString;

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value is double)) return null;

        var stringValue = lastConvertBackString ?? value.ToString();
        lastConvertBackString = null;

        return stringValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value is string)) return null;

        double result;
        if (double.TryParse((string)value, out result))
        {
            lastConvertBackString = (string)value;
            return result;
        }

        return null;
    }
}

请查看此链接:绑定到带有验证的双精度字段

但我认为最好的方法是将 UpdateSourceTrigger 设置为 LostFocus


+1 Delay=500 可以规避验证问题,同时仍然保持 UpdateSourceTrigger 为 PropertyChanged。 - Ben Adams

0
尝试在绑定中添加StringFormat定义。像这样:
<TextBox Name="txtPower" Height="23" 
TextWrapping="Wrap" Text="{Binding Path=Power, Mode=TwoWay, 
UpdateSourceTrigger=PropertyChanged,StringFormat=N2}"></TextBox>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接