This is the next sample in the Sample Applications Series. The purpose of the Sample Series is to provide concise code solutions for specific programming tasks. This sample provides a brief description of the problem, the solution and full source code.
I have been preparing for this weekends Code Camp in Charlotte, NC and wanted to use the Infragistics xamDataGrid in my example code. That code will be posted here on 16 May 2008.
All of my business objects implement the System.ComponentModel.IDataErrorInfo interface. This interface provides a simple UI agnostic method of validating business objects.
Currently the Infragistics xamDataGrid does not directly support the IDataErrorInfo interface. (By the way, this awesome data grid is free.)
I did not want to imbed my business logic in my UI so I’ve come with a way to get the xamDataGrid to cleanly support the IDataErrorInfo interface.
If you are not familiar with the IDataErrorInfo interface, please read up on this very cool interface before proceeding.
You MUST have the Infragistics free xamDataGrid or .NET Advantage for WPF Volume 2 installed on your system to compile and run this application.
If you are using the free xamDataGrid you may need to change the references to the Infragistics libraries. I’m not sure if the names match or not.
The above image shows a xamDataGrid with several rows. Each row’s DataItem is an instance of the SalesPerformance class.
This simple class has two data properties ProductLineId and SalesAmount along with the IDataErrorInfo.Item and IDataErrorInfo.Error property.
The ProductLineId property is the foreign key to the ProductLine.ProductLineIdent field. This value is used by the Product Line ComboBox to display the ProductLine.Name.
This is a very typical scenario found in business applications that uses a normalize database.
In the above image, the user has selected a value in the Product Line ComboBox that does not meet the validation rules for the SalePerformance.ProductLineId property.
The ComboBox now has a red border. In addition, the user can’t edit any other row until this row is valid.
The Sales Amount field also has a validation rule that requires the value to be greater than or equal to zero.
xamDataGrid Timing Cycle
When you perform an edit on a cell the following events are raised in this order.
- xamDataGrid: RecordUpdating
- xamDataGrid: EditModeEnded
So our code must be able to manage the process using the above events in the order that the xamDataGrid raises them. For those who are wondering, I don’t use the EditModeEnding event because the value in the bound DataItem has not yet been changed. Since the property value is not reflected in EditModeEnding, validating the object in that event handler will do us no good.
RecordUpdating Event Handler
Private Sub xdgSalesPerformance_RecordUpdating(ByVal sender As System.Object, _ ByVal e As Infragistics.Windows.DataPresenter.Events.RecordUpdatingEventArgs) #If DEBUG Then Debug.WriteLine("xamDataGrid: RecordUpdating") #End If 'if there are errors on the object, cancel the update. 'this keeps the user from editing other records until this record is corrected If DirectCast(DirectCast(DirectCast(e.Record, _ Infragistics.Windows.DataPresenter.DataRecord).DataItem, System.Object), _ IDataErrorInfo).Error.Length > 0 Then e.Action = _ Infragistics.Windows.DataPresenter.RecordUpdatingAction.CancelUpdateRetainChanges End If End Sub
The above event handler is very simple. It gets a reference to the DataItem and casts it as an IDataErrorInfo.
The RecordUpdating method is the icing on the cake. If the e.Action is canceled, the xamDataGrid will not allow the user to edit another row in the xamDataGrid until the current row is corrected.
EditModeEnded Event Handler
Private Sub xdgSalesPerformance_EditModeEnded(ByVal sender As System.Object, _ ByVal e As Infragistics.Windows.DataPresenter.Events.EditModeEndedEventArgs) #If DEBUG Then Debug.WriteLine("xamDataGrid: EditModeEnded") #End If 'get the data object Dim obj As IDataErrorInfo = DirectCast(DirectCast(DirectCast( _ DirectCast(e.Cell, Infragistics.Windows.DataPresenter.Cell).Record, _ Infragistics.Windows.DataPresenter.DataRecord).DataItem, System.Object), _ IDataErrorInfo) 'query the objects IDataErrorInfo.Item property for any errors on this column's data Dim strErrorMessage As String = obj.Item(DirectCast(DirectCast( _ e.Cell, Infragistics.Windows.DataPresenter.Cell).Field, _ Infragistics.Windows.DataPresenter.Field).Name) If strErrorMessage.Length > 0 Then 'indicate a data entry problem e.Editor.BorderBrush = Brushes.Red 'save the current tooltip If e.Editor.ToolTip IsNot Nothing Then e.Editor.Tag = e.Editor.ToolTip End If e.Editor.ToolTip = strErrorMessage Else If e.Editor.Tag IsNot Nothing Then e.Editor.ToolTip = e.Editor.Tag e.Editor.Tag = Nothing Else e.Editor.ToolTip = Nothing End If 'clear the data entry problem indicator e.Editor.BorderBrush = Nothing End If End Sub
This is another super simple event handler.
This code gets a reference to the DataItem, validates the value using the IDataErrorInfo.Item property and then sets or removes the error visual clue in the UI.
Source Code: After downloading the source code you MUST change the file extension from .zip.DOC to .zip. This is a requirement of WordPress.com.
You can see how very simple it was to get the xamDataGrid to work with your business objects that support IDataErrorInfo interface. After looking at what I’ve done, you can see that extending the xamDataGrid to encapsulate this behavior wouldn’t take but a few minutes.
Maybe in the future Infragistics can provide support for the IDataErrorInfo interface. Possibly a property on a column that indicates that this column should be validated using IDataErrorInfo interface. A nice ValidationErrorTemplate like the WPF controls have might also be possible instead of hard coding the border color to red.
We front line developers need to let our software tools vendors like Infragistics and Microsoft know that built in support for IDataErrorInfo is required and greatly simplifies business application development.
Hope you can learn just a little bit more about .NET from this article and the Sample Series.
Just a grain of sand on the worlds beaches.