In my last blog http://blogs.interknowlogy.com/adamcalderon/archive/2005/05/25/158.aspx I showed you how to get bi-directional binding from the business object to the UI controls. In this final blog I am going to wrap everything up by walking through the DataBinding Source Code which takes you though databinding from front to back.
The first thing we need to consider in this final stage is how to get the business rule errors propagated up to the form. This is accomplished by adding the event DataErrorEvent to the customer class. This event which contains the DataErrorEventArgs value will be raised when a business rule error has occurred. The form in turn will handle this event and update the error provider with the error message. How this is done is covered a little later in the blog.
Public Event DataErrorEvent(ByVal sender As Object, ByVal e As DataErrorEventArgs)
So now that we have an event to raise we need to add the code to raise it. This is done in two places. The first is in the CustomerName property set method and the second is in a validation method Validate that can be called to perform a class wide validation of all entries.
Public Property CustomerName() As String
…
Set(ByVal value As String)
….
Me.ValidateCustomerName(value)
End Set
End Property
Public Function Validate() As Boolean
Return ValidateCustomerName(_customerName)
End Function
The main validation routine ValidateCustomerName is the one that raises the event and fills the DataErrorEventArgs class with the property name and error message.
Private Function ValidateCustomerName(ByVal name As String)
Dim blnSuccess As Boolean = True
If name.Length = 0 Then
‘raise event sending property name and message
RaiseEvent DataErrorEvent(Me, New DataErrorEventArgs(“CustomerName”, “Must have a customer name entry”))
Else
‘raise event sending property name a blank message to clear out this particular entry
RaiseEvent DataErrorEvent(Me, New DataErrorEventArgs(“CustomerName”, “”))
End If
Return blnSuccess
End Function
With the customer business class completed lets move on to the form. The form in the code sample contains a single textbox that accepts a customer name, an error provider and a save button. First the form has a private variable of type customer that is declared using the WithEvent keyword. This enables us to subscribe to the events using a metaphor familiar to most VB developers. The customerEntry_DataErrorEvent method handles the DataError event raised by the customer class and via the ErrorBinding.BindErrorToControl shared method binds the error message to the textbox control. What is going on in this method is a simple looping construct that finds the binding entry that matches the property name and then associates the error message and the control to the error provider.
Private Sub customerEntry_DataErrorEvent(ByVal sender As Object, ByVal e As DataErrorEventArgs) Handles customerEntry.DataErrorEvent
Dim base As BindingManagerBase = Me.BindingContext.Item(CType(sender, Customer))
ErrorBinding.BindErrorToControl(base, Me.ControlErrorProvider, e.PropertyName, e.ErrorMessage)
End Sub
Public Shared Sub BindErrorToControl(ByVal pBindingBase As BindingManagerBase, ByVal pErrorProvider As ErrorProvider, ByVal pstrDataSourcePropertyName As String, ByVal pstrErrorMessage As String)
…
Dim curBinding As Binding
‘loop through the bindings asosciated with the datasource and find the control that
‘is bound to the property and associate the error provider to it
For Each curBinding In pBindingBase.Bindings
Dim bindingInfo As BindingMemberInfo = curBinding.BindingMemberInfo
If bindingInfo.BindingMember = pstrDataSourcePropertyName Then
pErrorProvider.SetError(curBinding.Control, pstrErrorMessage)
End If
Next
End Sub
With the customer tie in to the error provider completed we have two things left. The binding of the customer to the textbox and the validation when the user clicks the save button. The binding of the customer to the textbox is handled in the Load event as shown below. The code for the DataBinding.SetBinding shared method is in the attached code as follows our earlier examples.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
customerEntry.CustomerName = “Test Customer Name”
DataBinding.SetBinding(Me.CustomerNameTextBox, “Text”, customerEntry, “CustomerName”)
End Sub
The validation code is done in the Save button event handler and basically calls the validate method on the customer class.
Private Sub SaveButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveButton.Click
If customerEntry.Validate() = False Then
MessageBox.Show(“Something was wrong with your data”)
End If
End Sub
In conclusion what I have demonstrated in these series of blogs is a way for you to connect your business objects to your UI components and have the error provider participate in alerting the user you have errors. By moving all of your business logic code into the business objects and using databinding you simplify your code and reduce the amount of coding on the form so the form basically contains glue code needed to tie everything together.