WPF验证是在获得焦点时启动的

时间:2015-01-23 10:14:23

标签: wpf validation xaml idataerrorinfo

我正在开发一个IDataErrorInfo来验证我的应用程序中的文本框。我有以下代码:

要验证的.cs类:

 public class UserInformation : IDataErrorInfo
{
    public string _name;
    public string _surname;

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public string Surname
    {
        get { return _surname; }
        set { _surname = value; }
    }

    public override string  ToString()
    {
        return Name + " " + Surname;
    }

    public string this[string columnName]
    {
        get
        {
            if (columnName == null) return string.Empty;
            string result = string.Empty;
            if (columnName.Equals("Name"))
            {
                if (string.IsNullOrEmpty(_name))
                    result = "Name cannot be empty.";
            }
            return result;
        }
    }

    public string Error { get; private set; }
}

.xaml:

<TextBox Grid.Column="3" Grid.Row="0" Name="TextBoxName" 
        Style="{DynamicResource InnerTextBox}" 
        Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}">
        <TextBox.Text>
              <Binding Path="Name" Source="{StaticResource UserInformation}" 
                      ValidatesOnDataErrors="True" UpdateSourceTrigger="PropertyChanged">
                 <Binding.ValidationRules>
                       <ExceptionValidationRule />
                  </Binding.ValidationRules>
                </Binding>
         </TextBox.Text>
      </TextBox>

ErrorTemplate

<ControlTemplate x:Key="ValidationErrorTemplate">
    <DockPanel >
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
            <Grid Width="20" Height="20">
                <Ellipse Width="20" Height="20" Fill="Tomato" HorizontalAlignment="Center" VerticalAlignment="Center" />
                <TextBlock Foreground="White" FontWeight="Heavy" FontSize="8" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center"
                   ToolTip="{Binding ElementName=ErrorAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">X</TextBlock>
            </Grid>
            <TextBlock Foreground="Tomato" FontWeight="12" Margin="2,0,0,0" FontSize="20"
                       Text="{Binding ElementName=ErrorAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
        </StackPanel>
        <AdornedElementPlaceholder x:Name="ErrorAdorner" />
    </DockPanel>
</ControlTemplate>

我打字时代码工作正常。但加载TextBox时,验证也会发生。我不希望它在获得焦点时发生,只有当它失去它或我改变文本时(就像在这里发布的那样)。

如何避免在第一次TextBox加载时考虑验证错误?

注意:即使我将UpdateSourceTrigger设置为 LostFocus ,它仍然会进行验证。

2 个答案:

答案 0 :(得分:3)

为了实现你的目标,你需要:

首先,删除绑定上的ValidatesOnDataErrors="True"。如docs中所述:

  

设置此属性提供了使用该属性的替代方法   DataErrorValidationRule元素显式

我们会明确地使用它。然后使用DataErrorValidationRule代替ExceptionValidationRule正确使用IDataErrorInfo和数据错误。

最后,我们需要使用此规则为我们提供的一些属性:

<Binding.ValidationRules>
    <DataErrorValidationRule ValidatesOnTargetUpdated="False" />
</Binding.ValidationRules>
如果目标本身发生变化(即加载时),

ValidatesOnTargetUpdated on false将不会触发验证。您还可以使用ValidationStep属性进行其他控制。

修改
好的,我发现您需要在加载时跳过验证,即使值未更改,您也需要验证丢失的焦点。好吧,验证规则不支持这一点,因为如果值没有更新,那么无论UpdateSourceTrigger设置如何,都不会调用更改的事件并且不会进行验证。
简单的方法是通过向TextBox本身添加LostFocus处理程序来模拟此功能:

 private void ValidatedTextBox_LostFocus(object sender, RoutedEventArgs e)
 {
     var txt = (TextBox)sender;
     txt.GetBindingExpression(TextBox.TextProperty).UpdateSource();
 }

如果您需要多个TextBox,则可以将代码移动到某个静态类。
使用Explicit update source trigger可以获得相同的结果,可以更清洁一些。

答案 1 :(得分:0)

我没有任何示例atm,因为我移动到你拥有的东西。但是您需要创建一个类,该类将继承自System.windows.controls中存在的ValidationRule,然后重写Validate方法。

然后你的xaml文本框看起来像这样

 <TextBox.Text>
<Binding Path="your binding here"    UpdateSourceTrigger="LostFocus" >
  <Binding.ValidationRules>
    <validationClass:yourRule/>  define this at the top of xaml page
  </Binding.ValidationRules>
</Binding>

您应该能够在msdn上找到示例,这里有关于验证规则的信息