這一課,將演示如何綁定到TCombobox,這個控件通常用來給用户提供選項列表。它們具有比VCL控件較強的定製性,可以使用樣式窗口對每一個項進行外觀的定製。
如果讀者已經看過《一步一步學習使用LiveBindings(9)》,那應該會比較熟悉這一課的案例,因為筆者將上一節的案例LiveBindings_BindFormat的源代碼複製到了這一節作為起點。
在上一節的員工管理窗口中,有一個Title職位字段,在真實的項目這個字段應該是一個下列拉表框供用户選擇,而不是一個文本輸入框,以避免用户胡亂輸入太多的職位而無法管理,效果如下所示:
我們通常會有一個表來存放職位信息,接下來一步一步演示如何實現從數據源到Combobox下拉表列框的綁定。
1. 打開LiveBindings_BindFormat項目的主窗體,從工具欄中拖一個TProtoTypeBindSource控件到主窗體上,將其命名為TitleBindSource,然後右擊該控件,打開Fields Editor,定義如下的幾個字段和生成器。

幾個字段的作用如下:
- ContactTitle:職位名稱
- TitleImageIndex:職位的圖片索引,演示如何給Combobox綁定一張圖片。
- TitleDescription:職位描述
- TitleColor:將用於職位的顏色。
2. 在主窗體上右擊鼠標,從彈出的菜單中選擇“LiveBinding Wizard...”,使用嚮導,選擇“Link a Control with a field”菜單項,創一個新的TCombobox到數據源TitleBindSource的連接,指定FieldName為ContactTitle,嚮導會自動將Combobox控件的Synch與TitleBindSource的*進行連接,並有一個指向Item.Text的單向連接。

綁定的連接是一個類型為TLinkListControlToField連接類型,FireMonkey的ListBox、ListView都會使用這種類型來綁定數據。
設計器中的Combobox除了Synch之外,還有如下的幾個可綁定類型:
- SelectedValue:當選中項時,SelectedValue返回的給其他數據源的數據。
- Item.Text:顯示在Combobox中的項的文本。
- Item.ImageIndex:顯示在Combobox的圖片索引。
- Item.LookupData:SelectedValue將返回的值類型,也就是要搜尋的數據。
在這裏需要將SelectedValue連接到EmployeeBindSource控件的Title字段,以便將當前選中的Contact Title更新到EmployeeBindSource的底層表。
在設計器中拖動SelectedValue到EmployeeBindSource控件的Title字段,設計器會彈出一個提示:

嚮導會刪除Synch到*的連接,接下來將如下圖連接Item.ImageIndex,並指定Item.LookupData到ContactTitle,以確保SelectedValue會返回職位名稱。

3. 選中Combobox控件,指定其Images屬性為一個TImageList,這樣就會在列表項左側顯示圖片。
最終效果如下所示:

4. 在代碼部分,更新了EmployeeObjectU.pas,添加了一個新的類TEmployeeTitle,現附上更新後的代碼
EmployeeObjectU.pas
unit EmployeeObjectU;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, System.StrUtils;
type
TEmployee = class
private
FContactBitmap: TBitmap; //聯繫人圖片
FContactName: string; //聯繫人名稱
FTitle: string; //職位
FHireDate: TDate; //僱傭日期
FSalary: Integer; //薪水
FAvailNow: Boolean; //是否在職
public
constructor Create(const NewName: string;
const NewTitle: string;
const NewHireDate: TDate;
const NewSalary: Integer;
const NewAvail: Boolean);
property ContactBitmap: TBitmap read FContactBitmap write FContactBitmap;
property ContactName: string read FContactName write FContactName;
property Title: string read FTitle write FTitle;
property HireDate: TDate read FHireDate write FHireDate;
property Salary: Integer read FSalary write FSalary;
property AvailNow: Boolean read FAvailNow write FAvailNow;
end;
type
TEmployeeTitle = class
private
FContactTitle: string; //職位名稱
FTitleColor: Cardinal; //顯示顏以
TTitleImageIndex: Integer; //顯示圖標索引
TTitleDescription: string; //職位描述
public
constructor Create(const NewTitle: string;
const NewTitleDesc: string;
const NewTitleColor: Cardinal;
const NewImageIdx: Integer);
property ContactTitle: string read FContactTitle write FContactTitle;
property TitleColor: Cardinal read FTitleColor write FTitleColor;
property TitleImageIndex: Integer read TTitleImageIndex write TTitleImageIndex;
property TitleDescription: string read TTitleDescription write TTitleDescription;
end;
implementation
{ TEmployee }
constructor TEmployee.Create(const NewName, NewTitle: string;
const NewHireDate: TDate; const NewSalary: Integer; const NewAvail: Boolean);
var
NewBitmap: TBitmap;
ResStream: TResourceStream;
begin
//將根據聯繫人名稱姓來關聯資源文件
ResStream := TResourceStream.Create(HINSTANCE, 'Bitmap_' + LeftStr(NewName, Pos(' ', NewName) - 1), RT_RCDATA);
try
NewBitmap := TBitmap.Create;
NewBitmap.LoadFromStream(ResStream);
finally
ResStream.Free;
end;
FContactName := NewName;
FTitle := NewTitle;
FContactBitmap := NewBitmap; //來自資源的圖片
FHireDate := NewHireDate;
FSalary := NewSalary;
FAvailNow := NewAvail;
end;
{ TEmployeeTitle }
constructor TEmployeeTitle.Create(const NewTitle, NewTitleDesc: string;
const NewTitleColor:Cardinal;const NewImageIdx: Integer);
begin
FContactTitle := NewTitle;
FTitleColor := NewTitleColor;
TTitleImageIndex := NewImageIdx; //來自TImageList的圖片
TTitleDescription:= NewTitleDesc;
end;
end.
在主窗體中,為TitleBindSource的OnCreateAdapter事件添加了如下的代碼來:
procedure TfrmMain.TitleBindSourceCreateAdapter(Sender: TObject;
var ABindSourceAdapter: TBindSourceAdapter);
begin
bsEmployeeTitle:= TListBindSourceAdapter<TEmployeeTitle>.Create(self, nil, True);
//賦值給TBindSourceAdapter
ABindSourceAdapter := bsEmployeeTitle;
end;
在FormCreate中關聯了List.
procedure TfrmMain.FormCreate(Sender: TObject);
begin
LoadData; //加載數據
//設置員工列表
bsEmployee.SetList(FEmployeeList, False);
bsEmployee.Active := True;
//設置員工編號列表
bsEmployeeTitle.SetList(FEmployeeTitleList, False);
bsEmployeeTitle.Active := True;
end;
最後,選中Combobox控件,設置DropDownKind為Custom,然後添加LinkFillControlToField.OnFillingListItem事件,讓其在填充列表項時,指定一個列表項的樣式:
procedure TfrmMain.LinkFillControlToFieldFillingListItem(Sender: TObject;
const AEditor: IBindListEditorItem);
begin
//指定列表項的樣式
(AEditor.CurrentObject as TListBoxItem).StyleLookup :='listboxitembottomdetail';
end;
listboxitembottomdetail是內置的列表項的樣式,它需要指定Item.text和Item.Detail的值。
TLinkFillControlToField的ListItemStyle為ItemDataEditor,這樣在LiveBindings Designer設計視圖中就會顯示Item.Detail和Item.Bitmap以及Item.Accessory,將Item.Detail綁定到TitleDescription即可。

顯示效果如下所示:

選擇使用FireMonkey的程序員,一定會被其強大的自定義樣式定義所吸引,在接下來的課程中,將會討論如何自定義樣式。