Coerce a WPF TextBox not working anymore in .NET 4.0

你离开我真会死。 提交于 2019-11-26 11:38:32

问题


In my WPF application I have a TextBox where the user can enter a percentage (as int, between 1 and 100). The Text property is databound to a property in a ViewModel, where I coerce the value to be in the given range in the setter.

However, in .NET 3.5, the data is not shown properly in the UI after being coerced. In this post on MSDN, Dr. WPF states that you have to manually update the binding so the correct will be shown. Therefore, I have a TextChanged handler (in the View) which calls UpdateTarget(). In code:

View XAML:

<TextBox Text=\"{Binding Percentage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, TargetNullValue={x:Static sys:String.Empty}}\"
    TextChanged=\"TextBox_TextChanged\"/>

View codebehind:

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    // Removed safe casts and null checks
    ((TextBox)sender).GetBindingExpression(TextBox.TextProperty).UpdateTarget();
}

ViewModel:

private int? percentage;
public int? Percentage
{
    get
    {
        return this.percentage;
    }

    set
    {
        if (this.Percentage == value)
        {
            return;
        }

        // Unset = 1
        this.percentage = value ?? 1;

        // Coerce to be between 1 and 100.
        // Using the TextBox, a user may attempt setting a larger or smaller value.
        if (this.Percentage < 1)
        {
            this.percentage = 1;
        }
        else if (this.Percentage > 100)
        {
            this.percentage = 100;
        }
        this.NotifyPropertyChanged(\"Percentage\");
    }
}

Unfortunately, this code breaks in .NET 4.0 (same code, simply changed TargetFramework to 4.0). Specifically, after I coerced the value for the first time, the TextBox ignores any further coerced values as long as I continue to enter integer values (since I am binding to an int).

So if I enter \"123\", after the 3 I see the value \"100\". Now if I enter \"4\", the setter in the ViewModel gets the value \"1004\", which it coerces to 100. The TextChanged event then fires (and the sender\'s TextBox.Text is \"100\"!), but the TextBox shows \"1004\". If I then enter \"5\", the setter gets the value \"10045\", etc.

If I then enter an \"a\", suddenly the TextBox shows the correct value, i.e. \"100\". The same occurs if I continue to enter numbers until the int overflows.

How can I fix this?


回答1:


Try using in xaml Explicit instead of PropertyChanged:

<TextBox Text="{Binding Percentage, Mode=TwoWay, UpdateSourceTrigger=Explicit, TargetNullValue={x:Static System:String.Empty}}"
             TextChanged="TextBox_TextChanged" />

and in code behind UpdateSource instead of UpdateTarget

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        // Removed safe casts and null checks
        ((TextBox)sender).GetBindingExpression(TextBox.TextProperty).UpdateSource();
    }

Tested it and it works. Btw this problem will probably be resolved in a later version of .NET.




回答2:


You can use PropertyChanged. However, try binding to the EditValueProperty dependency instead of the TextProperty dependency (or events). It will work as desired.



来源:https://stackoverflow.com/questions/3905227/coerce-a-wpf-textbox-not-working-anymore-in-net-4-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!