Binding to double field with validation

前端 未结 6 936
时光说笑
时光说笑 2020-12-30 04:13

I\'m trying to bind TextBox to double property of some object with UpdateSourceTrigger=PropertyChanged. The goal is to immediately dur

相关标签:
6条回答
  • 2020-12-30 04:15

    The behavior of binding float values to a textbox has been changed from .NET 4 to 4.5. With .NET 4.5 it is no longer possible to enter a separator character (comma or dot) with ‘UpdateSourceTrigger = PropertyChanged’ by default.

    Microsoft says, this (is) intended

    If you still want to use ‘UpdateSourceTrigger = PropertyChanged’, you can force the .NET 4 behavior in your .NET 4.5 application by adding the following line of code to the constructor of your App.xaml.cs:

    public App()  
    {
        System.Windows.FrameworkCompatibilityPreferences
                   .KeepTextBoxDisplaySynchronizedWithTextProperty = false;   
    }
    

    (Sebastian Lux - Copied verbatim from here)

    0 讨论(0)
  • 2020-12-30 04:16

    I have run into the same problem, and have found a quite simple solution: use a custom validator, which does not return "valid" when the Text ends in "." or "0":

    double val = 0;
    string tmp = value.ToString();
    
    if (tmp.EndsWith(",") || tmp.EndsWith("0") || tmp.EndsWith("."))
    {
        return new ValidationResult(false, "Enter another digit, or delete the last one.");
    }
    else
    {
        return ValidationResult.ValidResult;
    }
    
    0 讨论(0)
  • 2020-12-30 04:20

    Try using StringFormat on your binding:

    <TextBox Width="100" Margin="10" Text="{Binding DoubleField, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, StringFormat='0.0'}"> 
    

    Not sure if that string format is even right since I've not done one for a while but it's just an example

    0 讨论(0)
  • 2020-12-30 04:24

    I realize I'm a little late to the party but I found a (I think) rather clean solution to this problem.

    A clever converter that remembers the last string converted to double and returns that if it exists should do everything you want.

    Note that when the user changes the contents of the textbox, ConvertBack will store the string the user input, parse the string for a double, and pass that value to the view model. Immediately after, Convert is called to display the newly changed value. At this point, the stored string is not null and will be returned.

    If the application instead of the user causes the double to change only Convert is called. This means that the cached string will be null and a standard ToString() will be called on the double.

    In this way, the user avoids strange surprises when modifying the contents of the textbox but the application can still trigger a change.

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-30 04:29

    The problem is that you are updating your property every time the value changes. When you change 12.03 to 12.0 it is rounded to 12.

    You can see changes by providing delay by changing the TextBox in xaml like this

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

    but delay will notify and set the property after the delay time in mili sec. Better use StringFormat like this

    <TextBox Width="100" Margin="10" Text="{Binding DoubleField, UpdateSourceTrigger=PropertyChanged,StringFormat=N2, ValidatesOnDataErrors=True}">
    
    0 讨论(0)
  • 2020-12-30 04:39

    Tried formatting the value with decimal places?

    It may be weird though since you will then always have N decimal places.

    <TextBox.Text>
        <Binding Path="DoubleField" StringFormat="{}{0:0.00}" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True"/>
    </TextBox.Text>
    

    If having fixed decimal places is not good enough, you may have to write a converter that treats the value as a string and converts it back to a double.

    0 讨论(0)
提交回复
热议问题