Search code examples
c#wpfmvvmlight

Enable Disable save button during Validation using IDataErrorInfo


How to disable/enable a button while doing validation using IDataErrorInfo?

I am using MVVM using GalaSoft light Framework. In my Model class I have implemented IDataErrorInfo to display the error messages.

public string this[string columnName]
{
    get
    {
        Result = null;
        if (columnName == "FirstName")
        {
            if (String.IsNullOrEmpty(FirstName))
            {
                Result = "Please enter first name";
            }
        }
        else if (columnName == "LastName")
        {
            if (String.IsNullOrEmpty(LastName))
            {
                Result = "Please enter last name";
            }
        }

        else if (columnName == "Address")
        {
            if (String.IsNullOrEmpty(Address))
            {
                Result = "Please enter Address";
            }
        }

        else if (columnName == "City")
        {
            if (String.IsNullOrEmpty(City))
            {
                Result = "Please enter city";
            }
        }

        else if (columnName == "State")
        {
            if (State == "Select")
            {
                Result = "Please select state";
            }
        }

        else if (columnName == "Zip")
        {
            if (String.IsNullOrEmpty(Zip))
            {
                Result = "Please enter zip";

            }
            else if (Zip.Length < 6)
            {
                Result = "Zip's length has to be at least 6 digits!";

            }
            else
            {
                bool zipNumber = Regex.IsMatch(Zip, @"^[0-9]*$");

                if (zipNumber == false)
                {
                    Result = "Please enter only digits in zip";


                }
            }
        }
        else if (columnName == "IsValid")
        {
            Result = true.ToString();
        }

        return Result;

    }
}

Screenshot: https://i.sstatic.net/kwEI8.jpg

How to disable/enable save button. Kindly suggest?

Thanks


Solution

  • The Josh Smith Way of doing this is to create the following methods in the Model:

    static readonly string[] ValidatedProperties =
    {
        "Foo",
        "Bar"
    };
    
    /// <summary>
    /// Returns true if this object has no validation errors.
    /// </summary>
    public bool IsValid
    {
        get
        {
            foreach (string property in ValidatedProperties)
            {
    
                if (GetValidationError(property) != null) // there is an error
                    return false;
            }
    
            return true;
        }
    }
    
    private string GetValidationError(string propertyName)
    {
        string error = null;
    
        switch (propertyName)
        {
            case "Foo":
                error = this.ValidateFoo();
                break;
    
            case "Bar":
                error = this.ValidateBar();
                break;
    
            default:
                error = null;
                throw new Exception("Unexpected property being validated on Service");
        }
    
        return error;
    }
    

    The ViewModel then contains a CanSave Property that reads the IsValid property on the Model:

    /// <summary>
    /// Checks if all parameters on the Model are valid and ready to be saved
    /// </summary>
    protected bool CanSave
    {
        get
        {
            return modelOfThisVM.IsValid;
        }
    }
    

    Finally, if you are using RelayCommand, you can set the predicate of the command to the CanSave property, and the View will automatically enable or disable the button. In the ViewModel:

    /// <summary>
    /// Saves changes Command
    /// </summary>
    public ICommand SaveCommand
    {
        get
        {
            if (_saveCommand == null)
                _saveCommand = new RelayCommand(param => this.SaveChanges(), param => this.CanSave);
    
            return _saveCommand;
        }
    }
    

    And in the View:

    <Button Content="Save" Command="{Binding Path=SaveCommand}"/>
    

    And that's it!

    PS: If you haven't read Josh Smith's article yet, it will change your life.