4f61a89be2 | ||
---|---|---|
.github | ||
media | ||
samples/xamarin-forms/LoginApp | ||
src | ||
.editorconfig | ||
.gitattributes | ||
.gitignore | ||
LICENSE | ||
README.md | ||
analyzers.ruleset | ||
analyzers.tests.ruleset | ||
azure-pipelines.yml | ||
build.cake | ||
build.cmd | ||
build.config | ||
build.ps1 | ||
build.sh | ||
cake.config | ||
version.json |
README.md
ReactiveUI.Validation
Validation for ReactiveUI based solutions, functioning in a reactive way.
This repository is based on jcmm33's Vistian.Reactive.Validation.
NuGet Packages
Install the following package into you class library and platform-specific project. ReactiveUI.Validation package supports all platforms, including .NET Framework, .NET Standard, MonoAndroid, Tizen, UAP, Xamarin.iOS, Xamarin.Mac, Xamarin.TVOS.
Platform | ReactiveUI Package | NuGet |
---|---|---|
Any | ReactiveUI.Validation |
How to use
- For ViewModels which need validation, implement
IValidatableViewModel
. - Add validation rules to the ViewModel.
- Bind to the validation rules in the View.
Example
- 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 theIValidatableViewModel
interface. Then, add validation to the ViewModel.
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 validations there is also the possibility to supply an Observable<bool>
indicating whether the rule is valid or not. Thus you can combine multiple properties or incorporate other complex logic.
this.ValidationRule(
vm => vm.WhenAnyValue(x => x.TextInput1, x => x.TextInput2, (input1, input2) => input1 == input2)
(vm, isValid) => isValid ? string.Empty : "Both inputs should be the same");
- Add validation presentation to the View.
public class SampleView : ReactiveContentPage<SampleViewModel>
{
public SampleView()
{
InitializeComponent();
this.WhenActivated(disposables =>
{
this.Bind(ViewModel, vm => vm.Name, view => view.Name.Text)
.DisposeWith(disposables);
// Bind any validations which reference the Name property
// to the text of the NameError UI control.
this.BindValidation(ViewModel, vm => vm.Name, view => view.NameError.Text)
.DisposeWith(disposables);
});
}
}
Note
Name
is anEntry
andNameError
is aLabel
(both are controls from the Xamarin.Forms library).
Example with Android extensions
There are extensions methods for Android specific and its Material design control TextInputLayout
. These extensions use internally the Error property from this control, allowing you a Material Design and fully native behavior to showing errors.
To use these extensions you must import ReactiveUI.Validation.Platforms.Android
.
using ReactiveUI.Validation.Platforms.Android;
namespace SampleApp.Activities
{
public class SampleActivity : ReactiveAppCompatActivity<SampleViewModel>
{
public TextInputEditText Name { get; set; }
public TextInputLayout NameLayout { get; set; }
protected override void OnCreate (Bundle bundle)
{
base.OnCreate(bundle);
// Sets our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
WireUpControls();
this.Bind(ViewModel, vm => vm.Name, view => view.Name.Text);
// Bind any validations which reference the Name property
// to the Error property of the TextInputLayout control
this.BindValidation(ViewModel, vm => vm.Name, NameLayout);
}
}
}
INotifyDataErrorInfo Support
For those platforms which support the INotifyDataErrorInfo
interface, ReactiveUI.Validation provides a helper base class named ReactiveValidationObject<TViewModel>
. The helper class implements both the IValidatableViewModel
interface and the INotifyDataErrorInfo
interface. It listens to any changes in the ValidationContext
and invokes INotifyDataErrorInfo
events.
public class SampleViewModel : ReactiveValidationObject<SampleViewModel>
{
[Reactive]
public string Name { get; set; } = string.Empty;
public SampleViewModel()
{
this.ValidationRule(
x => x.Name,
name => !string.IsNullOrWhiteSpace(name),
"Name shouldn't be empty.");
}
}
Note The
Reactive
attribute is from the ReactiveUI.Fody NuGet package.
When using the ValidationRule
overload that uses Observable<bool>
for more complex scenarios please keep in mind to supply the property which the validation rule is targeting as the first argument. Otherwise it is not possible for INotifyDataErrorInfo
to conclude which property the error message is for.
this.ValidationRule(
vm => vm.TextInput2,
vm => vm.WhenAnyValue(x => x.TextInput1, x => x.TextInput2, (input1, input2) => input1 == input2)
(vm, isValid) => isValid ? string.Empty : "Both inputs should be the same");
Capabilities
- Rules can be composed of single or multiple properties along with more generic Observables.
- Validation text can encapsulate both valid and invalid states.
- Binding can occur to either a View or an action.
- Validation text can reference either the ViewModel or properties which comprise the validation rule e.g. include text entered as part of validation message.
- Validation text output can be adjusted using custom formatters, not only allowing for single & multiline output but also for platforms like Android it should be possible to achieve richer renderings i.e. Bold/italics.
How it Works
In essence, it's a relatively simple model of the ValidationContext
containing a list of IValidationComponent
instances. An IValidationComponent
provides an observable for ValidationState
. Whenever validation state changes (either a transition of validity) or ValidationText
changes, then a new value is pushed out.
Feedback
Please use GitHub issues for questions or comments.
Authors
- jcmm33 - Initial work - GitHub profile
- Àlex Martínez Morón - Repository maintenance - GitHub profile
Contribute
ReactiveUI.Validation is developed under an OSI-approved open source license, making it freely usable and distributable, even for commercial use. Because of our Open Collective model for funding and transparency, we are able to funnel support and funds through to our contributors and community. We ❤ the people who are involved in this project, and we’d love to have you on board, especially if you are just getting started or have never contributed to open-source before.
So here's to you, lovely person who wants to join us — this is how you can support us:
- Responding to questions on StackOverflow
- Passing on knowledge and teaching the next generation of developers
- Donations and Corporate Sponsorships
- Asking your employer to reciprocate and contribute to open-source
- Submitting documentation updates where you see fit or lacking.
- Making contributions to the code base.
Copyright and License
Code released under the MIT license.