This is a migrated thread and some comments may be shown as answers.

How to check if any cell was modified in RowValidating event handler

5 Answers 194 Views
GridView
This is a migrated thread and some comments may be shown as answers.
AlexPinsker
Top achievements
Rank 1
AlexPinsker asked on 12 May 2011, 09:17 AM
Is it possible to check whether any cell was actually modified in RowValidating event handler.
Probably it's possible to do it comparing all cell values with GridViewRowValidatingEventArgs.OldValues, but may be there is a better way to find it?

Thanks
   Alex

5 Answers, 1 is accepted

Sort by
0
Accepted
Dimitrina
Telerik team
answered on 13 May 2011, 08:07 AM
Hi AlexPinsker,

 On RowValidating event you could compare the e.OldValue to the values in e.Row (as you have mentioned). You can as well cast e.Row to your business object and compare e.OldValues with its properties. There is not a direct way to know if any changes have been made. 

Basically the validation could be done on data lever as well, rather that on UI level. Could you please specify what exactly you would like to do regarding the validation, so that we could suggest you another way of validating the data? 

All the best,
Didie
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
AlexPinsker
Top achievements
Rank 1
answered on 13 May 2011, 08:13 AM
Hi Didie,
I'm trying to achieve the following functionality:
When user changed any cell in the row I want to display notification asking him to provide a reason for the change and save this reason (for auditing purposes). So, if user just entered 'edit mode' and then jumped to another row without actually changing data - I don't want to show him this notification.

(I want to ask user only after I've validated that his changes are valid and hence I do it in RowValidating handler.  Is there a better way to achieve this functionality)?

Thanks
   Alex
0
Accepted
Dimitrina
Telerik team
answered on 16 May 2011, 08:32 AM
Hello AlexPinsker,

 In your scenario you are right to use the RowValidating event. In order to avoid comparing all cell values with GridViewRowValidatingEventArgs.OldValues you could define a private variable hasChanges. Then in CellValidated event handler you could compare e.OldValue with e.NewValue and set hasChanges to the result of the comparison.

In RowValidating after you finish your logic, you should set hasChanges back to false.

If you have any more questions regarding the validation, please feel free to contact us!

Regards,
Didie
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
AlexPinsker
Top achievements
Rank 1
answered on 16 May 2011, 11:00 AM
Thanks, that's completely answers my question.
Alex
0
Lawrence
Top achievements
Rank 2
Iron
answered on 05 Aug 2013, 02:41 PM
I wrote a generic RowValidating Method that uses reflection to compare the new values against the old ones.  In this particular example, your object will need to inherit from a class that has a "Save" method.  In my case "ModelTransactionBase"       

/// <summary>
/// Rows the validating.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="GridViewRowValidatingEventArgs"/> instance containing the event data.</param>
public static void RowValidating<T>(object sender, GridViewRowValidatingEventArgs e) where T : ModelTransactionalBase
{
    try
    {
        bool hasChanged = false;
        var entity = (T)e.Row.Item;
 
        if (e.EditOperationType == GridViewEditOperationType.Insert)
        {
            hasChanged = true;
        }
        else
        {
            Type entityType = entity.GetType();
            var properties = new List<PropertyInfo>(entityType.GetProperties());
 
            // See if the old values are different from the new ones.
            foreach (PropertyInfo propertyInfo in properties)
            {
                foreach (KeyValuePair<string, object> value in e.OldValues)
                {
                    if (propertyInfo.Name.Equals(value.Key))
                    {
                        Type newType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
                        var oldValue = (value.Value == null) ? null : Convert.ChangeType(value.Value, newType);
                        var newValue = propertyInfo.GetValue(entity);
 
                        if (newValue == null && oldValue == null)
                        {
                            hasChanged = false;
                            break;
                        }
                        else if (newValue == null || oldValue == null)
                        {
                            hasChanged = true;
                            break;
                        }
                        else if (value.Value.GetType() != newType)
                        {
                            hasChanged = true;
                            break;
                        }
                        else if (!propertyInfo.GetValue(entity).Equals(oldValue))
                        {
                            hasChanged = true;
                            break;
                        }
                    }
                }
 
                // Once one property has changed, no need to continue checking the remainder.
                if (hasChanged)
                {
                    break;
                }
            }
        }
 
        if (hasChanged)
        {
            entity.Save();
        }
    }
    catch (ValidationException vex)
    {
        RadWindow.Alert(vex.Message, delegate(object windowSender, WindowClosedEventArgs args) { e.IsValid = false; });
    }
}


Which can be called from your RowsValidating event of your RadGridView.  "YourObject" is what's bound to the grid and inherits from what I have below as "ModelTransactionalBase".

private void RadGridViewTemplatesRowValidating(object sender, GridViewRowValidatingEventArgs e)
{                          
      RadGridViewHelper.RowValidating<YourObject>(sender, e);
}

ModelTransactionBase.  ModelBase Inherits from "Telerik.Windows.Controls.ViewModelBase", and doesn't provide any value for this example, but is specific to my application.

internal abstract class ModelTransactionalBase : ModelBase
{ 
    #region Abstract Methods
    /// <summary>
    /// Saves this instance.
    /// </summary>
    public abstract void Save();
    #endregion
}
Tags
GridView
Asked by
AlexPinsker
Top achievements
Rank 1
Answers by
Dimitrina
Telerik team
AlexPinsker
Top achievements
Rank 1
Lawrence
Top achievements
Rank 2
Iron
Share this question
or