如何复制 WPF 绑定类型转换错误行为

How to duplicate WPF binding type conversion error behavior

考虑以下因素:

C#:

public class MyVM {
    public double DValue { get; set; }
}

XAML:

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

用户在框中键入“asdf”。这无法转换为 double,因此您会在文本框上看到错误模板——它周围有一个红色边框。

在按键时验证的数字文本输入的经典问题是,如果用户键入“-”,则这不是有效的数值。如果用户将值补全为“-1”,那很好,但文本框已经合适了。

一种解决方法是为 ViewModel 提供一个 StringDValue 属性,该属性将“-”和“”视为 0,保持 DValue 属性正确更新,等等。你可以做到这一点。值转换器是有问题的,因为事情是双向的:用户键入“-”,0 返回到 ViewModel 属性,OnPropertyChanged 被触发,0 返回,文本框中出现零。我想这也是可以解决的,但这不是我在这里选择的路径。

所以问题来了:

问题是当用户键入“asdf”时会发生什么。 StringDValue 如何告诉 Binding 该值是无效输入?您是否可以抛出一些异常,绑定将捕获并将其视为非崩溃输入错误?我抛出的每个异常类型都未在绑定中捕获。

这应该是显而易见的。

答案是写一个ValidationRule, as in this answer here:

C#

public class NumericInputTextValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        var s = (value ?? "").ToString().Trim();

        double d;

        var valid = s == "-" || s == "+" || s == "" || double.TryParse(s, out d);

        if (!valid)
        {
            return new ValidationResult(false, "Not a Number");
        }

        return new ValidationResult(true, "");
    }
}

XAML

<TextBox>
    <TextBox.Text>
        <Binding Path="StringDValue" UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                <MyNS:NumericInputTextValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>