在 WPF 中進行表單驗證

WPF的表單驗證,天然比不上WEB多姿多彩。通常有三種方式進行表單驗證:this

1. 代碼直接驗證(很多人直接用 MessageBox  彈出消息,Windows 的老傳統),雖然夠醒目,卻太過打擾用戶,很差。spa

2. 經過異常驗證(數據綁定,並設置 ValidatesOnExceptions=True ),調試時煩死人,很差。.net

3. 經過內置接口 IDataErrorInfo 、INotifyDataErrorInfo 進行驗證(數據綁定),這應該是目前較爲理想的驗證方式。這兩個接口都位於 System.ComponentModel 空間,與 INotifyPropertyChanged 在一塊兒。調試

 

只說第三種驗證方式。code

這兩個接口,我的較喜歡第二個,緣由是第一個接口不太靈活,並且是爲了兼容而存在的,不推薦使用。第二要靈活得多。blog

 

爲了突出驗證消息的提示效果,可添加這樣一個樣式(定義爲字典資源,用起來更方便):接口

<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>

 

1、首先定義一個集合,用於保存驗證消息:事件

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

 

2、下面是實現接口,具體用法見註釋:資源

// 該方法僅爲簡化屬性調用。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)); }

 

3、屬性這樣調用驗證代碼(以及更新事件):get

public string Password
{
    get { return m_password; }
    set
    {
        m_password = value;
     // 因爲第三種驗證方式比較溫和,不能像異常那樣阻止屬性值更新,所以該方法放在下面沒有問題。 Validate(() => !Regex.IsMatch(value, "4"), "數字 4 不祥"); } }

 

4、前臺代碼並無什麼特殊的,只要你別忘了應用上面的樣式。 ValidatesOnNotifyDataErrors=True 可不寫,但建議寫上,有提示做用:

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

 

完。

相關文章
相關標籤/搜索