第一次加载时的验证绑定

one*_*ill 11 validation wpf binding

我仍在努力进行WPF验证.

我有一个自定义验证规则,要求文本出现在文本框中,即它强制执行强制字段约束.

<TextBox local:Masking.Mask="^[a-zA-Z0-9]*$" x:Name="CameraIdCodeTextBox" Grid.Row="1" Grid.Column="1">
  <Binding Path="CameraIdCode" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True" ValidatesOnExceptions="True">
    <Binding.ValidationRules>
      <localValidation:RequiredFieldRule />
    </Binding.ValidationRules>
  </Binding>
</TextBox>
Run Code Online (Sandbox Code Playgroud)

问题是,当Window首次加载时,TextBox中没有文本(正如您所期望的那样).但是Text属性被绑定到ViewModel上的属性,因此,验证规则正在触发,表明Window存在问题 - 在用户甚至有机会违反业务规则之前.

这是一个以前解决过的问题吗?我不可能是第一个体验这一点.我敢肯定这对年轻球员来说是一个陷阱.

one*_*ill 0

已经有一段时间了,我应该更新这个问题。我使用 Ian Griffths 的 WPF 书中(O'Reilly 的书)中找到的一个类解决了这个问题:

public static class Validator
{
    /// <summary>
    /// This method forces WPF to validate the child controls of the control passed in as a parameter.
    /// </summary>
    /// <param name="parent">Type: DependencyObject. The control which is the descendent root control to validate.</param>
    /// <returns>Type: bool. The validation result</returns>
    public static bool IsValid(DependencyObject parent)
    {
        // Validate all the bindings on the parent
        bool valid = true;
        LocalValueEnumerator localValues = parent.GetLocalValueEnumerator();
        while (localValues.MoveNext())
        {
            LocalValueEntry entry = localValues.Current;
            if (BindingOperations.IsDataBound(parent, entry.Property))
            {
                Binding binding = BindingOperations.GetBinding(parent, entry.Property);
                foreach (ValidationRule rule in binding.ValidationRules)
                {
                    ValidationResult result = rule.Validate(parent.GetValue(entry.Property), null);
                    if (!result.IsValid)
                    {
                        BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property);
                        Validation.MarkInvalid(expression, new ValidationError(rule, expression, result.ErrorContent, null));
                        valid = false;
                    }
                }
            }
        }

        // Validate all the bindings on the children
        for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
        {
            DependencyObject child = VisualTreeHelper.GetChild(parent, i);
            if (!IsValid(child))
            {
                valid = false;
            }
        }

        return valid;
    }

}
Run Code Online (Sandbox Code Playgroud)

然后,在视图上,我有以下配置:

<TextBox local:Masking.Mask="^[0-9]*$" IsEnabled="{Binding Path=LocationNumberEnabled}" Grid.Row="1" Grid.Column="3">
    <Binding Path="LocationNumber"  Mode="TwoWay" UpdateSourceTrigger="LostFocus" NotifyOnValidationError="True" ValidatesOnExceptions="True">
        <Binding.ValidationRules>
            <localValidation:PositiveNumberRule />
            <localValidation:RequiredFieldRule />
        </Binding.ValidationRules>
    </Binding>                    
</TextBox>
Run Code Online (Sandbox Code Playgroud)

效果非常好!每次我想手动验证(例如按下按钮时)时,我都会调用 IsValid 方法。