WPF验证不会在TextBox的第一个LostFocus上触发

时间:2008-09-19 16:42:21

标签: wpf validation focus

我正在尝试针对对象验证WPF表单。当我在文本框中键入内容时,验证会激活,失去焦点会回到文本框,然后删除我写的任何内容。但是,如果我只是从文本框中加载WPF应用程序和选项卡而不从文本框中写入和删除任何内容,那么它就不会被触发。

这是Customer.cs类:

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>

6 个答案:

答案 0 :(得分:18)

如果您不想在代码中添加一些逻辑,那么您可以使用以下内容处理实际的 LostFocus 事件:

<强>的.xaml

<TextBox LostFocus="TextBox_LostFocus" ....

<强> .xaml.cs

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
     ((Control)sender).GetBindingExpression(TextBox.TextProperty).UpdateSource();
}

答案 1 :(得分:8)

不幸的是,这是设计上的。仅当控件中的值发生更改时,才会触发WPF验证。

难以置信,但却是如此。到目前为止,WPF验证是一个很大的谚语 - 它很可怕。

然而,您可以做的一件事是从控件的属性中获取绑定表达式并手动调用验证。它很糟糕,但它确实有效。

答案 2 :(得分:5)

查看ValidationRule的ValidatesOnTargetUpdated属性。它将验证何时首次加载数据。如果您尝试捕获空字段或空字段,这很好。

你会像这样更新你的绑定元素:

<Binding 
    Source="{StaticResource CustomerKey}" 
    Path="LastName" 
    ValidatesOnExceptions="True" 
    ValidatesOnDataErrors="True" 
    UpdateSourceTrigger="LostFocus">
    <Binding.ValidationRules>
        <DataErrorValidationRule
            ValidatesOnTargetUpdated="True" />
    </Binding.ValidationRules>
</Binding>

答案 3 :(得分:1)

我发现处理这个问题的最好方法是在文本框的LostFocus事件中我做这样的事情

    private void dbaseNameTextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        if (string.IsNullOrWhiteSpace(dbaseNameTextBox.Text))
        {
            dbaseNameTextBox.Text = string.Empty;
        }
    }

然后它看到错误

答案 4 :(得分:0)

我遇到了同样的问题并找到了一种解决这个问题的简单方法:在窗口的Loaded事件中,只需输入txtLastName.Text = String.Empty即可。而已!!由于对象的属性已更改(已设置为空字符串),因此验证已触发!

答案 5 :(得分:0)

以下代码遍历所有控件并验证它们。不一定是首选的方式,但似乎工作。它只有TextBlocks和TextBoxes,但您可以轻松更改它。

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();
        }

    }
}

只需在您的窗口或控件上调用Validate,它就应该为您预先验证它们。