延迟验证的一种方法是在绑定中设置属性UpdateSourceTrigger=Explicit。如果您这样做,绑定将不会更新源对象,因此不会导致验证错误,直到您明确告诉绑定这样做。单击按钮时,您会强制更新绑定,对每个控件使用如下行:
someTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
然后,您的属性设置器会针对无效数据抛出异常。
如果有很多控件可以强制绑定更新,这种方法可能会有点麻烦。
此外,强制更新绑定必须在控件的代码隐藏中完成。如果您也使用带有按钮的命令,那么您可能会遇到问题。按钮可以同时具有 Command 和 Click 事件处理程序,并且两者都会在单击按钮时执行,但我不知道发生这种情况的顺序,或者即使可以保证顺序。一个快速的实验表明事件处理程序是在命令之前执行的,但我不知道这是否是未定义的行为。因此,该命令可能会在绑定更新之前被触发。
以编程方式创建验证工具提示的一种方法是绑定文本框的另一个属性,然后故意导致此绑定出错。
'sapient'posted a complete solution, including code 在 Silverlight 论坛上(搜索 2009 年 7 月 8 日下午 4:56 的帖子)。简而言之,他/她创建一个具有 getter 引发异常的属性的辅助对象,将文本框的 Tag 属性绑定到此辅助对象,然后强制更新绑定。
'sapient 的代码是在 Silverlight 4 发布之前编写的。我们会将他/她的代码“升级”到 Silverlight 4。ControlValidationHelper 类变为以下内容:
public class ControlValidationHelper : IDataErrorInfo
{
public string Message { get; set; }
public object ValidationError { get; set; }
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string columnName]
{
get { return Message; }
}
}
很容易敲出一个快速演示应用程序来尝试一下。我创建了以下三个控件:
<TextBox x:Name="tbx" Text="{Binding Path=Text, ValidatesOnDataErrors=True, NotifyOnValidationError=True, Mode=TwoWay}" />
<Button Click="ForceError_Click">Force error</Button>
<Button Click="ClearError_Click">Clear error</Button>
Text 属性和两个按钮的事件处理程序位于代码隐藏中,如下所示:
public string Text { get; set; }
private void ForceError_Click(object sender, RoutedEventArgs e)
{
var helper = new ControlValidationHelper() { Message = "oh no!" };
tbx.SetBinding(Control.TagProperty, new Binding("ValidationError")
{
Mode = BindingMode.TwoWay,
NotifyOnValidationError = true,
ValidatesOnDataErrors = true,
UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
Source = helper
});
tbx.GetBindingExpression(Control.TagProperty).UpdateSource();
}
private void ClearError_Click(object sender, RoutedEventArgs e)
{
BindingExpression b = tbx.GetBindingExpression(Control.TagProperty);
if (b != null)
{
((ControlValidationHelper)b.DataItem).Message = null;
b.UpdateSource();
}
}
“强制错误”按钮应使验证错误出现在文本框上,“清除错误”按钮应使其消失。
如果您使用的是ValidationSummary,则会出现这种方法的一个潜在缺点。 ValidationSummary 将列出所有针对 ValidationError 的验证错误,而不是针对每个属性的名称。