Data Binding Objects VB Library to Reference

Microsoft Data Binding Collection (../SYSTEM32/MSBIND.DLL) Description

Apparently, when Microsoft was planning the new release of Visual Basic, they researched how professional developers were using the language. One result which seems to have taken the VB development team by surprise was that very few professional developers use the Data control and data bound controls. The reason for this is quite easy to understand: rightly or wrongly, professional VB developers see the Data control and data bound controls as inflexible and an encroachment on their control over the database. Furthermore, as more and more VB applications follow the n-tier paradigm, in which database access is performed on a remote server, with only properties passed to (or requested by) the client, the usefulness of a Data control was diminishing rapidly.

With this in mind, Microsoft introduced a new object model to give developers control over data mapping without sacrificing the rapid development time offered by more or less central data binding. The binding objects sit between standard form controls and your recordset (which can be wrapped within a class in an ActiveX server), automatically updating the form control as the user navigates through the recordset. Therefore, any form control can now be bound to a database field.

The Binding object model, which is shown in Figure 7-2, consists of a top-level collection to which you add Binding objects, these being the physical binding of data column to form control. The Binding object offers a flexibility that should satisfy most needs. For example, you can bind data to any property on a control, and you can specify at what point the data binding should be updated. A major enhancement over previous data binding technologies is the ability to bind the controls on a form to a VB class object. This can be achieved in both directions; that is to say, a VB class module can now be a data source, or it can be a data consumer.

Data Binding Objects (VB6) 185

-»• stdDataFormat |

—> stdDataValue |

Figure 7-2: The Data Binding object model

Figure 7-2: The Data Binding object model

Example

To introduce the objects involved in both data binding and data formatting, this example demonstrates how the objects can bind data from an ActiveX OLE server to standard VB form controls without using a Data control. This example uses the sample SQL Server pubs database, but it can be easily modified to use an Access database or even the computer's own file system as a source of data. What's important is the relationship between the different objects in the Data Binding and Data Formatting object model.

In this example, an ActiveX DLL class object performs the database access and exposes itself as a data source. The form creates a BindingCollection object that binds various controls on the form to database fields in two different recordsets held in the class. The example shows how to:

• Create a BindingCollection object.

• Specify the VB class as the data source for the BindingCollection object.

• Add individual Binding objects to the collection, thereby binding controls to database fields held within the data provider class object.

• Create DataFormat objects to perform formatting functions on the incoming and outgoing data.

• Navigate through the recordset.

• Perform simple validation and confirmation before updating the database. Data Consumer Form Code

The form includes the following object references, which are selected from the References dialog:

• Microsoft Data Binding Collection

• Microsoft Data Formatting Object Library

In addition, if the data source class isn't in the same project as the data consumer form, a reference to the data source class needs to be added.

186 Chapter 7- The Language Reference

The form contains the following controls:

Control Name

Control Type

chkContract

Checkbox

cmdMoveNext

Command button

cmdMovePrevious

Command button

txtAddress

Text box

txtContract

Text box

txtFirstName

Text box

txtlastName

Text box

txtPubDate1

Text box

txtTitle1

Text box

Option Explicit

'declare object variables for the BindingCollection 'objects we'll need and a single Binding object. Private obcAuthors As BindingCollection Private obcTitles As BindingCollection Private oBind As Binding

'declare an object variable referencing our

'BindingSource class

Private oSource As BindingSource

'declare object variables for the DataFormat objects Private WithEvents fmtFl As StdDataFormat Private WithEvents fmtF2 As StdDataFormat Private WithEvents fmtF3 As StdDataFormat Private WithEvents fmtF4 As StdDataFormat

Private Sub Form_Load()

'create new instances of the required objects

'our source class

Set oSource = New BindingSource

'and the two BindingCollections

Set obcAuthors = New BindingCollection

Set obcTitles = New BindingCollection

'Set up the required Format Objects

'first to show a short message and automatically

'handle NULL database values

Set fmtFl = New StdDataFormat fmtFl.Type = fmtCustom fmtFl.NullValue = "No Data Found"

'second to handle 0 and 1 values in the database 'displaying a string in the text box instead Set fmtF2 = New StdDataFormat fmtF2.Type = fmtBoolean

Data Binding Objects (VB6) 187

fmtF2.FalseValue = "No Contract" fmtF2.TrueValue = "Contract Signed"

'third to switch a checkbox on or off automatically 'depending on the database value of 0 or 1 Set fmtF3 = New StdDataFormat fmtF3.Type = fmtCheckbox

'last one to format a date field Set fmtF4 = New StdDataFormat fmtF4.Type = fmtGeneral fmtF4.Format = "long date"

'instruct the BindingCollection not to perform 'an update until the user moves to the next record obcAuthors.UpdateMode = vbUpdateWhenRowChanges 'set the DataMember to the required value - this 'will be passed to the class to obtain a reference 'to the correct recordset obcAuthors.DataMember = "Authors"

'now assign our source class as the datasource for

'the authors bindings collection

Set obcAuthors.DataSource = oSource

'use the add method to create the binding between

'form controls and database fields obcAuthors.Add txtFirstName, "Text", "au_fname", _

fmtF1, "fname" obcAuthors.Add txtLastName, "Text", "au_lname", _

fmtF1, "lname" obcAuthors.Add txtContract, "Text", "contract", _

fmtF2, "contract" obcAuthors.Add chkContract, "Value", "contract", _

fmtF3, "chkCont" obcAuthors.Add txtAddress, "Text", "address", _ fmtF1, "address"

'now do the same for the Titles recordset obcTitles.UpdateMode = vbUpdateWhenRowChanges obcTitles.DataMember = "Titles" Set obcTitles.DataSource = oSource obcTitles.Add txtTitle1, "Text", "title", _

