DataGrid validation/IEditableObject behaviour

Jun 23, 2009 at 10:30 AM
Edited Jun 23, 2009 at 1:51 PM

Dear all,

I am working on a LOB project where we are using Wpf and I cannot understand the behaviour of the DataGrid. I have put together a sample project using various recommendations.

Here are some notes about the project:
1) All business objects implement IEditableObject , IDataErrorInfo   and INotifyPropertyChanged interfaces.
2) The validation rules of the DataGrid is bound to IDataErrorInfo using the technique described in this article .

EDIT: I have removed the long code listing, if you want to see my code please go here or download the sample project.

Here are my questions/problems:

1) Where the grid loads it should display a validation problem for the one person who does not have an age set, do can I achieve this?
2) If I enter something incorrect and tab out of the field pressing Esc will not fire CancelEdit, how come? Even if I go back into the field pressing Esc will not fire CancelEdit but the value still change back, but the underlying property is not changed.
3) If I enter something incorrect in Age and tab out of the field and return, F2 will not allow me to correct the value.
4) If I enter something incorrect then I cannot change any other field before the validation problem is corrected, how can I allow this?
5) Try the following
   a) enter -5 in age (you should get a validation error indication)
   b) tab out of the field
   c) tab back into the field and enter 500
   e) tab out of the field
   f) tab back into the field and hit Esc - why does the validation indication disappear but the value 500 remains?

Coordinator
Jun 23, 2009 at 9:57 PM

Hi Pawaw,

1) If you want your validation rule to be applied from the beginning of the application run (and not when you try to update values) change ValidationStep to "RawProposedValue" (right now it is set to "UpdatedValue").

3) This is likely a bug -- we will investigate.

4) This is by design; you will need to change your rules so they don't return an error.

5) Pressing esc causes the DataGrid to intentionally not apply the validation rule.

Hope some of this helps!

Alexis

Jun 24, 2009 at 9:31 AM

Hi Alexis,

Thank you for you guidance.

Do you know of a way for me to override the grid behaviour mentioned in 4)? Imagine you have an object with StartData and EndDate (and validation implements that StartDate must be prior to EndDate), lets say that the default value of StartDate is 1 Jan 2009 and for EndDate 3 Jan 2009, now if the user wants to correct the StartDate to 5 Jan 2009 and EndDate to 7 Jan 2009 he must change the EndDate before the StartDate due to this design.

To solve my edit problem in 2) and 5) I have made the following interface

    public interface IEditableObjectProperty
    {
        void CancelEdit(String propertyName);
    }

This interface allows an object to support cancellation of user inputs to a specific property. In the DataGrid I then subscribe to the CellEditEnding event:

        void dataGrid_CellEditEnding(object sender, Microsoft.Windows.Controls.DataGridCellEditEndingEventArgs e)
        {
            if (e.EditAction == DataGridEditAction.Cancel)
            {
                IEditableObjectProperty obj = e.Row.Item as IEditableObjectProperty;
                String property = ((Binding)e.Column.ClipboardContentBinding).Path.Path;
                obj.CancelEdit(property);
            }
        }

In my person class IEditableObjectProperty is implement like this:

        public void CancelEdit(string propertyName)
        {
            if (inTxn)
            {
                PropertyInfo pi = this.GetType().GetProperty(propertyName);
                object backupValue = pi.GetValue(backupData, null);
                pi.SetValue(this, backupValue, null);
            }
        }

If anybody is interested here is the new full project code.

May 2, 2011 at 5:14 PM

Hi Pawaw, 

Do you know how to put your example working on .net Framework 4? because I tried to migrate your code but It seems that the post validation after the 2nd ESC is not getting called. :(

Oct 19, 2011 at 12:14 PM

As for the second issue of dates, I would solve this by updating the end date in the code behind/view model after the start date is changed. Here's an example for what the property would look like in the view model:

        private DateTime _startDate;
        public DateTime StartDate
        {
            get { return _startDate; }
            set
            {
                _startDate = value;
                this.UpdateEndDate();
                this.OnPropertyChanged("StartDate");
            }
        }

        private DateTime _endDate;
        public DateTime EndDate
        {
            get { return _endDate; }
            set
            {
                _endDate = value;
                this.OnPropertyChanged("EndDate");
            }
        }

        private void UpdateEndDate()
        {
            this.EndDate = this.StartDate.AddDays(1);
        }

Then I would simply have the property on the grid bound to this, and the end date should always be set past the start date when the start date is changed. If you don't like this, you could also use a code behind with a cell value changed event that would also update the end date.

That's just my first thought. But there might also be other ways around it.

Jan 3, 2013 at 1:28 PM

Hi,

The BeginEdit is called twice. And I have to hit ESC two times to invoke CancelEdit. Any idea how to get over that bug ?

http://stackoverflow.com/questions/4450878/wpf-datagrid-calls-beginedit-on-an-ieditableobject-two-times

Apr 30, 2015 at 9:52 PM
Following the note 5) if we use UpdateSourceTrigger="PropertyChanged" the validation indication won't disappear. The value is reverted due the implementation of the IEditableObject but the validation indication never disappear following the steps in note 5)