为什么绑定设置在.NET 4和.NET 3.5中的行为不同 [英] Why does binding setup behave differently in .NET 4 vs .NET 3.5

查看:156
本文介绍了为什么绑定设置在.NET 4和.NET 3.5中的行为不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个最近从VS 2008 .NET 3.5项目转换到VS2010 .NET 4项目的应用程序。项目中的一些WPF对话框在转换后表现不同。我想了解导致行为差异的原因,因此我可以找到并修复现在可能有问题的其他方面。



例如,我有一个MVVM对话框,让用户输入数字。该数字在内部存储为双精度,用户只能接受对话框,如果他们键入的文本是有效的双。所以我有一个文本框绑定到一个字符串在ViewModel,和一个确定按钮,只有当字符串是有效的双精度时启用。相关的Xaml看起来像这样:

 < TextBox Text ={Binding ValueString,UpdateSourceTrigger = PropertyChanged}/> 
< Button IsEnabled ={Binding ValueIsValid}>确定< / Button>

ViewModel看起来像:

  class ViewModel:INotifyPropertyChanged 
{
private double actualValue;
public string ValueString
{
get {return actualValue.ToString(G3); }
set
{
double doubleValue;
if(double.TryParse(value,NumberStyles.Float,CultureInfo.CurrentCulture,out doubleValue))
{
actualValue = doubleValue;
ValueIsValid = true;
RaisePropertyChanged(ValueString);
}
else
{
ValueIsValid = false;
}
}
}

private bool valueIsValid = true;
public bool ValueIsValid
{
get {return valueIsValid; }
set
{
if(valueIsValid!= value)
{
valueIsValid = value;
RaisePropertyChanged(ValueIsValid);
}
}
}

private void RaisePropertyChanged(string property)
{
if(PropertyChanged!= null)
{
PropertyChanged(this,new PropertyChangedEventArgs(property));
}
}

公共事件PropertyChangedEventHandler PropertyChanged;
}

这在.NET 3.5中工作得很好,但是当它在.NET 4上运行时它在用户输入数字时有问题。例如,如果用户在.NET 3.5版本的文本框中输入3.05555,一切都很好。但是在.NET 4版本中,他们可以输入3.05很好,但是当他们键入下一个5时,文本框的值更改为3.06,然后更改为3.07,如果他们再次按5。这就好像从$ ValueString 属性读取的值一旦被设置(因此被格式化为G3),但这没有使用发生在.NET 3.5。



我看过 .NET Framework 4中的新增功能(包括 WPF版本4的新增功能),但我没有找到任何关于此更改的信息。



如果您想查看自己,我创建了一个小例子VS2010解决方案,您可以从这里下载。 BindingTest2008项目已从VS 2008转换为目标.NET 3.5,BindingTest2010项目在VS 2010中针对.NET 4.创建。两个项目的代码是相同的,但是.NET 4项目有这个问题。 p>

我会感谢任何帮助,了解为什么会发生这种情况。
感谢。



更新:删除调用 RaisePropertyChanged(ValueIsValid); 不改变行为并键入无效数字(例如3.1a)不会被最后一个有效数字替换(例如在这种情况下为3.1)。此外,可以输入比3个有效数字更高的精度的数字。例如。 3.0545555 - 只有当你输入的内容会导致第三个有效数字的四舍五入时,这个问题才会出现。

解决方案

这种行为差异的原因是:


在3.5中,绑定会将新的
值写回源在每个
后敲击,而不改变
TextBox文本。但是该文本可能不会
准确地表示源的值
,也许因为它不
包括格式化和转换,或者
,因为源改变了值
在属性设置器中)到
else。这导致频繁和
强烈的投诉 - 人们想要
TextBox显示源的
值,正如一个TextBlock如果
绑定到相同的属性与
相同的转换器和格式。 UI
应该显示
数据中的实际内容,而不是最终用户键入的内容。



要修复这个类的bug,
绑定现在在每次更新之后将格式化和
转换应用到源的新值
。 (LostFocus
绑定在3.5中已经做到了)
TextBox现在显示数据
中的内容,但是这会使用户键入
更复杂。



我们计划在下一个版本中以至少两种方式改进这个场景:
1.当TextBox文本被替换为修改的字符串时,插入
点(光标)为旧的
字符串工作可能不再正确的
新的字符串。启发式,
猜测在何处放置光标可以改进

2.绑定将暴露一种方法来做每个
按键之后的
部分验证的LostFocus(或显式)更新。格式化/转换
仅在焦点更改时应用,
,但用户在每次击键后获得验证反馈




  • Sam(WPF小组)




