# ReactiveUI.Validation **Repository Path**: mirrors_reactiveui/ReactiveUI.Validation ## Basic Information - **Project Name**: ReactiveUI.Validation - **Description**: Validation helpers for ReactiveUI-based apps. - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-25 - **Last Updated**: 2025-12-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [![NuGet Stats](https://img.shields.io/nuget/v/reactiveui.validation.svg)](https://www.nuget.org/packages/reactiveui.validation) ![Build](https://github.com/reactiveui/ReactiveUI.Validation/workflows/Build/badge.svg) [![Code Coverage](https://codecov.io/gh/reactiveui/ReactiveUI.Validation/branch/main/graph/badge.svg)](https://codecov.io/gh/reactiveui/ReactiveUI.Validation) [![#yourfirstpr](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](https://reactiveui.net/contribute) [![Downloads](https://img.shields.io/nuget/dt/reactiveui.validation.svg)](https://www.nuget.org/packages/reactiveui.validation) [![Slack](https://img.shields.io/badge/chat-slack-blue.svg)](https://reactiveui.net/slack) # ReactiveUI.Validation Validation for ReactiveUI based solutions, functioning in a reactive way. `ReactiveUI.Validation` was originally developed by [@jcmm33](https://github.com/jcmm33) as [Vistian.Reactive.Validation](https://github.com/jcmm33/ReactiveUI.Validation), and then refactored and updated by [Àlex Martínez Morón](https://github.com/alexmartinezm) and the [ReactiveUI Core Team](https://github.com/reactiveui/ReactiveUI#core-team). `ReactiveUI.Validation` supports all platforms, including .NET Framework, .NET Standard, .NET Core, Maui. ## NuGet Packages Install the following package into your class library and into a platform-specific project. | Platform | ReactiveUI Package | NuGet | | ------------------ | ------------------------------------------------ | -------------------- | | Any Platform | [ReactiveUI.Validation][CoreDoc] | [![CoreBadge]][Core] | | AndroidX (Maui, Xamarin) | [ReactiveUI.Validation.AndroidX][DroDoc] | [![DroXBadge]][DroX] | | Xamarin.Android | [ReactiveUI.Validation.AndroidSupport][DroDoc] | [![DroBadge]][Dro] | [Core]: https://www.nuget.org/packages/ReactiveUI.Validation/ [CoreBadge]: https://img.shields.io/nuget/v/ReactiveUI.Validation.svg [CoreDoc]: https://reactiveui.net/docs/handbook/user-input-validation/ [Dro]: https://www.nuget.org/packages/ReactiveUI.Validation.AndroidSupport/ [DroBadge]: https://img.shields.io/nuget/v/ReactiveUI.Validation.AndroidSupport.svg [DroDoc]: https://github.com/reactiveui/reactiveui.validation#example-with-android-extensions [DroX]: https://www.nuget.org/packages/ReactiveUI.Validation.AndroidX/ [DroXBadge]: https://img.shields.io/nuget/v/ReactiveUI.Validation.AndroidX.svg ## How to Use * For ViewModels which need validation, implement `IValidatableViewModel`. * Add validation rules to the ViewModel using the `ValidationRule` extension methods. * Bind to the validation rules in the View via `BindValidation` or `INotifyDataErrorInfo`. ## Example 1. Decorate existing ViewModel with `IValidatableViewModel`, which has a single member, `ValidationContext`. The ValidationContext contains all of the functionality surrounding the validation of the ViewModel. Most access to the specification of validation rules is performed through extension methods on the `IValidatableViewModel` interface. Then, add validation to the ViewModel. ```csharp using ReactiveUI.Validation.Extensions; public class SampleViewModel : ReactiveObject, IValidatableViewModel { public SampleViewModel() { // Creates the validation for the Name property. this.ValidationRule( viewModel => viewModel.Name, name => !string.IsNullOrWhiteSpace(name), "You must specify a valid name"); } public ValidationContext ValidationContext { get; } = new ValidationContext(); private string _name; public string Name { get => _name; set => this.RaiseAndSetIfChanged(ref _name, value); } } ``` For more complex validation scenarios there are several more overloads of the `ValidationRule` extension method that accept observables. These allow validation to occur asynchronously, and allows complex chains of observables to be combined to produce validation results. The simplest accepts an `IObservable` where the observed boolean indicates whether the `ValidationRule` is valid or not. The overload accepts a message which is used when the observable produces a `false` (_invalid_) result. ```csharp IObservable passwordsObservable = this.WhenAnyValue( x => x.Password, x => x.ConfirmPassword, (password, confirmation) => password == confirmation); this.ValidationRule( vm => vm.ConfirmPassword, passwordsObservable, "Passwords must match."); ``` Any existing observables can be used to drive a `ValidationRule` using the extension method overload that accepts an arbitrary `IObservable` streams of events. The overload accepts a custom validation function that is supplied with the latest `TState`, and a custom error message function, responsible for formatting the latest `TState` object. The syntax for this looks as follows: ```csharp // IObservable<{ Password, Confirmation }> var passwordsObservable = this.WhenAnyValue( x => x.Password, x => x.ConfirmPassword, (password, confirmation) => new { Password = password, Confirmation = confirmation }); this.ValidationRule( vm => vm.ConfirmPassword, passwordsObservable, state => state.Password == state.Confirmation, state => $"Passwords must match: {state.Password} != {state.Confirmation}"); ``` > **Note** The function to extract a message (`messageFunc`) is only invoked if the function to establish validity (`isValidFunc`) returns `false`, otherwise the message is set to `string.Empty`. Finally, you can directly supply an observable that streams any object (or struct) that implements `IValidationState`; or you can use the `ValidationState` base class which already implements the interface. As the resulting object is stored directly against the context without further transformation, this can be the most performant approach: ```csharp IObservable usernameNotEmpty = this.WhenAnyValue(x => x.UserName) .Select(name => string.IsNullOrEmpty(name) ? new ValidationState(false, "The username must not be empty") : ValidationState.Valid); this.ValidationRule(vm => vm.UserName, usernameNotEmpty); ``` > **Note** As a valid `ValidationState` does not really require a message, there is a singleton `ValidationState.Valid` property that you are encouraged to use to indicate a valid state whenever possible, to reduce memory allocations. 2. Add validation presentation to the View. ```csharp using ReactiveUI.Validation.Extensions; public class SampleView : ReactiveContentPage { public SampleView() { InitializeComponent(); this.WhenActivated(disposables => { this.Bind(ViewModel, vm => vm.Name, view => view.Name.Text) .DisposeWith(disposables); // Bind any validations that reference the Name property // to the text of the NameError UI control. this.BindValidation(ViewModel, vm => vm.Name, view => view.NameError.Text) .DisposeWith(disposables); // Bind any validations attached to this particular view model // to the text of the FormErrors UI control. this.BindValidation(ViewModel, view => view.FormErrors.Text) .DisposeWith(disposables); }); } } ``` > **Note** `Name` is an ``, `NameError` is a `