Created
April 24, 2014 06:02
-
-
Save GrantByrne/11243164 to your computer and use it in GitHub Desktop.
Using Fluent Validation with WPF - Dead Simple
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is there a reason why you use a int for indexing even though you defined a overload which takes a column name?
Additionally, could it be that you have copy paste error, because all ErrorTemplates use [0] not [0],[1],[2], ...?