WPF验证未在文本框的第一个失去焦点时触发
我正在尝试针对一个对象验证WPF表单。当我在文本框中键入内容失去焦点,返回文本框,然后删除我所写的内容时,将触发验证。但是,如果我只是加载WPF应用程序并在文本框中添加tab,而没有写入和删除文本框中的任何内容,那么它就不会被触发 下面是Customer.cs类:WPF验证未在文本框的第一个失去焦点时触发,wpf,validation,focus,Wpf,Validation,Focus,我正在尝试针对一个对象验证WPF表单。当我在文本框中键入内容失去焦点,返回文本框,然后删除我所写的内容时,将触发验证。但是,如果我只是加载WPF应用程序并在文本框中添加tab,而没有写入和删除文本框中的任何内容,那么它就不会被触发 下面是Customer.cs类: public class Customer : IDataErrorInfo { public string FirstName { get; set; } public string Last
public class Customer : IDataErrorInfo
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string columnName]
{
get
{
string result = null;
if (columnName.Equals("FirstName"))
{
if (String.IsNullOrEmpty(FirstName))
{
result = "FirstName cannot be null or empty";
}
}
else if (columnName.Equals("LastName"))
{
if (String.IsNullOrEmpty(LastName))
{
result = "LastName cannot be null or empty";
}
}
return result;
}
}
}
以下是WPF代码:
<TextBlock Grid.Row="1" Margin="10" Grid.Column="0">LastName</TextBlock>
<TextBox Style="{StaticResource textBoxStyle}" Name="txtLastName" Margin="10"
VerticalAlignment="Top" Grid.Row="1" Grid.Column="1">
<Binding Source="{StaticResource CustomerKey}" Path="LastName"
ValidatesOnExceptions="True" ValidatesOnDataErrors="True"
UpdateSourceTrigger="LostFocus"/>
</TextBox>
LastName
不幸的是,这是出于设计。WPF验证仅在控件中的值已更改时激发
难以置信,但这是真的。到目前为止,WPF验证是众所周知的一大难题——这太可怕了
但是,您可以做的一件事是从控件的属性获取绑定表达式并手动调用验证。这很糟糕,但很有效 我也遇到了同样的问题,并找到了一种非常简单的解决方法:在窗口的已加载事件中,只需将txtLastName.Text=String.Empty放入。就这样!!由于对象的属性已更改(已设置为空字符串),因此将触发验证 看看ValidationRule的属性。它将在首次加载数据时进行验证。如果您试图捕获空字段或空字段,这是很好的 您将更新绑定元素,如下所示:
<Binding
Source="{StaticResource CustomerKey}"
Path="LastName"
ValidatesOnExceptions="True"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="LostFocus">
<Binding.ValidationRules>
<DataErrorValidationRule
ValidatesOnTargetUpdated="True" />
</Binding.ValidationRules>
</Binding>
如果您不反对在代码中添加一点逻辑,您可以使用以下方法处理实际的LostFocus事件:
<Binding
Source="{StaticResource CustomerKey}"
Path="LastName"
ValidatesOnExceptions="True"
ValidatesOnDataErrors="True"
UpdateSourceTrigger="LostFocus">
<Binding.ValidationRules>
<DataErrorValidationRule
ValidatesOnTargetUpdated="True" />
</Binding.ValidationRules>
</Binding>
.xaml
<TextBox LostFocus="TextBox_LostFocus" ....
下面的代码在所有控件上循环并验证它们。不一定是首选方式,但似乎有效。它只做文本块和文本框,但你可以很容易地改变它
public static class PreValidation
{
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
public static void Validate(DependencyObject depObj)
{
foreach(var c in FindVisualChildren<FrameworkElement>(depObj))
{
DependencyProperty p = null;
if (c is TextBlock)
p = TextBlock.TextProperty;
else if (c is TextBox)
p = TextBox.TextProperty;
if (p != null && c.GetBindingExpression(p) != null) c.GetBindingExpression(p).UpdateSource();
}
}
}
公共静态类预验证
{
公共静态IEnumerable FindVisualChildren(DependencyObject depObj),其中T:DependencyObject
{
if(depObj!=null)
{
for(int i=0;i
只要在窗口或控件上调用Validate,它就会为您预先验证它们。我发现处理此问题的最佳方法是在文本框的LostFocus事件上执行类似操作
private void dbaseNameTextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(dbaseNameTextBox.Text))
{
dbaseNameTextBox.Text = string.Empty;
}
}
然后它会看到一个错误谢谢,但该解决方案不可扩展,很难在所有页面上维护!如果使用reflector进行检查,您将看到DataErrorValidationRule已将“ValidateOnTargetUpdated”属性设置为true。它使用指定此参数的参数调用继承的构造函数。因此,如图所示添加属性指定不会产生任何影响。好主意-我一直在尝试解决一个类似的问题,这看起来很有希望。这对我来说是一个自定义规则!谢谢你,老兄!这是一个答案,还是你在试图寻求帮助解决你遇到的问题?不幸的是,这可以应用于MVVM逻辑。当您不想修改隐藏的代码时,有没有关于如何执行此操作的提示?我认为视图中的代码“专为视图”在MVVM中与viewmodel没有关系是可以的。