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
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?
Didie
the Telerik team
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
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!
Didie
the Telerik team
Alex
/// <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
}