Delphi - Setting selected item in DBLookupCombo at design time

I have a picklist which is a TDBLookupComboBox with its (lookup) list attached to a populated dataset.

When the combo box is first displayed, I want the app to select the first item in the list rather than waiting for user to select an item. I do not know at design time what the contents of the lookup list will be other than it will not be empty.

Is it possible to programatically select an item from the list rather than relying on user input?
gamutgroupAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Geert GOracle dbaCommented:
use the AfterInsert event of the dataset to set any intial fields in the inserted record

if you want the first record, then you may need to execute a separate query to know which is first
this will also depend on sorting
unit Unit2;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DB, ExtCtrls, DBCtrls, DBClient, Mask;
 
type
  TForm2 = class(TForm)
    cds: TClientDataSet;
    dbcbbDescr: TDBLookupComboBox;
    DBNavigator1: TDBNavigator;
    ds: TDataSource;
    cdsSub: TClientDataSet;
    dsSub: TDataSource;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    DBText1: TDBEdit;
    DBText2: TDBEdit;
    procedure FormCreate(Sender: TObject);
    procedure cdsAfterInsert(DataSet: TDataSet);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form2: TForm2;
 
implementation
 
{$R *.dfm}
 
procedure TForm2.cdsAfterInsert(DataSet: TDataSet);
begin
  cds.FieldByName('cdsDescrId').AsInteger := 1;
end;
 
procedure TForm2.FormCreate(Sender: TObject);
begin
  cdsSub.Active := True;
  cdsSub.AppendRecord([1, 'Test Descr 1']);
  cdsSub.AppendRecord([2, 'Test Descr 2']);
  cdsSub.AppendRecord([3, 'Test Descr 3']);
  cdsSub.AppendRecord([4, 'Test Descr 4']);
  cds.Active :=True;
end;
 
end.
 
--dfm--
object Form2: TForm2
  Left = 0
  Top = 0
  Caption = 'Form2'
  ClientHeight = 301
  ClientWidth = 467
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 120
    Top = 34
    Width = 10
    Height = 13
    Caption = 'Id'
  end
  object Label2: TLabel
    Left = 120
    Top = 57
    Width = 27
    Height = 13
    Caption = 'Name'
  end
  object Label3: TLabel
    Left = 120
    Top = 80
    Width = 27
    Height = 13
    Caption = 'Descr'
  end
  object dbcbbDescr: TDBLookupComboBox
    Left = 168
    Top = 80
    Width = 145
    Height = 21
    DataField = 'cdsDescrID'
    DataSource = ds
    KeyField = 'cdsDescrID'
    ListField = 'cdsDescr'
    ListSource = dsSub
    TabOrder = 2
  end
  object DBNavigator1: TDBNavigator
    Left = 32
    Top = 136
    Width = 240
    Height = 25
    DataSource = ds
    TabOrder = 3
  end
  object DBText1: TDBEdit
    Left = 168
    Top = 34
    Width = 81
    Height = 17
    AutoSize = False
    Color = clWhite
    DataField = 'cdsID'
    DataSource = ds
    TabOrder = 0
  end
  object DBText2: TDBEdit
    Left = 168
    Top = 57
    Width = 145
    Height = 17
    AutoSize = False
    Color = clWhite
    DataField = 'cdsName'
    DataSource = ds
    TabOrder = 1
  end
  object cds: TClientDataSet
    Active = True
    Aggregates = <>
    FieldDefs = <
      item
        Name = 'cdsID'
        DataType = ftInteger
      end
      item
        Name = 'cdsName'
        DataType = ftString
        Size = 20
      end
      item
        Name = 'cdsDescrID'
        DataType = ftInteger
      end>
    IndexDefs = <>
    Params = <>
    StoreDefs = True
    AfterInsert = cdsAfterInsert
    Left = 24
    Top = 24
    Data = {
      570000009619E0BD010000001800000003000000000003000000570005636473
      49440400010000000000076364734E616D650100490000000100055749445448
      0200020014000A6364734465736372494404000100000000000000}
  end
  object ds: TDataSource
    DataSet = cds
    Left = 72
    Top = 24
  end
  object cdsSub: TClientDataSet
    Active = True
    Aggregates = <>
    FieldDefs = <
      item
        Name = 'cdsDescrID'
        DataType = ftInteger
      end
      item
        Name = 'cdsDescr'
        DataType = ftString
        Size = 100
      end>
    IndexDefs = <>
    Params = <>
    StoreDefs = True
    Left = 24
    Top = 80
    Data = {
      4A0000009619E0BD0100000018000000020000000000030000004A000A636473
      4465736372494404000100000000000863647344657363720100490000000100
      0557494454480200020064000000}
  end
  object dsSub: TDataSource
    DataSet = cdsSub
    Left = 72
    Top = 80
  end
