Using BindingValidationError to Add Messages to a Validation Summary in Silverlight

 

If you aren’t familiar with it, the ValidationSummary control in Silverlight automatically shows validation exceptions for any controls within its same container element.  That means if you add it to a grid or StackPanel that is full of bound controls, it will capture any validation exceptions from those bindings.  It also gives you all kinds of useful functionality, like taking you to the invalid control when clicking on an item, and even removing the message when the input is corrected.

For example, these two textboxes are bound to FirstName and MiddleInitial properties, and MiddleInitial is required to be a string no longer than 1 character.

This works automatically, because the textboxes and the ValidationSummary are all inside the same layout grid.

But, if for some reason, we have to move the ValidationSummary outside, to another grid:

 

Oh no!  The validation exceptions are no longer handled, and the ValidationSummary remains blank.

That’s because the ValidationSummary always hooks into a certain event of its parent container, in order to handle any ValidationExceptions from sibling controls.  Luckily, we can use that same event to hook it back up again, even when it is outside the layout control.

The event is BindingValidationError, and it is triggered each time a ValidationException is thrown due to a binding setter, and also each time a  setter action makes a previously invalid input valid again.  So both the adding and the removal of ValidationSummaryItems can be handled in the same place.  Here we are handling the event on the grdDataEntry, or the grid containing our textbox controls.  You can use the Context property to set and find any messages that match a particular control.

private void grdDataEntry_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
    if (e.Action == ValidationErrorEventAction.Added)
    {
        ValidationSummaryItem vsi = new ValidationSummaryItem() 
        { Message = e.Error.ErrorContent.ToString(), Context = e.OriginalSource };
        vsi.Sources.Add(
            new ValidationSummaryItemSource(String.Empty, e.OriginalSource as Control));
        valSum.Errors.Add(vsi);
    }
    else
    {
        ValidationSummaryItem valsumremove = 
            valSum.Errors.FirstOrDefault(v => v.Context == e.OriginalSource);
        if (valsumremove != null)
        {
            valSum.Errors.Remove(valsumremove);
        }
    }
}

 

Now the validation messages appear as the ValidationSummaryItems are added and removed.  An invalid entry into the MiddleInitial field shows up in my ValidationSummary:

And when I correct the input, the message is removed!

 

So, the ValidationSummary can indeed be completely functional even when you are unable to place it in the same container as your bound controls.

comments powered by Disqus

Get weekly updates in your inbox!