The information in this article applies to:
SUMMARY
Visual Basic version 4.0 for Windows ships with a full-featured grid that
allows in-place editing of items in a table. This grid, the Data Bound Grid
(DBGRID), was designed to be used to edit and display records in a database
table. This article includes a document that was written by Apex Software
Corporation, the designers of the control, that discusses how to use this
control in an unbound mode.
MORE INFORMATIONThe following file is available for download from the Microsoft
Download Center. Click the file name below to download the file: Dbgridub.exeFor more information about how to download files from the Microsoft Download Center, please visit the Download Center at the following Web address http://www.microsoft.com/downloads/search.aspand then click How to use the Microsoft Download Center. THE DOCUMENTIntroduction to True DBGrid Unbound ModeWhen used in "Unbound Mode" (DataMode property set to 1), the grid is not connected to a database file. Instead, data in the grid must be supplied and maintained by you, the programmer, while the grid handles all user interaction and data display. Should a user cover the grid with another window, for example, and later uncover it, the grid will be completely responsible for controlling the details of repainting the grid. The programmer, meanwhile, does not need to deal with any of the user interaction or display requirements. With the grid controlling all other facets, you need to concentrate solely on maintaining your data. When the grid needs to display data on the screen, you will be prompted for it, by way of the UnboundReadData event. Once the user has made changes to the data in the grid, you will be notified again - this time in reference to the changes, by way of the UnboundAddData, UnboundWriteData and UnboundDeleteRow events - and prompted to update the data to reflect these changes. If the data is changed internally, rather than by user interaction with the grid, you will need to instruct the grid to repaint itself, by using the RefreshRow, RefreshColumn, or Refresh method.In short, True DBGrid in unbound mode provides a useful tool for dealing with dynamic data. Since it has no inherent storage capability, the grid handles frequently changing data fluidly and easily. Make use of other True DBGrid events and techniques, and you should be able to create efficient and friendly applications. Unbound Mode BookmarksBefore we discuss the use of Unbound Mode, we must answer the question: What is a "bookmark" when referring to the Unbound mode? Simply put: Bookmarks are variants used by the unbound grid as a means of uniquely identifying a row within the data to be displayed. How, then, are bookmarks created, stored and used? Well, since you provide, store and maintain the data in the unbound grid, you must deal similarly with the bookmarks. The bookmarks, themselves, must be supplied by the UnboundReadData and UnboundAddData (see next section) events, and are passed to and from the grid in the form of Variant data type variables. As variants, you are free to use whatever you choose for the purposes of identifying a row, albeit with some restrictions. To better understand these restrictions, we must first take a look at how VB and True DBGrid treat bookmarks, and the importance of these differences.The GridThe grid treats bookmarks as packets of binary information which cannot be interpreted. To the grid, a bookmark is a piece of data containing a specific number of bytes (ASCII codes) in a specific order. Thus, pieces of different lengths, or pieces with different bytes, are considered different bookmarks. For example, if the grid were to compare the String bookmarks: "1", " 1" and "01", it would consider each bookmark different from the other, though they could, numerically, be considered the same. Similarly, a 2-byte Integer and a 4-byte Long would also be considered different, even if both contained the same numeric value.Visual BasicVisual Basic, on the other hand, treats bookmarks as true variants. That is, they are quantities that can be converted from one form to another without loss of equality, unless they are both in the form of a String. In addition, bookmarks are often passed by Visual Basic(tm) as Byte Arrays, both by the grid and by data controls. Thus, two bookmarks should be compared in Visual Basic(tm) for equality, unless those bookmarks are converted to Strings. This rule remains true whether the bookmark comes from a grid (bound or unbound) or from a data control.To avoid difficulties, it is usually best to use Strings universally for bookmarks with an Unbound grid. NOTE: Even though bookmarks passed to the grid may be strings, comparison of bookmarks obtained from the grid (via Bookmark type properties) should always be explicitly converted to strings before comparison. The conversion can be done by simply defining a string variable and assigning the bookmark to that variable. Another important consideration regarding bookmarks is their length. We advise that all bookmarks in your application be created the same way. For example, the Visual Basic(tm) functions Format$(), CStr() and Str$() do not generate the same string, even if they are passed the same numerical value. The Str$() function always generates a character for the sign of the numerical value, while Format$() and CStr() do not (eg. Str$(1) generates " 1", with a leading blank character, while Format$() and CStr() generate "1"). Remember that since these strings are of different length, they will constitute different bookmarks. To avoid difficulties of this nature, we suggest writing a single Visual Basic for Applications function, like MakeBookmark(), and use it consistently whenever a bookmark must be generated. Due to the way the grid handles bookmarks internally, this function should, ideally, generate strings of at least 2 characters. Thus, if possible, use the Str$() function. Creating an Unbound Mode ApplicationListed below are the basic steps for creating a True DBGrid application, using the Unbound Mode.Determine Data Storage Method: You, as the programmer, are responsible for maintaining and storing the data which will be displayed on the grid. One of the most common ways to store this data is the Visual Basic(tm) array. If your grid is very large (1,000,000 rows x 5,000 columns), however, there may not be sufficient system memory to store the arrays. In such a case, you will need to store the data in files, or in other storage media (Generally, in such a case, databases are used to store the data and it will be easier to use the Database mode of the grid.). Another use the grid unbound would be to use a function/sub to return the values to display (The values are usually dependent on row and column numbers). If using a function, you can define it in the UnboundReadData event. Bookmarks will be generated by the same function/sub. This technique is most appropriate when using another DBMS such as Q+E Library, Choreo or Rocket. Initialize the Data and the Grid: Because the grid will start requesting data as soon as it is loaded, it is best to initialize the data before the grid is ready. This can be done in Sub Main (if you start your project with Main) or the Form_Load event (of the Form containing the grid). That done, you must now initialize a few grid properties. Some of these properties can be initialized at design time using either the properties window or the True DBGrid property pages. (See Chapter 3 - Configuring True DBGrid at Design Time.) We will now illustrate how to initialize some properties at runtime. With a 3 row by 2 column table entry, where the data is stored using a two- dimensional array, the following code initializes the data and grid properties:
The following code is not necessary for configuring the grid at design time. However, it does increase the efficiency of the code.
Note that the grid defaults to two columns, unless the number of columns has been modified in the Columns property page. In the above sample code, we have simply changed the properties of the existing default columns. If a different number of columns is required, you must use the Columns() collection Add and Remove methods. Here, we provide sample code that deals with multiple columns and their manipulation.
Once the grid is loaded, you will be asked for data to display. The UnboundReadData event is used to provide that data. Before describing the event itself, however, we will briefly discuss the event's arguments: (see Chapter 10 - Command Reference for more information)
RowBuffer - the RowBuffer is an OLE Object defined by the grid and used to exchange row data between the grid and the Unbound data events. It has the following properties and methods, and can be viewed using the Visual Basic(tm) Object Browser, or Apex's Visual Basic for Applications Companion(tm) Object Browser RowBuf.RowCount Long - number of rows which the Unbound event expects to be processed during the event. If fewer rows can be processed than requested, this property should be changed in the event to reflect the actual number of rows available. RowBuf.ColumnCount Integer - number of columns which the Unbound event expects to be processed during the event. This property is read-only, and no attempt should be made to change it. The Unbound event should process all columns requested. RowBuf.ColumnName(Col) String - name of the grid column indicated by the Col parameter. This property is read-only.
RowBuf.Bookmark Variant - specifies Unbound row bookmarks when the RowBuffer is used to fetch data during the UnboundReadData event. The RowBuffer row is passed as an argument. RowBuf.Value(Row, Col) Variant - used to specify the data value associated with a RowBuffer row and column. The Value property takes the RowBuffer row and column as arguments.
In the UnboundReadData event, the RowBuffer object is created by the grid with Values and Bookmarks set to Null. RowBuf is passed to the event with the expectation that the event will set the necessary values and bookmarks. In the UnboundAddData and UnboundWriteData events, data the user has changed is held in the RowBuf.Value(0,Col). Any column with unchanged data will have RowBuf.Value(0,Col) = Null. The programmer saves the changed (not Null) values to the data source (the array in most cases). Note: Only non- Null values of the RowBuffer indicate data changes. StartLocation Variant - specifies the row "before" the desired data. We set "before" apart in quotation marks because its meaning is dependent on the value of the third argument: ReadPriorRows (described below). StartLocation will contain a bookmark as a specification of the row. ReadPriorRows Boolean - indicates the direction in which the grid is requesting the data. For example, if the grid specifies a StartLocation indicating the 46th row, a RowCount of 5 and if the ReadPriorRows property is True, then the UnboundReadData event should return the following information in the RowBuffer:
On the other hand, if the value of ReadPriorRows in the above case were False, the event would return the following information in the RowBuffer:
NOTE: Regardless of the value of ReadPriorRows, the nearer a row is to the StartLocation bookmark, the lower its row index in the RowBuffer. In addition, data for the row indicated by the StartLocation bookmark is not returned. At first glance, the RowBuffer object may seem complicated and difficult to use. A closer look, however, reveals that its use is only slightly different from that of a two-dimensional array. StartLocation and ReadPriorRows may seem unnecessarily cumbersome as well. However, they are the simplest means of communicating the row boundaries of the data to the grid. They increase the speed and performance of the grid. The grid only caches a portion of the data, and it is with these two properties that you and the user can navigate from one bookmark to the next. Example: Suppose there are 100 rows of data, the current row is 75, and the grid is asked to move to the 3rd row of data using a previous obtained bookmark. The following sequence demonstrates what might happen in this situation:
There is another situation of which you should be aware, in the UnboundReadData event. This instance occurs when the grid needs data for the first or last row of the grid. In this case, StartLocation is passed as a Null variant. Whether a Null StartLocation indicates BOF or EOF depends upon the value of ReadPriorRows. Example:
A final note: The programmer cannot make any assumption as to when the grid will request data, or how many times it will request the same data. In short, it is the grid's responsibility to display the data properly, while the task of storing and maintaining the data falls to you. This system will allow you not to worry about when and how to display data in the grid. Define the UnboundWriteData Event: If the grid is up-datable, and if the user has edited data in the row cells, then moving to another row will trigger an update. The grid will then fire the UnboundWriteData event, which allows you to record the changes, and which uses the values passed via a RowBuffer to update the data you are responsible for storing and maintaining.
RowBuffer in this event has the same properties that are used in the UnboundReadData event described above, though it is used differently. In this case, the RowBuffer contains values passed by the grid, indicating which columns have been edited as well as the modified values. The RowCount is always 1 for this event, but should be changed to 0 if, for some reason, the update cannot be completed. Setting the RowCount to 0 will trigger a trappable grid error event. To minimize the overhead associated with the update, only RowBuffer values that have actually been edited require updating (are Non-Null). WriteLocation Variant - specifies a bookmark for the current row, if it has just been edited.
Define the UnboundAddData Event: If the AllowAddNew property is True, and if the grid is updatable, you must define the UnboundAddData event. Much like in the UnboundWriteData event, data is taken from the RowBuffer and stored. Once again, the RowCount is used as an indicator of the success or failure of the AddNew.
For added rows, the second argument, NewRowBookmark, must be set, returning a bookmark for the added row.
Define the UnboundDeleteRow Event: If the AllowDelete property is True, and if the grid is updatable, the UnboundDeleteRow event should be defined.
This is the simplest of all the unbound grid events, though a vital one if rows are to be deleted from the grid. This event should delete the row indicated by the bookmark passed from internal storage. If the deletion fails, the bookMark argument should be set to Null to indicate the failure. Note that following the UnboundDeleteRow event, the grid is automatically refreshed. Changing values in code - Refresh the Grid: In order to change the value of a cell in code, change the value of the underlying data then refresh the grid. The Columns().Value property is read only.
Putting It Together in Unbound ModeFollowing is code for a sample application, using the concepts discussed above. This example should be viewed as a starting point, intended to show the logical function of the aspects of Unbound Mode. Example:
Additional query words:
Keywords : kbfile kbVBp400 IAPThird VB4WIN |
Last Reviewed: December 13, 1999 © 2000 Microsoft Corporation. All rights reserved. Terms of Use. |