fmtF1, "title" obcTitles.Add txtPubDate1, "Text", "pubdate", _ fmtF4, "pubdate"

End Sub

Private Sub fmtF1_Format(ByVal DataValue As _

StdFormat.StdDataValue)

'the format event is called when a custom type 'is about to be formatted. Just for fun let's set 'the firstname field to uppercase and the

188 Chapter 7- The Language Reference

'lastname field to lowercase

If DataValue.TargetObject.Name = "txtFirstName" Then fmtF1.Format = ">"

End Sub

Private Sub fmtF1_UnFormat(ByVal DataValue As _

StdFormat.StdDataValue)

'the unformat event is only called for custom type 'formats that are just about to be written back to 'the database - so lets convert them back to proper 'case

DataValue.Value = StrConv(DataValue.Value, _

vbProperCase)

End Sub

Private Sub cmdMoveNext_Click()

'the user has finished with the record and wants 'the next one.

'just check this out first.. Call CheckForUpdate

'ok now we'll give them the next record by calling 'the MoveNext method in our source class. oSource.MoveNext

'we need to rebind the titles recordset because

'it's dynamically built

Set obcTitles.DataSource = oSource

End Sub

Private Sub cmdMovePrev_Click()

Call CheckForUpdate

'call the MoveBack method in our source class oSource.MoveBack

n if a

End Sub

PS to

Private Function CheckForUpdate() As Boolean

Dim iResponse As Integer

'before we give them the next record - let's just 'check whether they made any amendments to the 'current record.

'iterate through the Binding objects

Data Binding Objects (VB6)

VB & VBA in a Nutshell: The Language, eMatter Edition Copyright © 2000 O'Reilly & Associates, Inc. All rights reserved.

189

For Each oBind In obcAuthors

'see if any values have been changed by the user If oBind.DataChanged Then

'indeed they did--was it intentional though? iResponse = MsgBox("The data has changed" _ & vbCrLf & _

"do you wish to update?", _ vbYesNo + vbQuestion) If iResponse = vbNo Then

'obviously not - so cancel the update from ' being written back to the database oBind.DataChanged = False End If

'no point in looking any further... Exit For End If Next

End Function

Notes

• This form is set as the project's startup object.

• In the Form_Load event, a reference to the data source class is assigned to the BindingCollection.DataSource property, firing the data source class's GetData-Member event. The GetDataMember event handler assigns a reference to the recordset specified in the BindingCollection.DataMember property to the BindingCollection.

• The Binding object's DataChanged property gives you control first, to interrogate the binding and determine if the value has been changed by the user, and second, to prevent the update from being written back to the database.

• See the Data Format Objects entry for more information about the stdDataFor-mat object.

Data Source Class Code

The class references the Microsoft ActiveX Data Objects 2.0 Library, selected from the References dialog. The class also has its DataSourceBehavior property set to vbDataSource.

Option Explicit 'declare the ADO objects Private cn As ADODB.Connection

Private WithEvents rsAuthors As ADODB.Recordset Private WithEvents rsTitles As ADODB.Recordset

Private Sub Class_GetDataMember(DataMember As String, _

Data As Object) 'this event is called as the datasource is assigned 'to the BindingCollection object. If DataMember = "Authors" Then

'this class provides two data members 'the first is authors, the other is titles

190 Chapter 7- The Language Reference

'assign the required recordset back to the 'BindingCollection object Set Data = rsAuthors

Else

Set Data = rsTitles End If End Sub

Private Sub Class_Initialize() Dim sSQL

'create an instance of the ADO Recordset to use 'for the Titles recordset later Set rsTitles = New ADODB.Recordset

'create the connection object Set cn = New ADODB.Connection

'there is a DNS called Test on this machine 'pointing to the Pubs database cn.ConnectionString = "Test" cn.Open

'peform the query to return the data from Authors sSQL = "SELECT * FROM authors"

Set rsAuthors = New ADODB.Recordset rsAuthors.Open sSQL, cn, adOpenKeyset, adLockOptimistic

'force the Titles recordset to be created rsAuthors.MoveFirst

End Sub

Public Sub MoveNext()

'move to the next record rsAuthors.MoveNext If rsAuthors.EOF Then rsAuthors.MoveFirst End If End Sub

Public Sub MoveBack()

'move to the previous record rsAuthors.MovePrevious If rsAuthors.BOF Then rsAuthors.MoveLast End If End Sub

Private Sub rsAuthors_MoveComplete(ByVal adReason As _

ADODB.EventReasonEnum, _ ByVal pError As ADODB.Error, _ adStatus As ADODB.EventStatusEnum, _ ByVal pRecordset As ADODB.Recordset)

Data Binding Objects (VB6) 191

'Move_Complete is an event from the ADO Recordset 'This code allows us to keep the two recordsets 'in synch. Dim sSQL As String sSQL = "SELECT titles.title, titles.pubdate" & vbCrLf _ & " FROM titles, titleauthor" & vbCrLf _ & " WHERE titleauthor.au_id = '" _

& rsAuthors("au_id") & & vbCrLf _

& " AND titles.title_id = titleauthor.title_id"

If rsTitles.State = adStateOpen Then rsTitles.Close End If

'you'll need to rebind this recordset - see code in form rsTitles.Open sSQL, cn, adOpenKeyset, adLockOptimistic

End Sub

Notes

• The Class_GetDataMember event handler is automatically placed in the class for you when you set the class's DataSourceBehavior property to vbData-Source.

• By declaring the ADO recordset object as WithEvents, you can access all the events in the recordset object (such as WillChangeField, which allows you to perform validation and cancellation prior to updating, if you wish).

See Also

BindingCollection Object, Binding Object

Was this article helpful?

0 0

Responses

Post a comment