绑定在WPF中非常强大。假设我们有一个Number属性(nullable int)并绑定到一个文本框。
我意识到当它抛出错误时,该属性具有最后一个正确的值。
我的意思是这些是过程:
TEXTBOX: "" PROPERTY: null
TEXTBOX: "2" PROPERTY: 2
TEXTBOX: "2b" PROPERTY: 2 <-- here is the problem, should be null instead 2(by the error)
绑定在产生错误时是否设置了空值?
有些人告诉我我需要实现IDataErrorInfo,但我想这个接口是验证业务规则。所以我不喜欢用户。
更新:
<TextBox Text="{Binding Number, UpdateSourceTrigger=PropertyChanged,
ValidatesOnExceptions=True, ValidatesOnDataErrors=True,
NotifyOnValidationError=True, TargetNullValue={x:Static sys:String.Empty}}"
答案 0 :(得分:3)
您正在使用UpdateSourceTrigger=PropertyChanged
,这意味着只要用户点击某个键,它就会将数据存储在您的数据上下文中
例如,用户类型2
,则您的属性等于"2"
。用户类型b
,它会尝试将"2"
替换为失败的"2b"
,因此"2"
的原始属性仍然存在。
删除UpdateSourceTrigger
,它将恢复为默认值LostFocus
,这意味着它只会在TextBox失去焦点时更新属性。
您可以在产生错误时将属性设置为null
,但我不建议这样做,因为如果用户意外地点击了错误的密钥,TextBox
将被清除。
作为旁注,请使用IDataErrorInfo
进行所有验证,而不仅仅是业务规则验证。 WPF是为了与它一起工作而构建的。我的模型使用它来验证他们的数据是否正确长度,类型等,我的ViewModels使用它来验证是否遵循业务规则
修改强>
我想要的替代建议是绑定到字符串值,而不是数字字段。这样,当值发生变化时,您可以尝试将其强制转换为Int,如果无法转换则返回错误。
public class SomeObject : IDataErrorInfo
{
public string SomeString { get; set; }
public Int32? SomeNumber { get; set; }
#region IDataErrorInfo Members
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string columnName]
{
get
{
if (columnName == "SomeString")
{
int i;
if (int.TryParse(SomeString, i))
{
SomeNumber = i;
}
else
{
SomeNumber = null;
return "Value is not a valid number";
}
}
return null;
}
}
#endregion
}
答案 1 :(得分:1)
我认为获得该行为的最简单方法是使用IValueConverter
将string
转换为int?
:
public class NullableIntConverter : IValueConverter
{
public static NullableIntConverter Instance = new NullableIntConverter();
public void ConvertBack(object value, ...)
{
int intValue = 0;
if (int.TryParse((string)value, out intValue))
return intValue;
return null;
}
public void Convert(object value, ...)
{
return value.ToString();
}
}
然后你可以在你的绑定中指定这个,如下所示(local
映射到你的转换器命名空间):
<TextBox Text="{Binding Number, Converter="{x:Static local:NullableIntConverter.Instance}" ... />
答案 2 :(得分:0)
它变得更强大了。您可能应该通过接口/绑定本身进行验证 - WPF内置了对此的支持,其中的示例可以在Data Binding Overview over at MSDN中找到。
实现这一点的一个例子如下:
<...>
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</...>
链接文档涵盖了绑定主题,所以这里是相关部分“数据验证”的摘录:
ValidationRule
对象检查属性的值是否为 有效的。
ExceptionValidationRule
检查在此期间抛出的异常 更新绑定源属性。在前面的例子中, StartPrice的类型为整数。当用户输入一个值时 无法转换为整数,抛出异常,导致 绑定被标记为无效。设置的另一种语法ExceptionValidationRule
显式是设置ValidatesOnExceptions
或Binding
属性为MultiBinding
{{1}}对象。