Solved

Delphi - Setting selected item in DBLookupCombo at design time

Posted on 2009-07-12
15
2,717 Views
Last Modified: 2012-05-07
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?
0
Comment
Question by:gamutgroup
  • 7
  • 4
  • 2
  • +2
15 Comments
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 24837390
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
 
LVL 1

Expert Comment

by:ccupo
ID: 24837752

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
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 24838948
>>ccupo
for inserting a record, the after edit does not get fired
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 24838961
>>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
 
LVL 26

Expert Comment

by:EddieShipman
ID: 24849254
[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
 
LVL 22

Expert Comment

by:senad
ID: 24891742
set combos itemindex property to '0' or you can do it in code....
0
 
LVL 22

Expert Comment

by:senad
ID: 24891756
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:gamutgroup
ID: 24892631
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
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 24897512
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
 
LVL 26

Accepted Solution

by:
EddieShipman earned 500 total points
ID: 24898340
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
 
LVL 22

Expert Comment

by:senad
ID: 24899147
just set the keyvalue (property of dblookupcombo) to your default value  :-)
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 25002370
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
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 25002376
>>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
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 25002379
>>DBLookupCombo at design time
and for this, you'll have to create your own derived component
0
 
LVL 22

Expert Comment

by:senad
ID: 25008918
not to mention it will be all random data ....
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This video discusses moving either the default database or any database to a new volume.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now