2011-07-14 9 views
0

可能性の重複:
How can I handle a Validation.Error in my ViewModel instead of my View's code behind?WPF:MVVMで広範なデータ検証を実装する方法を

WPFでデータの検証を使用する方法の一般的な例は通常はエラーを定義することを伴いますコントロールのテンプレートを使用して、コントロールのツールチップにエラーメッセージを表示します。私がしたいのは、すべてのValidationErrorsのコレクションを作成し、それをItemsControl内にユーザに表示し、ユーザがItemsControlの関連する(エラー)アイテムをクリックしたときに無効なコントロールにフォーカスすることです。私はすべてのコントロールにValidation.GetErrors(OBJ)を呼び出し、それを私のコレクションを構築することができますので、問題の多くではありません非MVVMのプロジェクトで

。しかし、MVVMでは、ViewModelはViewへの直接リンクを持っていないので、ビューのコントロールへの参照がないため、ViewModelでGetErrors()を呼び出してコレクションを構築することはできません。

任意のバインドするトリックまたはルートViewModelにに見るからによりvalidationErrorsはありますかこれはMVVMで達成するだけでは不可能でしょうか?

+2

これのためにコードビハインドを使用することは違法ではありません。ちょっとしたC#を追加するだけです。 –

答えて

1

データ検証とMVVMのための通常のアプローチは、IDataErrorInfoを使用しています。あなたはウェブ上で多くの情報を見つけるでしょう。

あなたがバインドコントロールにフォーカスを設定するトリックは、Bindingプロパティ名を使用することです。ジョシュ・スミスpostedはそれについてブログしてきました。以下は

0

当社のViewModel基底クラスそれによりvalidationErrorsプロパティのコードです。私たちのビューモデル基本クラスはINotifyPropertyChangedとIDataErrorInfoを実装し、Silverlight 4+ではINotifyDataErrorInfoも実装します。

SilverlightとWPFのための条件付きコンパイル文に注意してください。 Silverlightでは、標準のINotifyDataErrorInfoメカニズムを使用してビューに通知し、WPFに対しては、影響を受けるコントロールを更新するPropertyChangedイベントをトリガーします。

使い方はかなりシンプルです。導出された各ビューモデルクラスは、ValidationErrorsプロパティを設定するだけで、他のすべてはプロパティセッターによって処理されます。 ValidationFailureの失敗クラスは、実際の検証ロジックを実装するために使用するFluentValidationライブラリに属します。

public IList<ValidationFailure> ValidationErrors 
{ 
    get { return GetPropertyValue(() => ValidationErrors); } 
    protected set 
    { 
    List<string> obsoleteValidationErrors = null; 

    // collect names of properties that do not longer have errors 
#if SILVERLIGHT 
    if (ErrorsChanged != null) 
#else 
    if (PropertyChanged != null) 
#endif 
    { 
     var oldErrorsCollection = ValidationErrors != null && ValidationErrors.Count > 0 ? ValidationErrors : new List<ValidationFailure>(); 
     var newErrorsCollection = value != null && value.Count > 0 ? value : new List<ValidationFailure>(); 
     var newPropertyNames = newErrorsCollection.Select(x => x.PropertyName).Distinct().ToDictionary(x => x); 

     // figure out which errors are no longer part of the new validation error collection 
     obsoleteValidationErrors = oldErrorsCollection.Where(x => 
     !newPropertyNames.ContainsKey(x.PropertyName)).Select(x => x.PropertyName).Distinct().ToList(); 
    } 

    if (SetPropertyValue(() => ValidationErrors, value)) 
    { 
     // fire event for properties that do not longer have errors 
     if (obsoleteValidationErrors != null) 
     { 
     foreach (var obsoleteValidationErrorPropertyName in obsoleteValidationErrors) 
#if SILVERLIGHT 
      ErrorsChanged(this, new DataErrorsChangedEventArgs(obsoleteValidationErrorPropertyName)); 
#else 
      OnPropertyChanged(obsoleteValidationErrorPropertyName); 
#endif 
     } 

     // fire event for properties that now have errors 
#if SILVERLIGHT 
     if (value != null && ErrorsChanged != null) 
#else 
     if (value != null && PropertyChanged != null) 
#endif 
     { 
     var propertyNames = value.Select(x => x.PropertyName).Distinct().ToList(); 

     foreach (var failedProperty in propertyNames) 
#if SILVERLIGHT 
      ErrorsChanged(this, new DataErrorsChangedEventArgs(failedProperty)); 
#else 
      OnPropertyChanged(failedProperty); 
#endif 
     } 
    } 
    } 
} 
関連する問題