TDBLookupComboBox: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: TDBLookupComboBox
| Old | New | Line | |
|---|---|---|---|
| 1 | + | **TDBLookupComboBox**  is a (doubly) data-bound [[TComboBox]]. A TDBLookupComboBox can be found on the [[Data Controls tab]] of the [[Component Palette]]. | |
| 2 | + | ||
| 3 | + | The TDBLookupCombobox control gets a list of values from its *ListSource* (which e.g. represents a table with product info, "Products"). It then: | |
| 4 | + | ||
| 5 | + | - displays the values in the **ListField** (e.g. a "ProductName" field) while | |
| 6 | + | - remembering the values in the **KeyField** (e.g. an "ID" field) | |
| 7 | + | ||
| 8 | + | The combobox stores the result (i.e. the **KeyField** value in the **DataField**, e.g. the "ProductID" field in the **DataSource** property (e.g. an "Orders" table). | |
| 9 | + | ||
| 10 | + | The difference with the [[TDBComboBox]] is that the TDBComboBox is a (as it were) "singly data bound control": it stores the results in a database field but the list of values to select from is supplied by code/via the [[Object Inspector]]. | |
| 11 | + | ||
| 12 | + | ## Unbound use | |
| 13 | + | ||
| 14 | + | You can get the combobox to look up values from one table without storing the results in another by leaving the *DataSource* and the *KeyField* properties empty. | |
| 15 | + | ||
| 16 | + | The following sample code snippet will: | |
| 17 | + | ||
| 18 | + | - Allow a TDBLookupCombo box to be configured in unbound mode (i.e. no changes made to any table in the database) | |
| 19 | + | - Ensure the visible data in the TDBLookupComboBox is from the selected record in the dataset (i.e. choosing a new value in TDBLookupComboBox contents will scroll the dataset to the correct record) | |
| 20 | + | - Set the initial displayed value in the TDBLookupComboBox and the selected record in the datset to previously remembered values. | |
| 21 | + | ||
| 22 | + | The following sample code snipper will NOT: | |
| 23 | + | ||
| 24 | + | - Automatically update the TDBLookupComboBox value if the dataset is scrolled (you need to add your own handler to Dataset.OnScroll to achieve this) | |
| 25 | + | ||
| 26 | + | ``` pascal | |
| 27 | + | interface | |
| 28 | + | type | |
| 29 | + | TForm1 = class(TForm) | |
| 30 | + | cboLookup: TDBLookupComboBox; | |
| 31 | + | dsSource: TDatasource; | |
| 32 | + | dsetSource: TDataset; | |
| 33 | + | ... | |
| 34 | + | protected | |
| 35 | + | FDisplayField: string; | |
| 36 | + | FKeyField: string; | |
| 37 | + | FPreviousKeyValue: string; // May be any datatype - see below | |
| 38 | + | ... | |
| 39 | + | end; | |
| 40 | + | ||
| 41 | + | ... | |
| 42 | + | ||
| 43 | + | implementation | |
| 44 | + | ||
| 45 | + | ... | |
| 46 | + | // Remember previous value | |
| 47 | + | FPreviousKeyValue:= load_from_settings_in_your_preferred_way_; | |
| 48 | + | ||
| 49 | + | ... | |
| 50 | + | // Configure DBLookupCombo | |
| 51 | + | dsSource.Dataset := dsetSource; | |
| 52 | + | cboLookup.ListSource := dsSource; | |
| 53 | + | ||
| 54 | + | cboLookup.ScrollListDataset := True; // This ensures that changing the ComboBox will automatically scroll | |
| 55 | + | // the dataset | |
| 56 | + | cboLookup.Style := csDropDownList; | |
| 57 | + | ||
| 58 | + | cboLookup.KeyField := FKeyField; | |
| 59 | + | cboLookup.ListField := FDisplayField; // This is the field that will appear in the contents of the ComboBox | |
| 60 | + | ||
| 61 | + | dsetSource.Open; // The ComboBox should now be populated, however intially no text is displayed | |
| 62 | + | // So right now there is no relationship between the selected record in the dataset | |
| 63 | + | // and the contents of the ComboBox | |
| 64 | + | ||
| 65 | + | // cboLookup.KeyValue reads and writes a Variant, so you may actually define | |
| 66 | + | // FPreviousKeyValue as any data type you feel is appropriate. | |
| 67 | + | ||
| 68 | + | // Remember a previous value | |
| 69 | + | if FPreviousKeyValue <> '' then | |
| 70 | + | begin | |
| 71 | + | dsetSource.Locate(FKeyField, FPreviousKeyValue, []); // Note: This will fail to correctly set the ComboBox, | |
| 72 | + | // But will set the Datatset to the correct record. | |
| 73 | + | ||
| 74 | + | // Now the dataset is on the correct record, lets ensure the DBLookupCombo | |
| 75 | + | // is showing the same value as the selected record | |
| 76 | + | If (cboLookup.KeyValue = Null) And (dsetSource.RecordCount > 0) Then | |
| 77 | + | cboLookup.KeyValue := dsetSource.FieldByName(FKeyField).AsVariant; | |
| 78 | + | end; | |
| 79 | + | ||
| 80 | + | ... | |
| 81 | + | // Save current value for next time | |
| 82 | + | FPreviousKeyValue:= cboLookup.KeyValue; | |
| 83 | + | write_to_settings_in_your_preferred_way_(FPreviousValue); | |
| 84 | + | ``` | |
| 85 | + | ||
| 86 | + | ## Bugs | |
| 87 | + | ||
| 88 | + | At least for TDBLookupComboBox, there is a bug with FPC 2.6.0 (used in Lazarus 1.0, 1.0.2 etc) that requires the **listfield** to be present in the datasource as well. | |
| 89 | + | ||
| 90 | + | Workaround: you can bypass this by declaring a calculated field with the same name as the listfield in the datasource's dataset that does nothing. | |
| 91 | + | ||
| 92 | + | ## Alternative control | |
| 93 | + | ||
| 94 | + | The Rx controls (in the RxNew package) have the RxDBLookupCombobox which has some extra functionality; it e.g. allows to display multiple fields/columns next to each other (much like MS Access comboboxes): | |
| 95 | + | ||
| 96 | + | ``` pascal | |
| 97 | + | RxDBLookupCombo.LookupDisplay = 'field1;field2'; //takes a semicolon-delimited list of fields | |
| 98 | + | ``` | |
| 99 | + | ||
| 100 | + | It additionally has a property DisplayAllFields. | |
| 101 | + | ||
| 102 | + | ## See also | |
| 103 | + | ||
| 104 | + | - [[doc:lcl/dbctrls/tdblookupcombobox.html|TDBLookupComboBox doc]] | |
| 105 | + | - [[TComboBox]] | |
| 106 | + | - [[TDBComboBox]] | |
| 107 | + | ||
| 108 | + | --- | |
| 109 | + | *From the Free Pascal wiki, page "TDBLookupComboBox", as it stood on 2020-02-29 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
