简体   繁体   中英

WPF Datagrid new row validation

I made a simple WPF application with DataGrid wchich is binded to the List with Employee objects:

public class Employee
{
    private string _name;

    public int Id { get; set; }


    public string Name
    {
        get { return _name; }
        set
        {
            if (String.IsNullOrEmpty(value))
                throw new ApplicationException("Name cannot be empty. Please specify the name.");
            _name = value;
        }
    }

As you can see, I want to prevent creating Employees without set Name property. So, I made a validation rule:

public class StringValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        string str = value as string;
        if (String.IsNullOrEmpty(str))
            return new ValidationResult(false, "This field cannot be empty");
        else
            return new ValidationResult(true, null);
    }
}

The XAML for Name field is the following:

<DataGridTextColumn Header="Name" 
                                ElementStyle="{StaticResource datagridElStyle}" >
                <DataGridTextColumn.Binding>
                    <Binding Path="Name" Mode="TwoWay" NotifyOnValidationError="True" ValidatesOnExceptions="True" UpdateSourceTrigger="PropertyChanged" >
                        <Binding.ValidationRules>
                            <emp:StringValidationRule/>
                        </Binding.ValidationRules>
                    </Binding>
                </DataGridTextColumn.Binding>
            </DataGridTextColumn>

If I try to edit the name of existing employee row in DataGrid and set it to empty string, datagrid marks the wrong field and does not allow to save row. This is correct behavior.

But if I create a new row and press Enter on keyboard, this new row is created with _name set to NULL, and validation does not work. I guess this is because DataGrid calls default constructor for new row object and sets _name field to NULL.

What is the correct way of validation for new rows?

You could implement IDataError on your Employee object. There's a good page on this here .

I actually came across the same issue, but because I have been using MVC Data Annotations as shown here by Karl Shifflett: http://bit.ly/18NCpJU . I had initially thought this was a good idea, but I now realize it may have been the intent of Microsoft not to include MVC Data Annotations as these seem more appropriate for submitting a form, but not an application where data persists and can be edited across sessions, but I digress..

Here's what I did for a temporary work-around. The long-term solution will be to implement IDataError:

// BusinessEntityBase is what allows us to
// use MVC Data Annotations ( http://bit.ly/18NCpJU )
public class MyModel : BusinessEntityBase
{
    private string _name;
    private List<Action> _validationQueue = new List<Action>();
    private Timer _timer = new Timer { Interval = 500 };

    [Required( AllowEmptyStrings = false )]
    public string Name
    {
        get
        {
            return this._name;
        }
        set
        {
            var currentValue = this._name;
            this._name = value;
            base.RaisePropertyChanged("Name");

            this.AddValidationAction( "Name", currentValue, value  );
        }
    }

    private void AddValidationAction<T>( string Name,  T currentValue, T newValue)
    {
        Action validationAction = 
            () => 
                base.SetPropertyValue( Name, ref currentValue, newValue );
        _validationQueue.Add(validationAction);
        this._timer.Enabled = true;
    }

    private void ProcessValidationQueue(object sender, ElapsedEventArgs e)
    {
        if( _validationQueue.Count > 0 )
        {
            while ( _validationQueue.Count > 0)
            {
                _validationQueue[0].Invoke();
                _validationQueue.RemoveAt( 0 );
            }
        }

        this._timer.Enabled = false;
    }

    public MyModel()
    {
        _timer.Enabled = false;
        _timer.Elapsed += this.ProcessValidationQueue;
        _timer.Start();
    }
}

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