< //connect.microsoft.com/VisualStudio/feedback/details/588343/changed-behaviour-from-net-3-5-to-net-4-0-of-wpf-textbox-formatting-when-propertychanged-is- used-as-updatesourcetrigger>将PropertyChanged用作UpdateSourceTrigger时,将行为从.Net 3.5更改为WPF TextBox格式的.Net 4.0


I have an app I've recently converted from a VS 2008 .NET 3.5 project, to a VS2010 .NET 4 project. Some of the WPF dialogs in the project behave differently after the conversion. I'd like to understand what is causing this difference in behaviour, so I can find and fix other areas that may now have problems.

As an example, I have a MVVM dialog that lets the user type in a number. The number is stored internally as a double, and the user can only accept the dialog if the text they type is a valid double. So I have a text box bound to a string in the ViewModel, and an OK button which is only enabled when the string is a valid double. The relevant Xaml looks like this:

<TextBox Text="{Binding ValueString, UpdateSourceTrigger=PropertyChanged}"/>
<Button IsEnabled="{Binding ValueIsValid}">OK</Button>

And the ViewModel looks like:

class ViewModel : INotifyPropertyChanged
{
    private double actualValue;
    public string ValueString
    {
        get { return actualValue.ToString("G3"); }
        set
        {
            double doubleValue;
            if (double.TryParse(value, NumberStyles.Float, CultureInfo.CurrentCulture, out doubleValue))
            {
                actualValue = doubleValue;
                ValueIsValid = true;
                RaisePropertyChanged("ValueString");
            }
            else
            {
                ValueIsValid = false;
            }
        }
    }

    private bool valueIsValid = true;
    public bool ValueIsValid
    {
        get { return valueIsValid; }
        set
        {
            if (valueIsValid != value)
            {
                valueIsValid = value;
                RaisePropertyChanged("ValueIsValid");
            }
        }
    }

    private void RaisePropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

This worked fine in .NET 3.5, but when it's running on .NET 4 it has a problem when the user is entering a number. For example, if the user enters "3.05555" into the text box on the .NET 3.5 version, everything is fine. However in the .NET 4 version, they can enter 3.05 fine but when they type the next "5" the value of text box changes to "3.06" and then changes to "3.07" if they press 5 again. It's as if the value is being read-back from the ValueString property as soon as it has been set (thus being formatted as "G3"), but this didn't used to happen with .NET 3.5.

I've had a look over What's New in the .NET Framework 4 (including What's New in WPF Version 4), but I didn't find anything about this change.

If you want to see this for yourself, I've created a small example VS2010 solution you can download from here. The BindingTest2008 project has been converted from VS 2008 and targets .NET 3.5, and the BindingTest2010 project was created in VS 2010 targeting .NET 4. The code is the same in both projects, but the .NET 4 project has this problem.

I'd appreciate any help on understanding why this is happening. Thanks.

Updated: Removing the call the RaisePropertyChanged("ValueIsValid"); doesn't change the behaviour and typing an invalid number (e.g. "3.1a") doesn't intermediately get replaced by the last valid number (e.g. "3.1" in that case). Also numbers can be entered to a higher precision than 3 significant digits. E.g. "3.0545555" - the problem only seems to happen when the thing you've just typed would cause a rounding on the 3rd significant figure.

解决方案

The reason for this behaviour difference is:

In 3.5, the binding would write a new value back to the source after each keystroke, without changing the TextBox text. But that text might not represent the source's value accurately, perhaps because it doesn't include formatting and conversion, or because the source changed the value (in the property-setter) to something else. This led to frequent and vehement complaints - people wanted the TextBox to show the source's value, exactly as a TextBlock would if bound to the same property with the same converters and formatting. The UI should display what's actually in the data, not what the end-user typed.

To fix this class of bugs in 4.0, the binding now applies formatting and conversion to the source's new value after every update. (LostFocus bindings already did this in 3.5.) The TextBox now shows what's in the data, but that can make the user's typing more complex.

We plan to improve this scenario in the next release in at least two ways: 1. When the TextBox text is replaced with a revised string, the insertion point (cursor) that worked for the old string may no longer be correct for the new string. The heuristic that guesses where to put the cursor can be improved. 2. Bindings will expose a way to do LostFocus (or Explicit) updates with partial validation after each keystroke. The formatting/conversion only gets applied when focus changes, but the user gets validation feedback after every keystroke.

  • Sam (WPF team)

From "Changed behaviour from .Net 3.5 to .Net 4.0 of WPF TextBox formatting when PropertyChanged is used as UpdateSourceTrigger"

这篇关于为什么绑定设置在.NET 4和.NET 3.5中的行为不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