-
-
Save GrantByrne/11243164 to your computer and use it in GitHub Desktop.
using System.Text.RegularExpressions; | |
using FluentValidation; | |
using WpfFluentValidationExample.ViewModels; | |
namespace WpfFluentValidationExample.Lib | |
{ | |
public class UserValidator : AbstractValidator<UserViewModel> | |
{ | |
public UserValidator() | |
{ | |
RuleFor(user => user.Name) | |
.NotEmpty() | |
.WithMessage("Please Specify a Name."); | |
RuleFor(user => user.Email) | |
.EmailAddress() | |
.WithMessage("Please Specify a Valid E-Mail Address"); | |
RuleFor(user => user.Zip) | |
.Must(BeAValidZip) | |
.WithMessage("Please Enter a Valid Zip Code"); | |
} | |
private static bool BeAValidZip(string zip) | |
{ | |
if (!string.IsNullOrEmpty(zip)) | |
{ | |
var regex = new Regex(@"\d{5}"); | |
return regex.IsMatch(zip); | |
} | |
return false; | |
} | |
} | |
} |
<Window | |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
xmlns:viewModels="clr-namespace:WpfFluentValidationExample.ViewModels" x:Class="WpfFluentValidationExample.Views.UserView" | |
Title="UserView" Height="300" MinWidth="500"> | |
<Window.DataContext> | |
<viewModels:UserViewModel/> | |
</Window.DataContext> | |
<StackPanel> | |
<StackPanel Orientation="Horizontal"> | |
<Label Content="Name" Margin="10"/> | |
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="200" Margin="10"> | |
<Validation.ErrorTemplate> | |
<ControlTemplate> | |
<StackPanel Orientation="Horizontal"> | |
<!-- Placeholder for the TextBox itself --> | |
<AdornedElementPlaceholder x:Name="textBox"/> | |
<TextBlock Margin="10" Text="{Binding [0].ErrorContent}" Foreground="Red"/> | |
</StackPanel> | |
</ControlTemplate> | |
</Validation.ErrorTemplate> | |
</TextBox> | |
</StackPanel> | |
<StackPanel Orientation="Horizontal"> | |
<Label Content="E-Mail" Margin="10"/> | |
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="200" Margin="10"> | |
<Validation.ErrorTemplate> | |
<ControlTemplate> | |
<StackPanel Orientation="Horizontal"> | |
<!-- Placeholder for the TextBox itself --> | |
<AdornedElementPlaceholder x:Name="textBox"/> | |
<TextBlock Margin="10" Text="{Binding [0].ErrorContent}" Foreground="Red"/> | |
</StackPanel> | |
</ControlTemplate> | |
</Validation.ErrorTemplate> | |
</TextBox> | |
</StackPanel> | |
<StackPanel Orientation="Horizontal"> | |
<Label Content="Zip" Margin="10"/> | |
<TextBox Text="{Binding Zip, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="200" Margin="10"> | |
<Validation.ErrorTemplate> | |
<ControlTemplate> | |
<StackPanel Orientation="Horizontal"> | |
<!-- Placeholder for the TextBox itself --> | |
<AdornedElementPlaceholder x:Name="textBox"/> | |
<TextBlock Margin="10" Text="{Binding [0].ErrorContent}" Foreground="Red"/> | |
</StackPanel> | |
</ControlTemplate> | |
</Validation.ErrorTemplate> | |
</TextBox> | |
</StackPanel> | |
<Button Margin="10">Submit</Button> | |
</StackPanel> | |
</Window> |
using System.Windows; | |
using WpfFluentValidationExample.ViewModels; | |
namespace WpfFluentValidationExample.Views | |
{ | |
/// <summary> | |
/// Interaction logic for UserView.xaml | |
/// </summary> | |
public partial class UserView : Window | |
{ | |
public UserView() | |
{ | |
InitializeComponent(); | |
DataContext = new UserViewModel(); | |
} | |
} | |
} |
using System; | |
using System.ComponentModel; | |
using System.Linq; | |
using WpfFluentValidationExample.Lib; | |
namespace WpfFluentValidationExample.ViewModels | |
{ | |
public class UserViewModel : INotifyPropertyChanged, IDataErrorInfo | |
{ | |
private readonly UserValidator _userValidator; | |
private string _zip; | |
private string _email; | |
private string _name; | |
public UserViewModel() | |
{ | |
_userValidator = new UserValidator(); | |
} | |
public string Name | |
{ | |
get { return _name; } | |
set | |
{ | |
_name = value; | |
OnPropertyChanged("Name"); | |
} | |
} | |
public string Email | |
{ | |
get { return _email; } | |
set | |
{ | |
_email = value; | |
OnPropertyChanged("Email"); | |
} | |
} | |
public string Zip | |
{ | |
get { return _zip; } | |
set | |
{ | |
_zip = value; | |
OnPropertyChanged("Zip"); | |
} | |
} | |
public string this[string columnName] | |
{ | |
get | |
{ | |
var firstOrDefault = _userValidator.Validate(this).Errors.FirstOrDefault(lol => lol.PropertyName == columnName); | |
if (firstOrDefault != null) | |
return _userValidator != null ? firstOrDefault.ErrorMessage : ""; | |
return ""; | |
} | |
} | |
public string Error | |
{ | |
get | |
{ | |
if (_userValidator != null) | |
{ | |
var results = _userValidator.Validate(this); | |
if (results != null && results.Errors.Any()) | |
{ | |
var errors = string.Join(Environment.NewLine, results.Errors.Select(x => x.ErrorMessage).ToArray()); | |
return errors; | |
} | |
} | |
return string.Empty; | |
} | |
} | |
public event PropertyChangedEventHandler PropertyChanged; | |
protected virtual void OnPropertyChanged(string propertyName) | |
{ | |
PropertyChangedEventHandler handler = PropertyChanged; | |
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); | |
} | |
} | |
} |
Wow. I totally forgot that I wrote this gist.
@mrNo0b - I'm not sure. I looked through the fluentvalidation documentation and I didn't find anything related to the performance implications of using the options.IncludeProperties(...) option. My guess would be that would improve performance, but I have no evidence to support it.
What if I wanna check if my name is unique among all the usernames present in my database.
How would you integrate this rule. Let's suppose I'm working with EF.
@moh-a-med Making some assumptions here:
- Assuming that you're using EF
- Assuming that you're using the built in UserManager
The process would be to inject in the UserManager and then create a rule with the .Must(...) method. You would look up a user by username. If no user is returned, then the username is unique.
what should i consider if am going to use this with combox or datepicker ?
DatePicker should be pretty straightforward. ComboBox may be a bit of a pain because of it doesn't seamlessly integrate with the MVVM pattern. I would say try it and see what problems you run into.
That's what I call Life Saver!! Thank you very much!
question: In
UserViewModel.cs
ln54, if I change the code to this:it will only check single rule from what I understood, will it be "faster"?