Silverlight – About validation when binding to custom forms – Part 2 using Silverlight 4

In my first part about validation and binding to custom forms I wrote about how we could with some small hack enable the Validation Tooltip for a bounded control manually when we press a button. In this post I will instead use Silverlight 4 with Commanding and the INotifyDataErrorInfo interface to “manually” show the validation tooltip for a specific control.

Thanks to the new INotifyDataErrorInfo interface, we can now notify about an error anywhere in the code to make sure the validation tooltip will be displayed for a control bound to a specific property. To understand the INotifyDataErrorInfo interface, you can take a look at my post about the interface: Silverlight 4 and Asynchronous Validation with INotifyDataErrorInfo.

I will first start with showing two helper method I have created to Add and Remove an error and also notify the UI when the error occurs:

public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
private Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();

protected virtual void RemoveValidationErrorMessage(string propertyName)
{
    if (_errors.ContainsKey(propertyName))
        _errors.Remove(propertyName);

    if (ErrorsChanged != null)
        ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}


protected virtual void AddValidationErrorMessage(string propertyName, string validationErrorMessage)
{
     if (!_errors.ContainsKey(propertyName))
           _errors.Add(propertyName, new List<string> { "MyTextBox can't be null or empty" });

      if (ErrorsChanged != null)
          ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}

 

The Remove and Add methods are added to a base class of my ViewModel. Within the ViewModel I have added some validation code for a TextBox:

 private bool ValidateMyTextBox(string valueToValidate)
{
    if (string.IsNullOrEmpty(valueToValidate))
    {
         base.AddValidationErrorMessage("MyTextBox", "MyTextBox can't be null or empty");
         return false;
    }
    else
    {
         base.RemoveValidationErrorMessage("MyTextBox");
          return true;
     }
}


Note: In this post I only have one TextBox and a Button added to the XAML. The ViewModel used has one property called “MyTextBox” bounded to the TextBox in the XAML, so that is the reason why the AddValidationErrorMessage has the first proepertyName argument set to “MyTextBox” and is not created as a generic method.

Here is the XAML I have used in this example:

<UserControl 
    ...
    xmlns:view="clr-namespace:Commanding.ViewModel">

    <UserControl.Resources>
        <view:CommandingViewModel x:Name="myView"/>
    </UserControl.Resources>
    
    <Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource myView}">

        <StackPanel VerticalAlignment="Center">

            <TextBox
                   Text="{Binding MyTextBox, Mode=TwoWay, ValidatesOnExceptions=True}" .../>
            <Button 
                  Command="{Binding SaveCommand}" .../>

        </StackPanel>
       
        
    </Grid>
</UserControl>


Here is the ViewModel:

public class CommandingViewModel : BaseViewModel
{
    private string _myTextBox;

   private ICommand _saveCommand;

   public string MyTextBox
   {
       get { return _myTextBox; }
       set
       {
          ValidateMyTextBox(value);
                
          _myTextBox = value;

          base.NotifyPropertyChanged("MyTextBox");
       }
    }

    public ICommand SaveCommand
    {
       get
       {
           if (_saveCommand == null)
               _saveCommand = new Command(p =>
                                        {
                                            if (IsValid())
                                                this.MyTextBox = "Save Button Pressed";
                                         });
                                        
           return _saveCommand;
       }
   }

   private bool IsValid()
   {
      var isValid = true;

      if (!ValidateMyTextBox(MyTextBox))
           isValid = false;

      return isValid;
   }


  private bool ValidateMyTextBox(string valueToValidate)
  {
     if (string.IsNullOrEmpty(valueToValidate))
     {
         base.AddValidationErrorMessage("MyTextBox", "MyTextBox can't be null or empty");
         return false;
     }
     else
     {
         base.RemoveValidationErrorMessage("MyTextBox");
         return true;
     }
  }
}

The part to focus on here is the SaveCommand property. As you can see the IsValid method is called when the Command is executed. The IsValid method will do an extra validation to make sure the MyTextBox is valid or not. The reason why this is done is due to a TwoWay binding issue mentioned in my Silverlight – About validation when binding to custom forms blog post. If we don’t change the value of the TextBox the setter of the bounded property will not be called when clicking on a button and no validation on the TextBox will be made because of that. The IsValid method will make sure to solve that issue. Thanks to the INotifyDataErrorInfo interface we can anytime and anywhere in the code notify if a validation fails and make sure the validation tooltip will be displayed for a control bind to a specific property. So the IsValid method will make sure the TextBox where the MyTextBox property is bound to will show the validation tooltip and error message if the validation fails when the Command is executed (when the Button is pressed). When using Silverlight 4, we don’t need to do some extra hack to show the validation tooltip when we press a button, isn’t that wonderful?!

 

If you want to know when I publish a new blog post, then you can follow me on twitter: http://www.twitter.com/fredrikn

No Comments