views:

1291

answers:

2

Hi,

I m trying to do a simple validation on textbox, its a required field and cannot be empty. Initially value will be empty so when user do not enter any value into the field and directly clicks Save button then valitaion is not triggered. It works fine when user types something and then deletes the value from it then it works perfectly and shows the validation error message. Is there anyway to do validation check after user clicks save button.

    [Display(Name = "Sometext", Description = "Some text")]
    [Required(ErrorMessage = "Required Field")]
    public string SomeText
    {
        get
        {
            return _someText; 
        }
        set
        {
            if (_someText== value &&
                value != string.Empty)
            {
                return;
            }

            Validate(value, "someText");//This calls Validator.ValidateProperty method
            _someText= value;
            FirePropertyChanged("someText");
        }
    }

Please suggest!

Thanks in advance Sai

+1  A: 

Josh Twist has given a work around for this. This works perfectly..

http://www.thejoyofcode.com/Silverlight_Validation_and_MVVM_Part_II.aspx

Sai
true, i've moved over to his approach aswell, it has flaws no doubt, but its much better than the build-in alternative
Neil
A: 

You could also call on your command execution

Validator.ValidateObject(this, new ValidationContext(this,null,null),true);

This should validate all properties on your viewmodel, assuming you call this from your viewmodel

edit: Response to comment

You could have a property like so (below) in your BaseViewModel (every viewmodel extends BaseViewModel), and then disallow save with a proper message

    protected bool HasValidationErrors
        {
            get
            {
                try { 
                      Validator.ValidateObject(this, new ValidationContext(this, null, null), true); 
                      return false; 
                    }
                catch (ValidationException) { return true; }

            }
        }

In your command you would call it like so

public void SaveCommandExecuted(object parameter)
    {   

        if (HasValidationErrors)
        {
            ShowValidationError();
        }
    }

Another thing, you could try is to bind the View event for validation errors to a listener in you viewmodel

    MyProgram.ViewModels.BaseViewModel baseViewModel = page.Resources["DataSource"] as MyProgram.ViewModels.BaseViewModel;

    page.BindingValidationError += new EventHandler<ValidationErrorEventArgs>(baseModel.OnValidationError);

then in your BaseViewModel

private ObservableCollection<ValidationError> Errors { get; set; }


public void OnValidationError(object sender, ValidationErrorEventArgs e)
        {
            switch (e.Action)
            {
                case ValidationErrorEventAction.Added:
                    Errors.Add(e.Error);
                    break;
                case ValidationErrorEventAction.Removed:
                    Errors.Remove(e.Error);
                    break;
                default:
                    break;
            }
        }

then modify HasValidationErrors to

protected bool HasValidationErrors
        {
            get
            {
                try { 
                      Validator.ValidateObject(this, new ValidationContext(this, null, null), true); 
                      return this.Errors.Count != 0; 
                    }
                catch (ValidationException) { return true; }

            }
        }
Neil
Yes, That will Validate all the properties but it doesnot propagate the validation exception to UI. instead it will throw an exception.
Sai
Instead of catching the exception, you could use TryValidateObject()
Kevin