2011-12-06 10 views
5

複数のフィールド間のバリデーションに問題があります。たとえば、DateViewModelという名前のクラスの2つのインスタンスを含むRangeMapという名前のViewModelがあります。それぞれのインスタンスは開始日と終了日を表します。このような異なるレベルの複数のフィールド間のバリデーション

だから私の結合ルックス -

<TextBox Text="{Binding StartDate.Date, ValidateOnDataError=True}"> 
<TextBox Text="{Binding EndDate.Date, ValidateOnDataError=True}"> 

マイRangeDateViewModelクラスがIDataErrorInfoインターフェイスを実装しています。私の計画では 、RangeDateViewModelはこのようなIDataErrorInfo [「プロパティ名」]機能で検証ロジックを適用することで、開始日が終了日より前の日付であることを検証します -

public string this[string columnName] 
    { 
     get 
     { 
      return ValidationError(); 
     } 
    } 

問題は、これは決してないということですその代わりにそれぞれのDateViewModelクラスにあるIDataErrorInfoプロパティが呼び出されています。

これは、バウンドプロパティがRangeDateViewModelと同じレベルではなく、子のDateViewModel内にあるためです。

私の必要性は非常に基本的であり、この問題のための簡単な解決策がなければならないと思います。 IDataErrorInfoの代わりにValidationRulesを使用しようとしましたが、ViewModelにValidationRulesから現在の検証ステータスを知らせるのに問題がありました。

答えて

1

次のアプローチを使用してみてください:ContentControlにこのビューモデルのインスタンス

<DataTemplate DataType="{x:Type ViewModels:DateViewModel}"> 
    <TextBox Text="{Binding Date}"> 
</DataTemplate> 
  • バインドし、その結合にtrueValidateOnDataErrorを設定します:

    1. DateViewModelためDataTemplateを作成

      <ContentControl Content="{Binding StartDate, ValidateOnDataError=True}" /> 
      <ContentControl Content="{Binding EndDate, ValidateOnDataError=True}" /> 
      
    2. StartDateEndDatePropertyChangedイベントをサブスクライブして上げたときに、StartDate/EndDatePropertyChangedイベントを発生させる:

      StartDate.PropertyChanged += (s, e) => InvokePropertyChanged("StartDate"); 
      EndDate.PropertyChanged += (s, e) => InvokePropertyChanged("EndDate"); 
      
  • +0

    ありがとうダニエル!私はあなたが示唆したことを試みましたが、明らかにまだ十分ではありません。 IDataErrorInfoプロパティは実際にはアクセスされていますが、テンプレートの初期化時にのみ使用され、実際のデータが変更されたときは後でありません。これは、StartDateとEndDateが複雑なオブジェクトなので、自分自身は変更されていませんが、その内部のプロパティであり、PropertyChangedを呼び出すのに十分なフォームではないからです。たぶん私は何らかの形で内部日付プロパティが変更されたときにイベントを発生させる必要がありますか? – Dror

    +0

    @Dror:そうです。更新された回答のステップ3を参照してください。 –

    +0

    もう一度Daniel!これは私が直面している最後のマイナーな問題がまだありますが、うまくいっています。このソリューションでは、値が無効のときに赤でマークされた2つのコントロールが表示されます。私は、赤でマークされているのではなく、これら2つのフィールドを保持しているStackpanelが読み込み中にマークされることを望みます。好ましくは、これらの2つのフィールドはマーキングされませんが、必須ではありません。私は "Validation.HasError"をtrueに設定する "HasErrors"という名前のRangeDateViewModelのboolプロパティにDataTriggerを適用しようとしましたが、残念ながら読み取り専用のプロパティです。この問題についてもお手伝いできることを願っています。 – Dror

    1

    私はpublic string this[string columnName]が単純に他の呼ばれていなかったという問題がありました週間。

    解決策は簡単でした。 バインディングWPFバインディングエンジンは、自分のViewModelsのネストに従うことができませんでした。

    私は現在のDataContextあるビューモデルでプロパティを実装するために必要なことを想定していたが、ではなくそれが制御にバインドあるのViewModelに実装する必要があります。

    例:

    <TextBox Text="{Binding Path=ProductViewModel.DescriptionViewModel.ProductName, 
                Mode=TwoWay, 
                ValidatesOnDataErrors=True, 
                NotifyOnValidationError=True}" /> 
    

    ここDescriptionViewModelは、バウンドプロパティが含まれているクラスです。IDataErrorInfoをそのクラスに実装する必要があります(ではなくProductViewModelにするか、それを含む可能性のある階層を別のクラスにする必要があります)。

    +0

    こんにちは先生、あなたのコメントのおかげで。 IDataErrorInfoがバインディング階層の下位クラスに実装されているときにうまくいきますが、2つの問題があります。 1 - 検証ロジックには2つのクラスが含まれていますが、これらの低レベルのクラスはお互いを知りません。 2 - 値が無効な場合は、フィールドの1つに赤色のマークを付けないようにします。私は全体のコントロールを赤でマークしたい。 – Dror

    関連する問題