public void ShouldDeliverErrorsWhenModelObservableValidationTriggers() { var viewModel = new IndeiTestViewModel(); string namesShouldMatchMessage = "names should match."; var validation = new ModelObservableValidation <IndeiTestViewModel, string>( viewModel, vm => vm.OtherName, vm => vm.WhenAnyValue( m => m.Name, m => m.OtherName, (n, on) => new { n, on }) .Select(bothNames => bothNames.n == bothNames.on), (_, isValid) => isValid ? string.Empty : namesShouldMatchMessage); viewModel.ValidationContext.Add(validation); Assert.False(viewModel.HasErrors); Assert.True(viewModel.ValidationContext.IsValid); Assert.Single(viewModel.ValidationContext.Validations); Assert.Empty(viewModel.GetErrors(nameof(viewModel.Name)).Cast <string>()); Assert.Empty(viewModel.GetErrors(nameof(viewModel.OtherName)).Cast <string>()); viewModel.Name = "JoJo"; viewModel.OtherName = "NoNo"; Assert.True(viewModel.HasErrors); Assert.Empty(viewModel.GetErrors(nameof(viewModel.Name)).Cast <string>()); Assert.Single(viewModel.GetErrors(nameof(viewModel.OtherName)).Cast <string>()); Assert.Single(validation.Text); Assert.Equal(namesShouldMatchMessage, validation.Text.Single()); }
/// <summary> /// Setup a validation rule with a general observable indicating validity. /// </summary> /// <typeparam name="TViewModel">ViewModel type.</typeparam> /// <typeparam name="TViewModelProp">ViewModel property type.</typeparam> /// <param name="viewModel">ViewModel instance.</param> /// <param name="viewModelProperty">ViewModel property referenced in viewModelObservableProperty.</param> /// <param name="viewModelObservableProperty">Func to define if the viewModel is valid or not.</param> /// <param name="messageFunc">Func to define the validation error message based on the viewModel and viewModelObservableProperty values.</param> /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns> /// <remarks> /// It should be noted that the observable should provide an initial value, otherwise that can result /// in an inconsistent performance. /// </remarks> public static ValidationHelper ValidationRule <TViewModel, TViewModelProp>( this TViewModel viewModel, Expression <Func <TViewModel, TViewModelProp> > viewModelProperty, Func <TViewModel, IObservable <bool> > viewModelObservableProperty, Func <TViewModel, bool, string> messageFunc) where TViewModel : ReactiveObject, IValidatableViewModel { if (viewModel is null) { throw new ArgumentNullException(nameof(viewModel)); } if (viewModelProperty is null) { throw new ArgumentNullException(nameof(viewModelProperty)); } if (viewModelObservableProperty is null) { throw new ArgumentNullException(nameof(viewModelObservableProperty)); } if (messageFunc is null) { throw new ArgumentNullException(nameof(messageFunc)); } var validation = new ModelObservableValidation <TViewModel, TViewModelProp>(viewModel, viewModelProperty, viewModelObservableProperty, messageFunc); viewModel.ValidationContext.Add(validation); return(new ValidationHelper(validation)); }
/// <summary> /// Setup a validation rule with a general observable indicating validity. /// </summary> /// <typeparam name="TViewModel">ViewModel type.</typeparam> /// <param name="viewModel">ViewModel instance.</param> /// <param name="viewModelObservableProperty">Func to define if the viewModel is valid or not.</param> /// <param name="messageFunc">Func to define the validation error message based on the viewModel and viewModelObservableProperty values.</param> /// <returns>Returns a <see cref="ValidationHelper"/> object.</returns> /// <remarks> /// It should be noted that the observable should provide an initial value, otherwise that can result /// in an inconsistent performance. /// </remarks> public static ValidationHelper ValidationRule <TViewModel>( this TViewModel viewModel, Func <TViewModel, IObservable <bool> > viewModelObservableProperty, Func <TViewModel, bool, string> messageFunc) where TViewModel : ReactiveObject, ISupportsValidation { var validation = new ModelObservableValidation <TViewModel>(viewModel, viewModelObservableProperty, messageFunc); viewModel.ValidationContext.Add(validation); return(new ValidationHelper(validation)); }
public void InitialValidStateIsCorrect() { var model = new TestViewModel() { Name = "name", Name2 = "name2" }; Subject <bool> validState = new Subject <bool>(); var v = new ModelObservableValidation <TestViewModel>(model, (m) => validState.StartWith(true), (m, s) => "broken"); Assert.True(v.IsValid); }
public void ObservableToInvalid() { var model = new TestViewModel() { Name = "name", Name2 = "name2" }; ReplaySubject <bool> validState = new ReplaySubject <bool>(1); var v = new ModelObservableValidation <TestViewModel>(model, (m) => validState, (m, s) => "broken"); validState.OnNext(false); validState.OnNext(true); validState.OnNext(false); Assert.False(v.IsValid); Assert.Equal("broken", v.Text.ToSingleLine()); }