end

Open in new window

0
ccupoCommented:

unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, ADODB, DBCtrls, StdCtrls;
 
type
  TForm1 = class(TForm)
    DBLookupComboBox1: TDBLookupComboBox;
    DataSource1: TDataSource;
    ADOConnection1: TADOConnection;
    ADOTable1: TADOTable;
    ADOTable2: TADOTable;
    DataSource2: TDataSource;
    Button1: TButton;
    ADOTable1SIFRA: TStringField;
    ADOTable1NAZIV: TStringField;
    ADOTable2SIFRA: TStringField;
    ADOTable2NAZIV: TStringField;
    ADOQuery1: TADOQuery;
    ADOTable2SJEDIS: TStringField;
    ADOTable1SJEDIS: TStringField;
    procedure Button1Click(Sender: TObject);
    procedure ADOTable1AfterEdit(DataSet: TDataSet);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.Button1Click(Sender: TObject);
var FirstValue:string;
begin
  ADOTable1.Active:=true;
  ADOTable2.Active:=true;
  ADOTable1.Edit;
end;
 
procedure TForm1.ADOTable1AfterEdit(DataSet: TDataSet);
var FirstValue:string;
begin
  ADOQuery1.Active:=false;
  ADOQuery1.SQL.Text:=
    'select  top 1 sifra from fs01 ';
  ADOQuery1.Active:=True;
 
  FirstValue:= ADOQuery1.fieldbyname('sifra').AsString;
  DBLookupComboBox1.KeyValue:=FirstValue;
end;
 
end.
 
////////////////////////////////////////////////////////////////
 
 
dfm:
 
object Form1: TForm1
  Left = 633
  Top = 104
  Width = 493
  Height = 350
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object DBLookupComboBox1: TDBLookupComboBox
    Left = 64
    Top = 120
    Width = 281
    Height = 21
    DataField = 'SJEDIS'
    DataSource = DataSource1
    KeyField = 'SIFRA'
    ListField = 'NAZIV'
    ListFieldIndex = 15
    ListSource = DataSource2
    TabOrder = 0
  end
  object Button1: TButton
    Left = 128
    Top = 232
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 1
    OnClick = Button1Click
  end
  object DataSource1: TDataSource
    DataSet = ADOTable1
    Left = 56
    Top = 16
  end
  object ADOConnection1: TADOConnection
    Connected = True
    ConnectionString = 
      'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initi' +
      'al Catalog=DB2007;Data Source=.'
    Provider = 'SQLOLEDB.1'
    Left = 104
    Top = 16
  end
  object ADOTable1: TADOTable
    Connection = ADOConnection1
    CursorType = ctStatic
    AfterEdit = ADOTable1AfterEdit
    TableName = 'FS01'
    Left = 160
    Top = 16
    object ADOTable1SIFRA: TStringField
      FieldName = 'SIFRA'
      Size = 15
    end
    object ADOTable1NAZIV: TStringField
      FieldName = 'NAZIV'
      Size = 60
    end
    object ADOTable1SJEDIS: TStringField
      FieldName = 'SJEDIS'
      Size = 60
    end
  end
  object ADOTable2: TADOTable
    Connection = ADOConnection1
    CursorType = ctStatic
    TableName = 'FS01'
    Left = 288
    Top = 32
    object ADOTable2SIFRA: TStringField
      FieldName = 'SIFRA'
      Size = 15
    end
    object ADOTable2NAZIV: TStringField
      FieldName = 'NAZIV'
      Size = 60
    end
    object ADOTable2SJEDIS: TStringField
      FieldName = 'SJEDIS'
      Size = 60
    end
  end
  object DataSource2: TDataSource
    DataSet = ADOTable2
    Left = 304
    Top = 64
  end
  object ADOQuery1: TADOQuery
    Connection = ADOConnection1
    Parameters = <>
    Left = 16
    Top = 16
  end
end 

Open in new window

