WPF验证不在文本框的第一个LostFocus上触发

时间:2020-03-06 14:26:53  来源:igfitidea点击:

我正在尝试针对一个对象验证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>

解决方案

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

令人难以置信,但事实如此。到目前为止,WPF验证是众所周知的巨大痛苦。

但是,我们可以做的一件事是从控件的属性中获取绑定表达式,然后手动调用验证。它很烂,但是有效。

我经历了同样的问题,找到了一种解决此问题的超简单方法:在窗口的Loaded事件中,只需将txtLastName.Text = String.Empty放进去。而已!!由于对象的属性已更改(设置为空字符串),因此验证生效!

看一下ValidationRule的ValidatesOnTargetUpdated属性。它将验证何时首次加载数据。如果我们尝试捕获空字段或者空字段,则很好。

我们将像这样更新绑定元素:

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

如果我们不反对在代码中添加一些逻辑,则可以使用以下类似的方法处理实际的LostFocus事件:

.xaml

<TextBox LostFocus="TextBox_LostFocus" ....

.xaml.cs

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