当绑定属性强制执行某些业务规则时,绑定 WPF TextBox 不会更新值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22307554/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 11:10:24  来源:igfitidea点击:

Bound WPF TextBox is not updating value when the bound property enforces some business rules

c#wpf.net-4.0inotifypropertychanged

提问by Matt Zappitello

I am using .NET 4.0. I have some very simple code that lets the user type in a number between 1 and 99,999 (inclusive). I have some logic in the Property setter that prevents the latest value from being applied if it does not adhere to the business rules (e.g., it is not a number or the number is too large).

我正在使用 .NET 4.0。我有一些非常简单的代码,可以让用户输入 1 到 99,999(含)之间的数字。我在属性设置器中有一些逻辑,如果它不符合业务规则(例如,它不是一个数字或数字太大),它会阻止应用最新的值。

    public class MainViewModel : INotifyPropertyChanged
{
    #region Fields

    private string _text = string.Empty;

    #endregion // Fields

    #region Properties

    public string Text
    {
        get { return _text; }

        set
        {
            if (_text == value) return;

            if (IsValidRange(value))
            {
                _text = value;
            }

            OnPropertyChanged("Text");
        }
    }

    #endregion // Properties

    #region Private Methods

    private bool IsValidRange(string value)
    {
        // An empty string is considered valid.
        if (string.IsNullOrWhiteSpace(value)) return true;

        // We try to convert to an unsigned integer, since negative bill numbers are not allowed,
        // nor are decimal places.
        uint num;
        if (!uint.TryParse(value, out num)) return false;

        // The value was successfully parse, so we know it is a non-negative integer.  Now, we
        // just need to make sure it is in the range of 1 - 99999, inclusive.
        return num >= 1 && num <= 99999;
    }

    #endregion // Private Methods

    #region INotifyPropertyChanged Implementation

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion // INotifyPropertyChanged Implementation
}

The problem I am running into is that when the value is not valid and I just ignore the value, the TextBox bound to this property does not update to reflect that change; rather, it just retains the value as it is typed in. Here is how I have the property bound:

我遇到的问题是,当该值无效而我只是忽略该值时,绑定到此属性的 TextBox 不会更新以反映该更改;相反,它只是保留输入的值。这是我如何绑定属性:

        <TextBox Grid.Row="0"
             Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>

Can anyone tell me what I'm doing wrong?

谁能告诉我我做错了什么?

I have read a lot of questions that seemed very similar to this, but none of the answers worked for me. The weird thing is that when I don't validate based on numbers, but just change all text typed in to be upper case, it works just fine. It just seems to not work when I try to not set the Property to the new value.

我已经阅读了很多与此非常相似的问题,但没有一个答案对我有用。奇怪的是,当我不根据数字进行验证,而只是将所有输入的文本更改为大写时,它就可以正常工作。当我尝试不将属性设置为新值时,它似乎不起作用。

回答by Matt

This seems to be a bug with the TextBoxin .NET 3.5-4.0. I first tried this in 4.5 and your code worked as written, but when I converted the project to 4.0, I could reproduce the issue. After doing some searching, I found:

这似乎是TextBox.NET 3.5-4.0 中的一个错误。我第一次在 4.5 中尝试了这个,并且您的代码按编写的方式工作,但是当我将项目转换为 4.0 时,我可以重现该问题。经过一番搜索,我发现:

WPF Textbox refuses to update itself while binded to a view model property, which details a workaround that references:

WPF 文本框在绑定到视图模型属性时拒绝更新自身,该属性详细介绍了引用的解决方法:

Textbox getting out of sync with viewmodel property.

文本框与 viewmodel 属性不同步

Of course if it's possible for you to use .NET 4.5 I'd suggest that, but of course it's not always as easy as that.

当然,如果您可以使用 .NET 4.5,我建议您这样做,但当然并不总是那么容易。