如何在WPF中使用Binding进行验证TextBox,在无效输入后切换回上一个有效值?

axa*_*npi 5 c# validation wpf binding mvvm

WPF,我想做一个TextBox验证用户输入只允许输入解析为double的输入.当盒子失去焦点(和Binding更新)时,如果用户输入了无效输入,我希望盒子切换回之前的状态.

这似乎应该很简单,但我无法让它工作.无论我尝试过什么,TextBox继续显示用户输入的无效字符串,即使属性正确验证输入而不保存除非有效.我觉得通知在失败的解析上更改属性会导致TextBox重置为旧值,但事实并非如此.

我的视图模型有一个属性:

private double _doubleDisplayValue;
public string DoubleDisplayValue
{
    get { return _doubleDisplayValue.ToString(); }
    set
    {
        double result;
        bool success = double.TryParse(value, out result);
        if(success)
        {
            if(_doubleDisplayValue != result)
            {
                _doubleDisplayValue = result;
                NotifyPropertyChanged("DoubleDisplayValue");
            }
        }
        else
        {
            // I feel like notifying property changed here should make the TextBox
            // update back to the old value (still in the backing variable), but
            // it just keeps whatever invalid string the user entered.
            NotifyPropertyChanged("DoubleDisplayValue");
        }
    }   
}
Run Code Online (Sandbox Code Playgroud)

我设置了我TextBox(我正在使用代码):

// . . .
TextBox textBox = new TextBox();
Binding b = new Binding("DoubleDisplayValue");
b.Mode = BindingMode.TwoWay;
// assume the DataContext is properly set so the Binding has the right source
textBox.SetBinding(TextBox.TextProperty, b);
// . . .
Run Code Online (Sandbox Code Playgroud)

我也尝试将属性修改为此,但它仍然无效:

private double _doubleDisplayValue;
public string DoubleDisplayValue
{
    get { return _doubleDisplayValue.ToString(); }
    set
    {
        double result;
        bool success = double.TryParse(value, out result);
        if(success)
        {
            // got rid of the if
            _doubleDisplayValue = result;
            NotifyPropertyChanged("DoubleDisplayValue");                
        }
        else
        {
            // Figured maybe I need to retrigger the setter
            DoubleDisplayValue = _doubleDisplayValue;
        }
    }   
}
Run Code Online (Sandbox Code Playgroud)

实现目标的最佳方法是什么?

Scr*_*og1 4

如果您确实想重置 TextBox 中显示的值,则必须在 DoubleDisplayValue 的 setter 中执行以下操作:

Application.Current.Dispatcher.BeginInvoke(new Action(() =>
    {
        _doubleDisplayValue = originalValue;
        NotifyPropertyChanged("DoubleDisplayValue");
    }), DispatcherPriority.ContextIdle, null);
Run Code Online (Sandbox Code Playgroud)