DBCombo Tips & Tricks
by Scott Whittlesey 12/7/95

(If displaying in Notepad, toggle Word Wrap 'ON')

This document discusses the use of the VB4 dbCombo control on a form with a single-data control.  This control is useful for displaying key fields, such as "Title" or "Customer Name".  Typically, the remaining fields in the record are displayed in bound controls once the record has been selected, but developers can use this control for any situation that requires selecting an item from a list that is derived from a database table.

The specific subjects covered here are: 
* Using the text portion of the control to search for records
* Keeping the data control in sync with the combo box.

There are two basic approaches to searching a combo box:
(1) Searching on each letter as it is typed.  A search is performed on each keypress.
(2) Searching on a completed string.  A search is not performed until the user is done entering text.

IMPORTANT NOTE: The VB4 documentation omits an essential fact: The first approach requires that the Style property of the dbCombo is set to "2 Dropdown List".  

It may be helpful to think of "combo" as having an attached *text box* that the user can type text into; a "list" has an attached *label* that responds to keypresses for the purpose of searching, but will not actually accept text.

The sample project contains two similar forms, one for each type of search.  A small test database (Jet 2.0 format) is also included.  Neither this document nor the sample project deals with using a DBCombo to provide data for a second Data Control, which is covered in the VB manuals.

DROPDOWN LIST 
=============
Setting Style = 2 (dropdown list) and MatchEntry = 1 Extended Matching will allow the user to type one or more letters and will search on each keypress, but (a) the user's entries do not appear in the combo box and (b) the control apparently resets this invisible string of characters to null after a period of time. Try this with the sample data:

In quick succession, type 
    I (I Saw Her Standing There appears)
    T (It's All Over Now appears)


Now, wait a few seconds.  Then type the same thing, only wait about 2 seconds before typing the T.  This time, The Night Before appears.  This is because the timer has reset the string, and the control assumed that T was the first character in a new search.

This is a clever approach, but extremely confusing to any user that types faster than the Hunt & Peck method.  According to the documentation for the MatchEntry property, the user can manually reset the string by pressing Backspace, but this does not seem to work.

This search method works even if the combo list is not ordered, which depends on the RecordSource of the Data Control.

The data control is not automatically sync'd up with the list; this can be accomplished by placing this code in the dbcombo's Change event:

         Data1.Recordset.Bookmark = DBCombo1.SelectedItem


If your data control is visible and you can use it to navigate through records, you will notice that it does not automatically syncronize with the data control.  To do this, place the following code in the data control's Reposition event:

      If Not mbCalledFromDBCombo Then
        DBCombo1.Text = Data1.Recordset(DBCombo1.ListField)
      End If

* Change the code in the dbcombo's Change event to:

      mbCalledFromDBCombo = True
      Data1.Recordset.Bookmark = DBCombo1.SelectedItem
      mbCalledFromDBCombo = False

* Put this in the Form's Declarations section:
      dim mbCalledFromDBCombo as Boolean.

This flag prevents a loop in which the data control sets the combo box text, triggering the change event which sets the bookmark of the data control which would then try to set the combo box text again, and so forth.  Before this flag was added, the dbCombo would not search on each keypress.

Note: The above techniques work the same when the MatchEntry property is set to 0 (vbMatchEntrySimple), where the program assumes that each letter typed is the first letter of an item.  This setting, which is the default, seems to work a lot better and is less confusing than Extended Matching.  To cycle through all entries beginning with the letter "a", just keep pressing the "a" key.


DROPDOWN COMBO / SIMPLE COMBO 
=============================
By entering a full or partial string in the text portion of the combo box and pressing Enter, the user can cause a search of the underlying recordset.  Please refer to the code in the DBCombo1_KeyDown event.  This checks for KeyCode 13 (Enter).

The example deals with both complete and partial matches.  First, the dbCombo's MatchedWithList property is examined; if True, it means that the complete text of an existing item has been entered.  Unfortunately, this does not automatically sync up the data control, so a FindFirst is performed on the recordset to accomplish this.

If MatchedWithList is False, a FindFirst is performed on the data control's recordset using the "Like" operator to find a partial string, starting from the leftmost character.  If the search succeeds, the full key is placed in the combo box's text portion.  If it fails, the recordset is returned to its previous position (using the Bookmark that was saved before the search) and the dbCombo's text is reset to the key field from the combo box.

Syncing the Data Control:
-------------------------
The same technique of setting the data control recordset's bookmark to the dbCombo's SelectedItem is used, but the code is placed in the combo box's Click event rather than the change event, otherwise the program would attempt to set the bookmark every time a key was pressed.  This way, the bookmark is only set when a valid item is seleted from the list.

Problem:
--------
What if the user enters text, assumes the item exists, and moves on to another control?  One solution would be to check the MatchedWithList property in the LostFocus event.  Unfortunately, LostFocus is unreliable as it is possible to select other controls with the mouse without triggering that event.  The developer should consider this possibility and code accordingly.

ALTERNATIVES
============
Though the Dropdown Combo technique described above works, it is not readily apparent to the user that they can enter full or partial text and press Enter, and as stated above, the user could merely move to another control, leaving the dbCombo and Data Control out of sync.  

Depending on considerations such as available screen real estate and user competency level, it may be a better idea to provide a "Find" dialog box, or separate text box. In this case, search the Data Control's recordset; if the item is found, set the text portion of the combo box to the appropriate field.

WARNING ABOUT SEARCH PERFORMANCE
================================
The larger the recordset in the data control, the slower the search will be.  In fact, it may be too slow for your users, or worse, it may stealthily become slow over time as the underlying tables grow in size.  What developer has not experienced the thrill of getting a call from users of a project completed a year ago saying "the program used to work fine but now it's too slow, can you fix it?"

If the tables underlying the data control's recordset are likely to become large, find a way to filter the initial query so that it returns a limited number of rows.  This could be based on information you already have, or by providing some QBE fields.
