I want to display a list of rows to the user, and let them edit those rows as they want. If a row has bad values then I want to indicate the row is in error; however the user is allowed to keep editing. When they hit the Apply button, if there are any validation errors for the rows in the grid, the changes are not saved and focus given back to the first row found in error.I am currently using an UltraValidator control (_validator) to validate that the columns Code and Name are not null & not empty strings.I have assigned UltraTextEditor controls to the Code and Name columns, and added ValidationSettings for both UltraTextEditors. When the user is editing the cells in the grid the Code and Name columns correctly display error icons if there are no values.I cannot use the UltraValidator.Validate function on the Apply button button click; this is because the UltraValidator only checks the values the UltraTextEditors currently contain and not each individual row. Also, by the time the Apply button click event fires, the controls are invisible and containing empty strings and hence the Validate function always this the controls are in error.I then tried to validate on the grid's BeforeRowUpdate event. I receive the exact same problem - UltraValdator.Valudate returns a Validation object with IsValid always false; even when the row is perfectly valid.My next thought was to put event handlers on the UltraValidator's Validating and ValidationError events and try to record a row-level variable for if any of the cells were in error. I placed an unbound column on the grid called InError. On the Validating event I set the grid.ActiveRow.Cells["InError"].Value = "NO". In the ValidationError event handler I set the grid.ActiveRow.Cells["InError"].Value = "YES".However this method of trying to track when a validation fails does not work. If the user enters a value for the Code column but not the Name column, for instance, then moves back into the Code column, the InError cell value is set to "NO" (as the last validated column didn't generate an error...)How can I keep a record of which rows were in error when the validator validates the row? I don't want to have to record which individual columns are in error. I like the way the UltraValidator displays an error icon next to cells in error.I can always custom code row validation on the grid's BeforeRowUpdate event, track which rows are invalid and set the row back color to a distinctive colour. However then I have to validate each cell value, code the validation rules, and loose the ErrorImage functionality of the UltraValidator control.Is there any way to use the UltraValidator control to meet my needs?
The UltraValidator.Validate method only triggers validation for a "standalone" control, i.e., not a cell that has an embeddable editor. Validations for UltraGrid cells can really only be triggered by user interaction - tabbing out of a cell, or as new characters are typed.
Forgetting about UltraValidator for a moment, and going by the objective you outlined here, you might want to use UltraGrid's intrinsic support for the IDataErrorInfo interface (see http://help.infragistics.com/Help/NetAdvantage/NET/2008.2/CLR2.0/html/WinGrid_Display_Row_Cell_Errors_Using_IDataErrorInfo.html). The DataRow.Row class exposes a boolean RowError property, which, when set to true, will put the corresponding UltraGridRow into a state for which you can set appearance properties that visually depict the error. You stated, "I like the way the UltraValidator displays an error icon next to cells in error"; UltraGrid's IDataErrorInfo support provides the ability to display an image in any of the cells that you determine to be in an error state, or display one on the row selector, or any combination thereof. You could use (for example) the grid's BeforeRowUpdate event to trigger the validation.
Regarding your statement that you would "...have to validate each cell value, code the validation rules...": yes, you would have to do that in this scenario. Note, however, that there are several concrete implementations of the ICondition interface in our framework (see http://help.infragistics.com/Help/NetAdvantage/NET/2008.2/CLR2.0/html/Infragistics2.Win.Misc.v8.2~Infragistics.Win.Misc.ValidationSettings~Condition.html for references) which you could use to make the coding extremely simple. Most of these classes require only a couple of lines of code to implement the most commonly used validations such as numeric ranges, required text, string patterns, etc.
Hi Brian,
I got a problem here.
I followed your link http://help.infragistics.com/Help/NetAdvantage/NET/2008.2/CLR2.0/html/WinGrid_Display_Row_Cell_Errors_Using_IDataErrorInfo.html
and tried to implement the example. But i keep getting the following error "Unable to cast object of type 'Infragistics.Win.UltraWinDataSource.UltraDataRow' to type 'System.Data.DataRowView'" at this point,
private void ultraGrid1_InitializeRow(object sender, Infragistics.Win.UltraWinGrid.InitializeRowEventArgs e) { string rowError = ""; string cellError = ""; Object value = e.Row.Cells["Fax"].Value; // Set the data error if Fax column value is empty if(DBNull.Value == value) { rowError = "Row contains errors."; cellError = "Fax can not be empty"; } DataRowView drv = (DataRowView)e.Row.ListObject; drv.Row.RowError = rowError; drv.Row.SetColumnError("Fax", cellError); }
private void ultraGrid1_InitializeRow(object sender, Infragistics.Win.UltraWinGrid.InitializeRowEventArgs e) { string rowError = ""; string cellError = ""; Object value = e.Row.Cells["Fax"].Value; // Set the data error if Fax column value is empty if(DBNull.Value == value) { rowError = "Row contains errors."; cellError = "Fax can not be empty"; }
private void
object
Object
// Set the data error if Fax column value is empty
if
DataRowView drv = (DataRowView)e.Row.ListObject;
drv.Row.RowError = rowError; drv.Row.SetColumnError("Fax", cellError); }
How can I get the listObject into a DataRowView in order tp take advantage of
the RowError and SetColumnError objects for my row?
Thanks in advance
Thanks for replying.
The RowError property on the DataRow will do perfectly. I didn't think of using the IDataErrorInfo interface as originally the data source was of type List<T> ie no support for such things. We've since swapped over to using DataSet, so we can use it.
This also helps with laying out the form with App Stylist, as our designer can setup the display rules for when a row is in error.