0
Geert GOracle dbaCommented:
>>ccupo
for inserting a record, the after edit does not get fired
0
Become a CompTIA Certified Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

Geert GOracle dbaCommented:
>>ccupo
i tested it with below code :
even when editing a empty dataset , only the after insert will fire, not after edit
procedure TForm2.cdsAfterEdit(DataSet: TDataSet);
begin
  cds.FieldByName('cdsDescrId').AsInteger := 2;
  Memo1.Lines.Add('After Edit');
end;
 
procedure TForm2.cdsAfterInsert(DataSet: TDataSet);
begin
  cds.FieldByName('cdsDescrId').AsInteger := 1;
  Memo1.Lines.Add('After insert');
end;
 
procedure TForm2.FormCreate(Sender: TObject);
begin
  cdsSub.Active := True;
  cdsSub.AppendRecord([1, 'Test Descr 1']);
  cdsSub.AppendRecord([2, 'Test Descr 2']);
  cdsSub.AppendRecord([3, 'Test Descr 3']);
  cdsSub.AppendRecord([4, 'Test Descr 4']);
  cds.Active :=True;
end;

Open in new window

0
Eddie ShipmanAll-around developerCommented:
[quote]
I want the app to select the first item in the list
<SNIP>
Is it possible to programatically select an item from the list rather than relying on user input?
[/quote]

To set the lookup list to the first items you have to do this:
  DBLookupCombo1.ListSource.Dataset.First;
 
0
senadCommented:
set combos itemindex property to '0' or you can do it in code....
0
senadCommented:
Here is an example :

procedure TForm1.Button1Click(Sender: TObject);
begin
table1.open;
dblookupcombobox1.ListSource.DataSet.First;
dblookupcombobox1.KeyValue :=
dblookupcombobox1.ListSource.DataSet.FieldValues[dblookupcombobox1.ListField];
end;
0
gamutgroupAuthor Commented:
DBLookupCombo doesn't have an itemindex property. The list is a dataset, not a stringlist (or list)

Solutions based on "dblookupcombobox1.ListSource.DataSet.First" look right but don't seem to work - i.e. moving the record pointer in the underlying dataset programatically doesn't seem to affect which item in the dropdown is selected
0
Geert GOracle dbaCommented:
you can't change the combobox
you can only change the value of the field
the combobox will set itself

not the other way around
0
Eddie ShipmanAll-around developerCommented:
There is no way to do this without focusing the DBLookupCombo, calling the DropDown and sending it key events
to select the first item.

Reasoning is this:
TDBLookupComboBox is NOT a ComboBox control.
It has a TPopupDataList property, which has a SelectedItems BUT you cannot access it because it is private.
I can get the handle to the list but it also entails calling dropdown. However, once you have the handle, you cannot
send it regular List control messages. It is derived from TDBLookupListBox which will not accept list control messages.

The only way to do this is to write your own control and expose the private TPopupDataList.

Geert has the idea, though, if you set the Datasource's value to the first value in the ListSource, it will show the
first value in the list, like below...


with DBLookupComboBox1 do
begin
  ListSource.DataSet.First;
  // Locate the record you want to store the value to first before you edit!
  DataSource.DataSet.Edit;
  DataSource.DataSet.FieldByName(DataField).Value :=
      ListSource.DataSet.FieldByName(ListField).Value;
  DataSource.DataSet.Post;
end;

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
senadCommented:
just set the keyvalue (property of dblookupcombo) to your default value  :-)
0
Geert GOracle dbaCommented:
not that you might think, but you accepted a wrong answer ...

afterinsert
--> dataset is in edit mode and you can directly set the field as in my sample

browsing mode for existing records
--> if you call this method your field will change to the first listsource value and be posted (it won't even show the original value, well it will, but only for the time you can blink)

--> browsing mode with no records
dataset.post will create a record

Have you tested this solution ?
0
Geert GOracle dbaCommented:
>>EddieShipman
these 2 lines:
-->  DataSource.DataSet.Edit;
-->  DataSource.DataSet.Post;

what if in insert mode ?
what if empty dataset ? (other key fields may be required)

>>gamutgroup
if you post the piece of your code where you use this,
i'll immediately point you to the problems

0
Geert GOracle dbaCommented:
>>DBLookupCombo at design time
and for this, you'll have to create your own derived component
0
senadCommented:
not to mention it will be all random data ....
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.