# 一步一步学习使用LiveBindings(10) LiveBindings绑定到漂亮的TCombobox
<p>这一课,将演示如何绑定到TCombobox,这个控件通常用来给用户提供选项列表。它们具有比VCL控件较强的定制性,可以使用样式窗口对每一个项进行外观的定制。</p><p>如果读者已经看过《一步一步学习使用LiveBindings(9)》,那应该会比较熟悉这一课的案例,因为笔者将上一节的案例LiveBindings_BindFormat的源代码复制到了这一节作为起点。</p>
<p>在上一节的员工管理窗口中,有一个Title职位字段,在真实的项目这个字段应该是一个下列拉表框供用户选择,而不是一个文本输入框,以避免用户胡乱输入太多的职位而无法管理,效果如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/22554/202508/22554-20250810205818081-1896052198.gif"><br>
我们通常会有一个表来存放职位信息,接下来一步一步演示如何实现从数据源到Combobox下拉表列框的绑定。</p>
<p><strong>1. 打开LiveBindings_BindFormat项目的主窗体,从工具栏中拖一个TProtoTypeBindSource控件到主窗体上,将其命名为TitleBindSource,然后右击该控件,打开Fields Editor,定义如下的几个字段和生成器。</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/22554/202508/22554-20250810152439110-788722100.png"></p>
<p>几个字段的作用如下:</p>
<ul>
<li>ContactTitle:职位名称</li>
<li>TitleImageIndex:职位的图片索引,演示如何给Combobox绑定一张图片。</li>
<li>TitleDescription:职位描述</li>
<li>TitleColor:将用于职位的颜色。</li>
</ul>
<p><strong>2. 在主窗体上右击鼠标,从弹出的菜单中选择“LiveBinding Wizard...”,使用向导,选择“Link a Control with a field”菜单项,创一个新的TCombobox到数据源TitleBindSource的连接,指定FieldName为ContactTitle,向导会自动将Combobox控件的Synch与TitleBindSource的*进行连接,并有一个指向Item.Text的单向连接。</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/22554/202508/22554-20250810160413112-1035224013.png"></p>
<p>绑定的连接是一个类型为TLinkListControlToField连接类型,FireMonkey的ListBox、ListView都会使用这种类型来绑定数据。</p>
<p>设计器中的Combobox除了Synch之外,还有如下的几个可绑定类型:</p>
<ul>
<li>SelectedValue:当选中项时,SelectedValue返回的给其他数据源的数据。</li>
<li>Item.Text:显示在Combobox中的项的文本。</li>
<li>Item.ImageIndex:显示在Combobox的图片索引。</li>
<li>Item.LookupData:SelectedValue将返回的值类型,也就是要搜寻的数据。</li>
</ul>
<p>在这里需要将SelectedValue连接到EmployeeBindSource控件的Title字段,以便将当前选中的Contact Title更新到EmployeeBindSource的底层表。</p>
<p>在设计器中拖动SelectedValue到EmployeeBindSource控件的Title字段,设计器会弹出一个提示:</p>
<p><img src="https://img2024.cnblogs.com/blog/22554/202508/22554-20250810161455124-421558854.png"></p>
<p>向导会删除Synch到*的连接,接下来将如下图连接Item.ImageIndex,并指定Item.LookupData到ContactTitle,以确保SelectedValue会返回职位名称。</p>
<p><img src="https://img2024.cnblogs.com/blog/22554/202508/22554-20250810162658915-1193716938.png"></p>
<p><strong>3. 选中Combobox控件,指定其Images属性为一个TImageList,这样就会在列表项左侧显示图片。</strong></p>
<p>最终效果如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/22554/202508/22554-20250810173144675-2072439559.png"></p>
<p><strong>4. 在代码部分,更新了EmployeeObjectU.pas,添加了一个新的类TEmployeeTitle,现附上更新后的代码</strong></p>
<p>EmployeeObjectU.pas</p>
<pre><code class="language-Pascal">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.
</code></pre>
<p>在主窗体中,为TitleBindSource的OnCreateAdapter事件添加了如下的代码来:</p>
<pre><code class="language-Pascal">procedure TfrmMain.TitleBindSourceCreateAdapter(Sender: TObject;
var ABindSourceAdapter: TBindSourceAdapter);
begin
bsEmployeeTitle:= TListBindSourceAdapter<TEmployeeTitle>.Create(self, nil, True);
//赋值给TBindSourceAdapter
ABindSourceAdapter := bsEmployeeTitle;
end;
</code></pre>
<p>在FormCreate中关联了List.</p>
<pre><code class="language-Pascal">procedure TfrmMain.FormCreate(Sender: TObject);
begin
LoadData;//加载数据
//设置员工列表
bsEmployee.SetList(FEmployeeList, False);
bsEmployee.Active := True;
//设置员工编号列表
bsEmployeeTitle.SetList(FEmployeeTitleList, False);
bsEmployeeTitle.Active := True;
end;
</code></pre>
<p>最后,选中Combobox控件,设置DropDownKind为Custom,然后添加LinkFillControlToField.OnFillingListItem事件,让其在填充列表项时,指定一个列表项的样式:</p>
<pre><code class="language-Pascal">procedure TfrmMain.LinkFillControlToFieldFillingListItem(Sender: TObject;
const AEditor: IBindListEditorItem);
begin
//指定列表项的样式
(AEditor.CurrentObject as TListBoxItem).StyleLookup :='listboxitembottomdetail';
end;
</code></pre>
<p>listboxitembottomdetail是内置的列表项的样式,它需要指定Item.text和Item.Detail的值。</p>
<p>TLinkFillControlToField的ListItemStyle为ItemDataEditor,这样在LiveBindings Designer设计视图中就会显示Item.Detail和Item.Bitmap以及Item.Accessory,将Item.Detail绑定到TitleDescription即可。</p>
<p><img src="https://img2024.cnblogs.com/blog/22554/202508/22554-20250810202243974-2081133764.png"></p>
<p>显示效果如下所示:</p>
<p><img src="https://img2024.cnblogs.com/blog/22554/202508/22554-20250810202332578-1850776265.png"></p>
<p>选择使用FireMonkey的程序员,一定会被其强大的自定义样式定义所吸引,在接下来的课程中,将会讨论如何自定义样式。</p><br><br>
来源:https://www.cnblogs.com/lincats/p/19030915
頁:
[1]