(1) MVVM INPC not compativle with Validation Event so OnPropertyChanged instead (2) Consider Grid Cell validation and Ok button CanExecute (3) IDXDataErrorInfo is for view,VM validation required custom code (4) IDXDataErrorInfo GetError Not implemented=> avoid clustered error on row level #region Validation for VM private bool _isValid; public bool IsValid { get { return _isValid; } set { if (_isValid != value) // check to reduce chking CanExcecute { _isValid = value; NotifyPropertyChanged(() => IsValid); } } } public void Validate() { int invalidChildrenCount= Children.Count(IsChildInvalid); bool allDataFieldValid = Validate("Pro1") == null && Validate("Pro2") ; IsValid= allDataFieldValid && invalidChildrenCount= == 0; } private bool IsChirldInvalid(ChirldGridVMData Chirld) { switch (SomeMode) { case "Mode1": if (Chirld.Validdate("Prop1") != null) return true; break; ... } switch (Mode2) { ... } return false; } private string Validate(string dataFieldName) { switch (dataFieldName) { case "VMProp1": if (string.IsNullOrEmpty(Description)) { return "Please enter ..."; // Non-empty description } break; ... } return null; } public string EnsureReferenceChirldChecked() { if (Chirlds.Count(l => l.IsRefChirld.HasValue && l.IsRefChirld.Value) >= 2) { return "Only one Chirld can be reference."; } if (Chirlds.Count(l => l.IsRefChirld.HasValue && l.IsRefChirld.Value) == 0) { return "At least one Chirld must be reference."; } return null; } #endregion #region IDataErrorInfo for View public string this[string dataFieldName] { get { //CommandManager.InvalidateRequerySuggested(); does not work var result = Validate(dataFieldName); return result; } } public string Error { get { // return this[string.Empty or Null] does not work return null; } } #endregion public class LegGridVMData : ViewModelItemBase, IDXDataErrorInfo { #region Fields private string _p1; public string VMP1 { get { return _p1;} set { _p1= value; NotifyPropertyChanged(() => WMP1); } } #endregion #region IDXDataErrorInfo for View public void GetError(ErrorInfo info) { // chose not to cluster error message to row level } public void GetPropertyError(string propertyName, ErrorInfo info) { info.ErrorType = ErrorType.Information; info.ErrorText= Validdate(propertyName); } #endregion #region Validation for VM public string Validdate(string propertyName) { switch (propertyName) { case "VMP1": if (string.IsNullOrEmpty(VMP1)) { return "Please select a VMp1"; } break; ... } return null; } #endregion private bool CanExecuteOk() { return ViewModel.IsValid; } private void TriggerViewModelChirldsValidation() { ViewModel.Chirlds = ViewModel.Chirlds; // Hack: assign itself to trigger Validation, w/o makeing NotifyPropertyChanged public. } void ListenToPropertyChangedEvent() { if (ViewModel == null || ViewModel.Chirlds == null) return; foreach (var l in ViewModel.Chirlds) l.PropertyChanged += OnPropertyChanged; ViewModel.PropertyChanged += OnPropertyChanged; } void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "IsValid") // IsValid changes => reevaluate CanExecute. { var cmd = ViewModel.OkCommand as DeChirldateCommand; if (cmd != null) cmd.RaiseCanExecuteChanged(); } else // otherwise, just do re-evaludation of IsValid { ViewModel.Validate(); } if (e.PropertyName == "IsRef") { TriggerViewModelChildrenValidation(); // Trigger one and only one Ref validation on Ref checkbox } }
Saturday, November 29, 2014
IDataErroInfo in MVVM +Presenter
Subscribe to:
Posts (Atom)