在 WPF 中进行表单验证

WPF的表单验证,自然比不上WEB多姿多彩。一般有三种方式进行表单验证:

1. 代码直接验证(不少人直接用 MessageBox  弹出消息,Windows 的老传统),虽然够醒目,却太过打扰用户,不好。

2. 通过异常验证(数据绑定,并设置 ValidatesOnExceptions=True ),调试时烦死人,不好。

3. 通过内置接口 IDataErrorInfo 、INotifyDataErrorInfo 进行验证(数据绑定),这应该是目前较为理想的验证方式。这两个接口都位于 System.ComponentModel 空间,与 INotifyPropertyChanged 在一起。

 

只说第三种验证方式。

这两个接口,个人较喜欢第二个,原因是第一个接口不太灵活,而且是为了兼容而存在的,不推荐使用。第二要灵活得多。

 

为了突出验证消息的提示效果,可添加这样一个样式(定义为字典资源,用起来更方便):

<Style TargetType="TextBox">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <DockPanel>
                    <TextBlock DockPanel.Dock="Bottom" Foreground="Red"
                                Text="{Binding ElementName=adornedElement, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"></TextBlock>
                    <Border BorderBrush="Red" BorderThickness="1">
                        <AdornedElementPlaceholder Name="adornedElement"></AdornedElementPlaceholder>
                    </Border>
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

一、首先定义一个集合,用于保存验证消息:

private readonly IDictionary<string, IList<string>> m_errors = new Dictionary<string, IList<string>>();

 

二、下面是实现接口,具体用法见注释:

// 该方法仅为简化属性调用。CallerMemberName 特性是 .net 4.5 才加入的,位于 System.Runtime.CompilerServices 空间。
public
void Validate(Func<bool> valid, string error, [CallerMemberName]string prop = null) { if (valid()) ClearError(prop); else SetError(new[] { error }, prop); OnChanged(prop); }
// 验证属性事件。
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; // 属性更改事件。
public event PropertyChangedEventHandler PropertyChanged; // 该方法由 wpf 调用。 public IEnumerable GetErrors(string propertyName) { if (string.IsNullOrEmpty(propertyName)) return null;    // SelectMany 方法很有用,若没有它,错误消息不能正确显示,除非你重写集合,并重写其 ToString 方法。它帮你省了很多麻烦。 var errors = m_errors.SelectMany(e => e.Value); return errors; } // 添加错误消息。 public void SetError(IList<string> errors, string prop) { m_errors.Remove(prop); m_errors.Add(prop, errors); OnError(prop); } // 清除错误消息。 public void ClearError(string prop) { m_errors.Remove(prop); OnError(prop); } // 验证属性时调用。 private void OnError(string prop) { ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(prop)); }

三、属性这样调用验证代码(以及更新事件):

public string Password
{
    get { return m_password; }
    set
    {
        m_password = value;
     // 由于第三种验证方式比较温和,不能像异常那样阻止属性值更新,因此该方法放在下面没有问题。 Validate(() => !Regex.IsMatch(value, "4"), "数字 4 不祥"); } }

 

四、前台代码并没有什么特殊的,只要你别忘了应用上面的样式。 ValidatesOnNotifyDataErrors=True 可不写,但建议写上,有提示作用:

<TextBox Text="{Binding Path=Password, ValidatesOnNotifyDataErrors=True}"></TextBox>

 

完。

原文地址:https://www.cnblogs.com/yyzj/p/7067431.html