简体   繁体   中英

WPF MVVM Validation Using IDataErrorInfo

I have created a Person MVVM model which needs to be validated. I am using IDataErrorInfo class and validating the user. But when the screen loads the textboxes are already red/validated indicating that the field needs to be filled out. I believe this is because I bind the PersonViewModel in the InitializeComponent. I tried to use LostFocus for updatetriggers but that did not do anything.

Here is my PersonViewModel:

 public class PersonViewModel : IDataErrorInfo
    {
        private string _firstName;
        private string _lastName; 

        public string LastName { get; set; }

        public string Error
        {
            get { throw new NotImplementedException(); }
        }

        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; }
        }



        public string this[string columnName]
        {
            get
            {
                string validationResult = String.Empty; 

                switch(columnName)
                {
                    case "FirstName":
                        validationResult = ValidateFirstName();
                        break; 

                    case "LastName":
                        validationResult = ValidateLastName();
                        break; 

                    default:
                        throw new ApplicationException("Unknown property being validated on the Product");
                }

                return validationResult; 
            }
        }

        private string ValidateLastName()
        {
            return String.IsNullOrEmpty(LastName) ? "Last Name cannot be empty" : String.Empty;
        }

        private string ValidateFirstName()
        {
            return String.IsNullOrEmpty(FirstName) ? "First Name cannot be empty" : String.Empty;
        }



    }

Here is the XAML:

  <StackPanel>
        <TextBlock>First Name</TextBlock>
        <TextBox Text="{Binding FirstName, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}" Background="Gray"></TextBox>
        <TextBlock>Last Name</TextBlock>
        <TextBox Text="{Binding LastName, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}" Background="Gray"></TextBox>
    </StackPanel>

MainWindow.cs:

  public MainWindow()
        {
            InitializeComponent();


            _personViewModel = new PersonViewModel();

            this.DataContext = _personViewModel; 



        }

Am I missing something? I do not want the validation to be fired when the screen loads. I only want it to be fired when the user looses the focus of the textboxes.

Rather than fight the tide of how WPF works by default, consider redefining the UI so that the error display 'fits' the scenario of screen load as well as data entry error. Besides, a user should have some hints on a blank form of what is needed.

Create a method to do your validation, and store the validation results in a dictionary:

private Dictionary<string, string> _validationErrors = new Dictionary<string, string>();

public void Validate(string propertyName)
{
    string validationResult = null;
    switch(propertyName)
    {
        case "FirstName":
            validationResult = ValidateFirstName();
            break; 
        }
        //etc.
    }

    //Clear dictionary properly here instead (You must also handle when a value becomes valid again)
    _validationResults[propertyName] = validationResult;
    //Note that in order for WPF to catch this update, you may need to raise the PropertyChanged event if you aren't doing so in the constructor (AFTER validating)
}

Then update your ViewModel to:

  1. Have the indexer return a result from the _validationErrors instead, if present.
  2. Call Validate() in your setters.
  3. Optionally, in Validate(), if the propertyName is null, validate all properties.

WPF will call the indexer to display errors, and since you are returning something, it will think that there are errors. It won't unless you explictly call Validate() with this solution.

EDIT: Please also note that there is now a more efficient way of implementing validation in .NET 4.5 called INotifyDataErrorInfo .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM