GithubHelp home page GithubHelp logo

dmo16 / mvvmvalidation Goto Github PK

View Code? Open in Web Editor NEW

This project forked from pglazkov/mvvmvalidation

0.0 0.0 0.0 19.55 MB

Lightweight library that helps reduce boilerplate when implementing validation in XAML MVVM applications

License: MIT License

C# 99.07% Batchfile 0.13% PowerShell 0.80%

mvvmvalidation's Introduction

Build status

MVVM Validation Helpers

MVVM Validation Helpers is a lightweight library that makes it easier for developers to implement validation in MVVM applications.

It allows you to:

  • Define and keep all your validation rules conveniently in one place.
  • Reduce boilerplate of maintaining error list for each of the validation targets (properties).
  • Validate a target and get the validation result back without worrying what rules need to be checked.
  • Easily implement INotifyDataErrorInfo interface in your view models to integrate with XAML binding engine for displaying validation errors in your views (see NotifyDataErrorAdapter below).

Getting Started

Install the NuGet package.

OR

Download the binaries from Releases.

Examples

Creating an instance of the helper

In order to use the library you need to create an instance of the ValidationHelper helper class and store it in an instance field of the class where you want to implement validation. If you do a lot of validation, it is probably the best to do it in your ViewModelBase class.

public class ViewModelBase
{
    public ViewModelBase()
    {
        Validator = new ValidationHelper();
    }
    
    protected ValidationHelper Validator { get; private set; }
}

Adding a simple validation rule

Validator.AddRule(nameof(FirstName),
                  () => RuleResult.Assert(!string.IsNullOrEmpty(FirstName), "First Name is required"));

OR

Validator.AddRequiredRule(() => FirstName, "First Name is required");

Adding a rule that depends on two different properties

Such a rule will be executed whenever you validate either of those properties.

Validator.AddRule(nameof(RangeStart),
                  nameof(RangeEnd),
                  () => RuleResult.Assert(RangeEnd > RangeStart, 
                                          "RangeEnd must be grater than RangeStart");

Adding an asynchronous rule

Such rule can perform more complex validation that may take long time or cannot be executed synchronously, for example, a call to a web service.

Validator.AddAsyncRule(nameof(UserName),
    async () =>
    {
        var isAvailable = await UserRegistrationService.IsUserNameAvailable(UserName).ToTask();

        return RuleResult.Assert(isAvailable, 
            string.Format("User Name {0} is taken. Please choose a different one.", UserName));
    });

Executing validation

// Validate all (execute all validation rules)
ValidationResult validationResult = Validator.ValidateAll();

// Validate a specific target
ValidationResult validationResult = Validator.Validate(nameof(FirstName));

Executing validation asynchronously

// Validate all (execute all validation rules)
ValidationResult validationResult = await Validator.ValidateAllAsync();

// Validate a specific target
ValidationResult validationResult = await Validator.ValidateAsync(nameof(FirstName));

Getting current validation state at any point of time

Any time you can request current validation state for the entire object or for specific validation targets.

// Get validation result for the entire object
var validationResult = Validator.GetResult();

// Get validation result for a target
var firstNameValidationResult = Validator.GetResult(nameof(FirstName));

Receive notifications when validation result changes

Validator.ResultChanged += OnValidationResultChanged;

private void OnValidationResultChanged(object sender, ValidationResultChangedEventArgs e)
{
    // Get current state of the validation
    ValidationResult validationResult = Validator.GetResult();

    UpdateValidationSummary(validationResult);
}

Implement INotifyDataErrorInfo interface

The library includes NotifyDataErrorAdapter class that makes the implementation of INotifyDataErrorInfo interface in your view models trivial.

public class ValidatableViewModelBase : INotifyDataErrorInfo
{
    protected ValidationHelper Validator { get; private set; }
    private NotifyDataErrorInfoAdapter NotifyDataErrorInfoAdapter { get; set; }

    public ValidatableViewModelBase()
    {
        Validator = new ValidationHelper();

        NotifyDataErrorInfoAdapter = new NotifyDataErrorInfoAdapter(Validator);
    }

    public IEnumerable GetErrors(string propertyName)
    {
        return NotifyDataErrorInfoAdapter.GetErrors(propertyName);
    }

    public bool HasErrors
    {
        get { return NotifyDataErrorInfoAdapter.HasErrors; }
    }

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged
    {
        add { NotifyDataErrorInfoAdapter.ErrorsChanged += value; }
        remove { NotifyDataErrorInfoAdapter.ErrorsChanged -= value; }
    }
}

For more examples download the source code and check out the example project.

Sample UI Screenshot

Advanced Use Cases

Execute rules even if the target is already invalid

By default, if the first rule for the target failed, the remaining rules for that target are skipped. For example, if the "Email" field is required it doesn't make sense to check that the email address is in valid format until user has entered something, so first we execute the "required" rule and only if it succeds we execute the next rule to verify the format of the email.

This default behavior can be overriden either globally or per rule:

Globally:

Validator = new ValidationHelper(new ValidationSettings
{
    DefaultRuleSettings = new ValidationRuleSettings
    {
        ExecuteOnAlreadyInvalidTarget = true
    }
});

Per Rule:

Validator.AddAsyncRule(/* Rule */)
         .WithSettings(s => s.ExecuteOnAlreadyInvalidTarget = false);

mvvmvalidation's People

Contributors

pglazkov avatar mageos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.