我有一个应用程序,我最近从VS 2008 .NET 3.5项目转换为VS2010 .NET 4项目。转换后,项目中的某些WPF对话框的行为有所不同。我想了解造成这种行为差异的原因,以便找到并修复现在可能存在问题的其他方面。
作为一个例子,我有一个MVVM对话框,允许用户输入一个数字。该数字在内部存储为double,如果用户输入的文本是有效的double,则用户只能接受该对话框。所以我有一个文本框绑定到ViewModel中的一个字符串,一个OK按钮仅在字符串是有效的double时启用。相关的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”。好像该值一旦被设置(即格式化为“G3”)就从ValueString
属性读回,但这不适用于.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” - 这个问题似乎只发生在你输入的东西会导致第三个重要数字的四舍五入。
答案 0 :(得分:5)
这种行为差异的原因是:
在3.5中,绑定会写一个新的 每次都回到源头 按键,不改变 TextBox文本。但该文本可能不会 代表来源的价值 准确地说,也许是因为它没有 包括格式和转换,或 因为来源改变了价值 (在物业设定者中)的东西 其他。这导致频繁和 激烈的抱怨 - 人们想要的 TextBox显示源代码 值,就像TextBlock那样 绑定到相同的属性与 相同的转换器和格式。用户界面 应该显示实际中的内容 数据,而不是最终用户键入的内容。
要修复4.0中的这类错误, 绑定现在应用格式和 转换为源的新值 每次更新后。 (引发LostFocus 绑定已经在3.5中做到了这一点。) TextBox现在显示数据中的内容, 但这可以使用户打字 更复杂。
我们计划改善这种情况 下一个版本至少有两种方式: 1.当TextBox文本替换为修改后的字符串时,插入 点(光标)适用于旧的 字符串可能不再正确 新的字符串。启发式的 猜猜光标可以放在哪里 改进。 2.绑定将揭示一种使用LostFocus(或Explicit)更新的方法 每次之后部分验证 按键。格式/转换 仅在焦点更改时应用, 但是用户得到了验证反馈 每次按键后。
- Sam(WPF团队)
答案 1 :(得分: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事件之后,重新评估绑定,即调用属性IS的getter,并在文本框中显示getter返回的值。