ComponentOne List 8.0 for ActiveX
Handling the UnboundReadDataEx event in mode 2

The UnboundReadDataEx event is used when the DataMode property is set to 2 - Unbound Extended, and is fired by the list whenever it requires one of the following:

The syntax of the UnboundReadDataEx event is as follows:

Example Title
Copy Code
Private Sub TDBList1_UnboundReadDataEx( _

        ByVal RowBuf As RowBuffer, _

        StartLocation As Variant, _

        ByVal Offset As Long, _

        ApproximatePosition As Long)

When this event is fired, the properties of the RowBuf argument are set as follows:

You can examine the RowCount and ColumnCount properties to determine whether the list is requesting a bookmark or data. If RowCount is 1 and ColumnCount is 0, the list is asking for a bookmark only; if ColumnCount is nonzero, the list is asking for RowCount rows of data (and the corresponding bookmarks).

StartLocation is a bookmark which, together with Offset, specifies the first row of data to be transferred to RowBuf.

Offset specifies the relative position (from StartLocation) of the first row of data to be transferred. A positive number indicates a forward relative position; a negative number indicates a backward relative position. Regardless of whether Offset is positive or negative, you should always return rows to the list in the forward direction.

ApproximatePosition is a variable which optionally receives the ordinal position of the first row of data to be transferred. Setting this variable will enhance the ability of the list to display its vertical scroll bar accurately. If the exact ordinal position of the row is not known, you can set it to a reasonable, approximate value, or just ignore this parameter.

Before returning from the UnboundReadDataEx event, you are expected to fill the Bookmark array of RowBuf with unique row identifiers, and the Value array with the actual data, if requested. For example, if Offset is 1 (or -1), then you must fill in RowBuf starting from the row that follows (or proceeds) StartLocation:

Example Title
Copy Code
Dim RowIndex As Long

Dim ColIndex As Integer, Col As Integer

 

With RowBuf

    For RowIndex = 0 To .RowCount - 1

        .Bookmark(RowIndex) = Variant Bookmark

        For ColIndex = 0 To .ColumnCount - 1

            Col = .ColumnIndex(RowIndex, ColIndex)

            .Value(RowIndex, ColIndex) = Variant Data for Col

        Next ColIndex

    Next RowIndex

End With

Note that there is a subtle difference between this example and the one presented in the earlier discussion of the UnboundReadData event of mode 1. When programming the UnboundReadDataEx event, you must fill in the Value array with column data according to the ColumnIndex array of the RowBuffer object, since it is possible that the column indexes of the list and the row buffer no longer match.

The list generally asks for data according to the number of columns and the order of the columns as displayed on the list. For example, if your data source has 20 columns, and the list needs to display the first 5 columns on the screen, then the UnboundReadDataEx event will be called with ColumnCount equal to 5 and the ColumnIndex array equal to (0, 1, 2, 3, 4). However, if the user moves column 4 between column 0 and column 1, then the next UnboundReadDataEx event will be called with ColumnCount equal to 5 and the ColumnIndex property array equal to (0, 4, 1, 2, 3). Therefore, you must account for the new column order, as given by the ColumnIndex property, when filling the Value array.

Another important distinction between the two row-based unbound modes is that in mode 2, UnboundReadDataEx will not fetch data for columns whose Visible property is False, and may not fetch data for columns that are not physically displayed or have been scrolled out of view, even if their Visible property is True. In mode 1, however, UnboundReadData will always fetch data for all columns, even if they are not shown on the screen or have their Visible property set to False. This is one of the reasons why mode 2 generally outperforms mode 1.

When the list first loads, it needs to determine if there is any data to display. It does this by firing the UnboundReadDataEx event to retrieve the bookmark (but not the data) for the first row. If your event handler provides a bookmark, the list fires UnboundReadDataEx again, this time to fetch the actual data in a block of ten rows. This process continues until the list has enough data to fill its display or your event handler informs the list that the end of the dataset has been reached.

For example, if the list specifies a StartLocation bookmark indicating the 46th row, the Offset argument is 3, and the row buffer's RowCount property is 10, then your UnboundReadDataEx event handler should populate the row buffer's Value array as follows:

