I\'m trying to get WPF validation to work within the MVVM pattern.
In my View, I can validate a TextBox like this which gets handled by the code-behind method \"Hand
I don't know if this will help you, but I'll offer it all the same.
Also, I'm using Silverlight, not WPF.
I don't specify any validation in my Views, neither in the code behind nor the xaml. My View has only data bindings to properties on the ViewModel.
All my error checking/validation is handled by the ViewModel. When I encounter an error, I set a ErrorMessage property, which is bound to the view as well. The ErrorMessage textblock (in the view) has a value converter which hides it if the error is null or empty.
Doing things this way makes it easy to unit test input validation.
Here's a way to do this using Expression Blend 3 behaviors. I wrote a ValidationErrorEventTrigger because the built-in EventTrigger doesn't work with attached events.
View:
<TextBox>
<i:Interaction.Triggers>
<MVVMBehaviors:ValidationErrorEventTrigger>
<MVVMBehaviors:ExecuteCommandAction TargetCommand="HandleErrorCommand" />
</MVVMBehaviors:ValidationErrorEventTrigger>
</i:Interaction.Triggers>
<TextBox.Text>
<Binding Path="FirstName"
Mode="TwoWay"
NotifyOnValidationError="True">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
ViewModel: (could be unchanged, but here's a look at how I dug into the validation arguments to find the error message when using the exception validation rule)
public ICommand HandleErrorCommand
{
get
{
if (_handleErrorCommand == null)
_handleErrorCommand = new RelayCommand<object>(param => OnDisplayError(param));
return _handleErrorCommand;
}
}
private void OnDisplayError(object param)
{
string message = "Error!";
var errorArgs = param as ValidationErrorEventArgs;
if (errorArgs != null)
{
var exception = errorArgs.Error.Exception;
while (exception != null)
{
message = exception.Message;
exception = exception.InnerException;
}
}
Status = message;
}
ValidationErrorEventTrigger:
public class ValidationErrorEventTrigger : EventTriggerBase<DependencyObject>
{
protected override void OnAttached()
{
Behavior behavior = base.AssociatedObject as Behavior;
FrameworkElement associatedElement = base.AssociatedObject as FrameworkElement;
if (behavior != null)
{
associatedElement = ((IAttachedObject)behavior).AssociatedObject as FrameworkElement;
}
if (associatedElement == null)
{
throw new ArgumentException("Validation Error Event trigger can only be associated to framework elements");
}
associatedElement.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.OnValidationError));
}
void OnValidationError(object sender, RoutedEventArgs args)
{
base.OnEvent(args);
}
protected override string GetEventName()
{
return Validation.ErrorEvent.Name;
}
}