【问题标题】:Why does binding setup behave differently in .NET 4 vs .NET 3.5为什么绑定设置在 .NET 4 和 .NET 3.5 中的行为不同
【发布时间】:2011-01-17 12:02:06
【问题描述】:

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

例如,我有一个 MVVM 对话框,让用户输入一个数字。该数字在内部存储为双精度数,如果用户键入的文本是有效的双精度数,则用户只能接受该对话框。所以我有一个文本框绑定到 ViewModel 中的一个字符串,以及一个仅在字符串为有效双精度时才启用的 OK 按钮。相关的 Xaml 如下所示:

<TextBox Text="{Binding ValueString, UpdateSourceTrigger=PropertyChanged}"/>
<Button IsEnabled="{Binding ValueIsValid}">OK</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));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

这在 .NET 3.5 中运行良好,但是当它在 .NET 4 上运行时,当用户输入数字时会出现问题。例如,如果用户在 .NET 3.5 版本的文本框中输入“3.05555”,则一切正常。但是在 .NET 4 版本中,他们可以正常输入 3.05,但是当他们键入下一个“5”时,文本框的值会变为“3.06”,如果再次按 5,则会变为“3.07”。就好像该值在设置后立即从 ValueString 属性中读回(因此被格式化为“G3”),但这在 .NET 3.5 中不会发生。

我查看了What's New in the .NET Framework 4(包括What's New in WPF Version 4),但没有发现任何有关此更改的信息。

如果您想亲眼看看,我创建了一个小示例 VS2010 解决方案,您可以download from here。 BindingTest2008项目是从VS 2008转换而来,面向.NET 3.5,而BindingTest2010项目是在VS 2010中针对.NET 4创建的。两个项目的代码是一样的,但是.NET 4项目有这个问题。

如果能帮助我理解为什么会发生这种情况,我将不胜感激。 谢谢。

更新:删除RaisePropertyChanged("ValueIsValid"); 的调用不会改变行为并且输入无效数字(例如“3.1a”)不会中间被最后一个有效数字替换(例如在这种情况下为“3.1”)。数字也可以输入到比 3 位有效数字更高的精度。例如。 “3.0545555” - 问题似乎只发生在您刚刚输入的内容会导致第三位有效数字舍入时。

【问题讨论】:

    标签: c# wpf xaml c#-4.0


    【解决方案1】:

    造成这种行为差异的原因是:

    在 3.5 中,绑定会写一个新的 每次后返回源值 击键,不改变 文本框文本。但该文本可能不会 代表来源的价值 准确地说,也许是因为它没有 包括格式和转换,或 因为来源改变了价值 (在属性设置器中)到某事 别的。这导致频繁和 强烈的抱怨——人们想要 显示源的文本框 值,与 TextBlock 完全一样,如果 绑定到相同的属性与 相同的转换器和格式。用户界面 应该显示实际在 数据,而不是最终用户键入的内容。

    为了在 4.0 中修复此类错误, 绑定现在应用格式和 转换为源的新值 每次更新后。 (失去焦点 绑定在 3.5 中已经这样做了。) TextBox 现在显示数据中的内容, 但这会使用户的打字 更复杂。

    我们计划在 下一个版本至少有两种方式: 1.当TextBox文本替换为修改后的字符串时,插入 适用于旧的点(光标) 字符串可能不再正确 新字符串。启发式 猜测光标可以放在哪里 改善。 2. 绑定将公开一种方法来进行 LostFocus(或显式)更新 每次之后的部分验证 击键。格式化/转换 仅在焦点更改时应用, 但用户得到验证反馈 每次击键后。

    • Sam(WPF 团队)

    来自“Changed behaviour from .Net 3.5 to .Net 4.0 of WPF TextBox formatting when PropertyChanged is used as UpdateSourceTrigger

    【讨论】:

    • 我们到了,4.5 已经发布,行为没有改善,也没有真正的替代方案。至少可以说,编辑行为很奇怪。也许是时候回滚这个变化了?
    【解决方案2】:

    看起来问题出在这一行:

     get { return actualValue.ToString("G3"); }
    

    .Net 4 版本的行为正确,因为该值使用“G3”格式字符串进行格式化,这意味着结果字符串中将有 3 个有效数字(3.055 变为 3.06)。

    3.5 和 4 的区别在于,显然绑定系统略有改变。在 3.5 中,当调用属性的 setter 并引发 PropertyChanged 事件时,不会重新评估绑定(不调用 getter)。而在 .Net 4 中,PropertyChanged 事件被触发后,绑定被重新评估,即调用属性的 getter,并且 getter 返回的值显示在文本框中。

    【讨论】:

    • 正确的是,舍入的原因是由于 get 方法中的格式(我确实想要,因此当您第一次打开对话框时,该值显示为 3 个表示数字)。但是,即使我删除了对 RaisePropertyChanged 的​​调用,问题仍然会发生。
    • 是的,RaisePropertyChanged 没有任何区别。绑定系统就是这样工作的——它从源中刷新值。您可以通过将绑定的 UpdateSourceTrigger 更改为 LostFocus 来实现所需的行为。
    • 如果它总是从源中刷新值,那么这是否也意味着如果我输入“a”它会用最后一个有效数字替换它?视为源仅存储最后一个有效数字。
    • 它不会用旧的有效数字替换文本框中的文本,因为getter返回的属性值没有改变。绑定系统会缓存该值,并且不会不必要地更新 UI。
    • 啊,是的 - 我没有考虑缓存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 2014-03-11
    • 2011-07-04
    • 2012-07-13
    • 1970-01-01
    • 2012-02-20
    相关资源
    最近更新 更多