Example Title
Copy Code
RowBuf.Value(0, ColIndex) = Data for row 49

RowBuf.Value(1, ColIndex) = Data for row 50

RowBuf.Value(2, ColIndex) = Data for row 51

...

RowBuf.Value(9, ColIndex) = Data for row 58

However, if Offset is -3, a different set of values must be returned:

Example Title
Copy Code
RowBuf.Value(0, ColIndex) = Data for row 43

RowBuf.Value(1, ColIndex) = Data for row 44

RowBuf.Value(2, ColIndex) = Data for row 45

...

RowBuf.Value(9, ColIndex) = Data for row 52

Note that you should always populate the Value array in the forward direction, regardless of whether Offset is positive or negative. This differs from the UnboundReadData event of mode 1, in which rows must be returned in reverse order if ReadPriorRows is True.

If you reach the beginning or end of the data, and have fewer than RowCount rows to provide, then you should fill the row buffer with the data you can provide, and change the RowCount property to the actual number of rows provided, which may be zero.

For example, if your dataset contains 50 records, the list specifies a StartLocation bookmark indicating the 46th row, the Offset argument is 1, and the row buffer's RowCount property is 10, then your UnboundReadDataEx event handler should populate the row buffer's Value array as follows:

Example Title
Copy Code
RowBuf.Value(0, ColIndex) = Data for row 47

RowBuf.Value(1, ColIndex) = Data for row 48

RowBuf.Value(2, ColIndex) = Data for row 49

RowBuf.Value(3, ColIndex) = Data for row 50

 

RowBuf.RowCount = 4       ' Since only 4 rows were processed

Since the value of RowCount was changed from 10 to 4, and Offset is positive, the list determines that it has reached the end of your data and stops firing UnboundReadDataEx with a positive Offset.

When the user scrolls vertically, the list computes the position of the new topmost visible row and fires UnboundReadDataEx to obtain a bookmark for that row. For example, if the user hits the PgUp key, the list might fire UnboundReadDataEx with a StartLocation representing row 90 and Offset equal to -20. In this case, the list is effectively asking for a bookmark for row 70. Once the list has the bookmark it needs, it will fire UnboundReadDataEx again to fetch the data to be displayed.

At times, the arguments passed to UnboundReadDataEx may seem peculiar. For example, if StartLocation specifies row 2 and Offset equals -10, the list is effectively asking for a bookmark for row -8, and you should set RowCount to 0 and exit the event. Although it may seem unnecessary for the list to request the bookmark of a row that does not exist, such behavior is normal, for this is how the list determines the boundaries of your data source. Also, since the list is designed to work with multi-user data sources, it is very conservative about boundary conditions. As long as you respond to UnboundReadDataEx consistently and correctly, the list will detect BOF and EOF conditions as fluidly as it does in bound mode.

A StartLocation of Null indicates a request for data from BOF or EOF. For example, if StartLocation is Null and Offset is 2 (or -2), then you should retrieve data starting from the second (or second to last) row:

Example Title
Copy Code
If IsNull(StartLocation) Then

    If Offset < 0 Then

        ' StartLocation indicates EOF, because the list is

        ' requesting data in rows prior to the StartLocation,

        ' and prior rows only exist for EOF.

        ' There are no rows prior to BOF.

    Else

        ' StartLocation indicates BOF, because the list is

        ' requesting data in rows after the StartLocation,

        ' and rows after only exist for BOF.

        ' There are no rows after EOF.

    End If

Else

    ' StartLocation is an actual bookmark passed to the list

    ' in the RowBuffer, an event argument (UnboundAddData), or

    ' the setting of a list bookmark. You must ensure that

    ' the bookmark is valid, and take the appropriate action

    ' if it is not.

End If
You cannot make any assumptions about when the list will request data, or how many times it will request the same data. In short, it is the list's responsibility to display the data properly, while the task of storing and maintaining the data falls to you. This division of labor frees you from worrying about when or how to display data in the list.

 

 


Copyright (c) GrapeCity, inc. All rights reserved.

Product Support Forum  |  Documentation Feedback