Integrating WPF Validation into MVVM
I have some ValidationRules that are working correctly. I'm just wondering what the best way to integrate this with my ViewModel would be.
I have an (overly simple) method—HasAnyErrors—that walks the control tree checking for errors, but I'm not sure how to expose these results to my ViewModel. In other words, what should I do if I have an ICommand that can only execute if there are not validation errors?
The best I could come up with was just handling the click event of the button, and then manually invoking the ViewModel's command if there were no errors.
private void Button_Click_RunCommand(object sender, RoutedEventArgs e) {
if (this.HasAnyErrors())
return;
(this.DataContext as SomeViewModel).SomeCommand.Execute(null);
}
It's not the most elegant solution; but it appears to work. Is there a more elegant solution available?
BREAK
For completeness here are the validation methods (most will be extension methods before too long). They (appear to) work fine, but I'm sure at least someone will wonder what they look like.
bool HasAnyErrors() {
List<string> errors = new List<string>();
GetErrors(this, errors);
return errors.Any();
}
void GetErrors(DependencyObject obj, List<string> errors) {
foreach (UIElement child in LogicalTreeHelper.GetChildren(obj).OfType<UIElement>()) {
if (child is TextBox)
AddErrorIfExists(child as UIElement, errors);
GetErrors(child, errors);
}
}
private void AddErrorIfExists(UIElement element, List<string> errors) {
if (Validation.GetHasError(element))
errors.Add(Validation.GetErrors(element)[0].ErrorContent.ToString());
}
Presumably you could determine whether or not their are any validation methods against the view model itself instead of using Validation.GetErrors()
- if you are implementing IDataErrorInfo
then it is probably going to be simpler.
If that is the case you can take the validation state of the view model into account within the CanExecute
method of the command to which the button is bound.
You might be interested in the BookLibrary sample application of the WPF Application Framework (WAF). The class BookView.xaml.cs shows how to synchronize the WPF validation state with the underlying ViewModel.
In the sample it is used for parsing errors. In this concrete case a parsing error comes when the user enters 'abc' in the Pages TextBox. Pages is bound to an integer value and so 'abc' cannot be parsed.
精彩评论