2005年06月10日

好吧,我面临一个任务,在BCB中,要根据输入的数据在数据库中查找相关的数据,如果有多条记录就需要显示一个ListBox供用户选择。



传统的做法是,用TListBox来显示ListBox……这恐怕用脚后跟都能想到。



例如使用ADOQuery,我们要把Query的DataSet取出需要显示的字段的数据加入ListBox中显示出来。然后根据选择把相应的信息显示或者处理。



这涉及到很多过程:



//从Query读数据出来,加入到ListBox:



while(!ADOQuery1->Eof)

{

    AnsiString name  = ADOQuery1->FieldByName("Name")->AsString.Trim();

    AnsiString num = ADOQuery1->FieldByName("Number")->AsString.Trim();

    ListBox1->Items->Add(Name+" "+Number);

    ADOQuery1->Next();

}

ListBox1->Show();


//在ListBox的OnClick事件中处理选择:



AnsiString text;

text=ListBox1->Items->operator [](ListBox1->ItemIndex);

int i=1;

for(int j=0;j<text.Length();j++)

{

     if(text.operator [](i)!=’ ‘)

           i++;

}

Edit1->Text=text.SubString(0,i-1);

ListBox1->Clear();

ListBox1->Visible=false;




那么我还要根据选择在数据库中读取其他字段怎么办呢?重新根据选择的内容查询?或者当初读出来的数据缓存到一个空间里面和ListBox1的ItemIndex关联?无论怎么做代码都不少写。



在查询很复杂,用户操作步骤很多,或者无法预知用户步骤的时候,我们需要多次对数据集进行操作。在这个时候我们真的必须把数据都读到ListBox中然后再操作吗?当然不用。我们有TDBLookupListBox。



但是我觉得它不够好用,一个投机取巧的办法是直接用DBGrid作为List。谁说List就一定要用ListBox了。把DBGrid属性中的
Option展开,设置:dgTitles、dgIndicator 、 dgColLines
、dgRowLines为false,设置dgRowSelect
为true。然后设置ReadOnly为true,怎么样,能看出来DBGrid和ListBox有什么区别了么?



我们可以再ADOQuery中select需要的字段,加入datasource,在DBGrid中显示出来。而不需要显示出来,却需要用的字段我们可以通过下面的手段隐藏掉。

例:

ADOQuery1->Close();

ADOQuery1->SQL->Clear();

ADOQuery1->SQL->Add("select Name, Number,Birthday,Address from MemberInfo where Name = :name");

ADOQuery1->Parameters->ParamByName("name")->Value = name;

ADOQuery1->Open();



DBGrid1->Columns[0].operator[](2)->Visible = false;

DBGrid1->Columns[0].operator[](3)->Visible = false;

DBGrid1->Show();


这样Brithday和Address字段我们就看不到了。但是他们就在数据集里面,我们甚至不需要编写多少处理Click事件的代码就可以轻松在Edit中显示想要的数据,或者进一步处理了。



要做的仅仅是在DBGrid的OnCellClick事件中通过简单的ADOQuery1->FieldByName("…")把想要的字段数据取出来并且加入处理过程这么简单了。



有时候,这种办法可以瞬间使得头疼的过程变得轻松异常。一个DBGrid可以起到几个DBLookupListBox的作用,在一些特别的地方可以试试这种特别的ListBox。至少想到这种方法以后,今天就把几个原来查询过程不太人性化的窗体重写了,效果还不错。