I'm not exactly sure of the best way to request this, so here goes:
I'm hoping for more robust validation and EndEdit functionality in a future release. The situation that seems like too much work right now is this: We have validation logic in our business entity. We have a DataGrid bound to a list of the business entities. When the user edits a row and moves away from the grid (without explicity saving the row), it would be nice to automatically cause an EndEdit to trigger which would then perform the validation and allow the grid to not leave the focus if there's a data validation error. We have events and overrides wired up now to support this, but we have no way of telling the user the validation failed and keep the user in the grid. We just have to Cancel the changes without the user knowing.
In addition, it would be nice to be able to bind cell validation to the entities in a better way. For example, allowing validation at a row level and allowing for a validation routine in the entity for the entire row - rather than one by one validation on each cell.
Are there ways of doing some of this already? Here's my current code for losing the focus and trying to save:
private void IsKeyboardFocusWithinChangedEvent(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue.ToString() == bool.FalseString)
{
DataRow row = GetDeductionRowFromDeductionObject((DeductionEntity) DeductionsGrid.CurrentItem);
if ((row != null) && (row.IsBeingEdited))
{
try
{
row.EndEdit();
}
catch (DataGridException)
{
// Not sure what to do here. It's not saving the row, but we would rather show a validation error to the user.
// Don't know how to abandon the UI request that was just made.
}
}
}
}
For the Validation, we're currently doing this (but it's a pretty lousy hack):
<xcdg:Column FieldName="DeductionType" Title="Deduction Type" CellContentTemplate="{StaticResource DeductionTypeTemplate}">
<xcdg:Column.CellValidationRules>
<local:EntityFieldValidationRule/>
</xcdg:Column.CellValidationRules>
</xcdg:Column>
public class EntityFieldValidationRule : CellValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo, CellValidationContext cellValidationContext)
{
string propertyName = Util.GetStringValue(cellValidationContext.Cell.ParentColumn.FieldName);
string title = Util.GetStringValue(cellValidationContext.Cell.ParentColumn.Title);
DeductionEntity deduction = cellValidationContext.DataItem as DeductionEntity;
if (deduction == null)
throw new Exception("The Deduction value is null and cannot be validated.");
string validationString = deduction.Validate(propertyName, title, value);
if (validationString == null)
return new ValidationResult(true, null);
return new ValidationResult(false, validationString);
}
}
(in the business object:)
public string Validate(string propertyName, string title, object value)
{
switch (propertyName)
{
case "Description":
if ((DeductionRecurrenceSource == DeductionRecurrenceSources.Select) &&
(
String.IsNullOrEmpty(Util.GetStringValue(value))))
return title + " is a required field";
break;
case "CurrentBalance":
if (Util.GetDoubleValue(value) <= 0)
return title + " must be great than 0";
break;
default:
throw new Exception("The Property '" + propertyName + "' was not handled in the Validate logic for DeductionEntity");
}
return null;
}