包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...

包中创建自定义列表项:数据绑定与天气预报实战

在Delphi/FireMonkey开发中,自定义列表项(Custom List Items)是实现复杂UI交互的核心技术之一。结合LiveBindings数据绑定框架,可以快速将天气预报等动态数据展示在界面上。本文将从实战角度出发,演示如何在包中创建自定义列表项,并通过LiveBindings实现数据绑定与显示。## 一、项目准备与基础架构### 1.1 创建包和自定义列表项首先,我们需要创建一个Package(包),在其中定义自定义列表项组件。这里以天气预报数据为例,每个列表项将显示城市名称、温度、天气图标。pascal// WeatherListBoxItem.pasunit WeatherListBoxItem;interfaceuses System.SysUtils, System.Types, System.UITypes, System.Classes, FMX.Types, FMX.Controls, FMX.Graphics, FMX.Objects, FMX.Layouts, FMX.ListBox;type TWeatherListBoxItem = class(TListBoxItem) private FCityLabel: TLabel; FTempLabel: TLabel; FIcon: TImage; procedure InitializeComponents; protected procedure Resize; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; property CityLabel: TLabel read FCityLabel; property TempLabel: TLabel read FTempLabel; property Icon: TImage read FIcon; end;implementation{ TWeatherListBoxItem }constructor TWeatherListBoxItem.Create(AOwner: TComponent);begin inherited; Height := 80; // 设置列表项高度 InitializeComponents;end;destructor TWeatherListBoxItem.Destroy;begin FCityLabel.Free; FTempLabel.Free; FIcon.Free; inherited;end;procedure TWeatherListBoxItem.InitializeComponents;begin // 创建城市标签 FCityLabel := TLabel.Create(Self); FCityLabel.Parent := Self; FCityLabel.Align := TAlignLayout.Left; FCityLabel.Width := 120; FCityLabel.Text := '城市'; FCityLabel.TextSettings.Font.Size := 16; // 创建温度标签 FTempLabel := TLabel.Create(Self); FTempLabel.Parent := Self; FTempLabel.Align := TAlignLayout.Client; FTempLabel.Text := '--°C'; FTempLabel.TextSettings.Font.Size := 14; FTempLabel.TextSettings.HorzAlign := TTextAlign.Center; // 创建天气图标 FIcon := TImage.Create(Self); FIcon.Parent := Self; FIcon.Align := TAlignLayout.Right; FIcon.Width := 60; FIcon.HitTest := False;end;procedure TWeatherListBoxItem.Resize;begin inherited; // 调整子控件布局 FCityLabel.Width := Width * 0.3; FIcon.Width := Width * 0.2;end;end.### 1.2 注册组件到工具箱为了让自定义列表项在IDE中可用,需要注册组件:pascal// WeatherComponentsReg.pasunit WeatherComponentsReg;interfaceuses System.Classes, WeatherListBoxItem;procedure Register;implementationprocedure Register;begin RegisterComponents('Weather Controls', [TWeatherListBoxItem]);end;end.## 二、数据绑定与LiveBindings实现### 2.1 创建本地内存表接下来,我们创建一个天气预报数据模型,并使用TFDMemTable(内存表)存储数据:pascal// WeatherDataModule.pasunit WeatherDataModule;interfaceuses System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.Comp.DataSet, FireDAC.Comp.Client, FireDAC.Stan.StorageBin;type TWeatherDataModule = class(TDataModule) WeatherMemTable: TFDMemTable; WeatherMemTableCity: TStringField; WeatherMemTableTemperature: TFloatField; WeatherMemTableCondition: TStringField; WeatherMemTableIconIndex: TIntegerField; procedure DataModuleCreate(Sender: TObject); private procedure LoadWeatherData; public property WeatherData: TFDMemTable read WeatherMemTable; end;var WeatherDataModule: TWeatherDataModule;implementation{%CLASSGROUP 'FMX.Controls.TControl'}{$R *.dfm}procedure TWeatherDataModule.DataModuleCreate(Sender: TObject);begin // 初始化内存表 WeatherMemTable.FieldDefs.Clear; WeatherMemTable.FieldDefs.Add('City', ftString, 50); WeatherMemTable.FieldDefs.Add('Temperature', ftFloat); WeatherMemTable.FieldDefs.Add('Condition', ftString, 100); WeatherMemTable.FieldDefs.Add('IconIndex', ftInteger); WeatherMemTable.CreateDataSet; LoadWeatherData;end;procedure TWeatherDataModule.LoadWeatherData;begin // 模拟从API获取天气预报数据 WeatherMemTable.AppendRecord(['北京', 25, '晴', 1]); WeatherMemTable.AppendRecord(['上海', 28, '多云', 2]); WeatherMemTable.AppendRecord(['广州', 32, '雷阵雨', 3]); WeatherMemTable.AppendRecord(['深圳', 30, '阴', 4]); WeatherMemTable.AppendRecord(['成都', 22, '小雨', 5]);end;end.### 2.2 使用LiveBindings绑定数据在Form中,我们通过LiveBindings将内存表数据与自定义列表项关联:pascal// MainForm.pasunit MainForm;interfaceuses System.SysUtils, System.Types, System.UITypes, System.Classes, FMX.Types, FMX.Controls, FMX.Forms, FMX.ListBox, FMX.Bind.Editors, FMX.Bind.DBEditors, Data.Bind.Components, Data.Bind.DBScope, WeatherListBoxItem, WeatherDataModule;type TForm1 = class(TForm) ListBox1: TListBox; BindSourceDB1: TBindSourceDB; BindingsList1: TBindingsList; LinkListControlToField1: TLinkListControlToField; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private FWeatherDataModule: TWeatherDataModule; procedure UpdateWeatherIcon(AItem: TListBoxItem; AIconIndex: Integer); public { Public declarations } end;var Form1: TForm1;implementation{$R *.fmx}procedure TForm1.FormCreate(Sender: TObject);begin // 创建数据模块 FWeatherDataModule := TWeatherDataModule.Create(Self); // 配置LiveBindings BindSourceDB1.DataSet := FWeatherDataModule.WeatherData; LinkListControlToField1.ControlList := ListBox1; LinkListControlToField1.FieldName := 'City'; // 绑定城市字段显示 // 自定义列表项生成事件 LinkListControlToField1.OnCreateControl := procedure(Sender: TObject; AControl: TControl; AFieldName: string; var AControlClass: TControlClass) begin // 使用自定义列表项类 AControlClass := TWeatherListBoxItem; end; // 数据绑定完成后的处理 LinkListControlToField1.AfterClose := procedure(DataSet: TDataSet) begin // 遍历所有列表项,设置温度与图标 for var I := 0 to ListBox1.Count - 1 do begin var Item := TWeatherListBoxItem(ListBox1.ListItems[I]); var Rec := FindRecord(I); if Rec <> nil then begin Item.TempLabel.Text := Format('%d°C', [Trunc(Rec.FieldByName('Temperature').AsFloat)]); UpdateWeatherIcon(Item, Rec.FieldByName('IconIndex').AsInteger); end; end; end; // 激活数据绑定 LinkListControlToField1.Active := True;end;procedure TForm1.FormDestroy(Sender: TObject);begin FWeatherDataModule.Free;end;procedure TForm1.UpdateWeatherIcon(AItem: TListBoxItem; AIconIndex: Integer);begin // 根据图标索引更新图片(此处使用预设颜色模拟) var Icon := TWeatherListBoxItem(AItem).Icon; case AIconIndex of 1: Icon.Bitmap.Clear(TAlphaColors.SkyBlue); // 晴 2: Icon.Bitmap.Clear(TAlphaColors.Gray); // 多云 3: Icon.Bitmap.Clear(TAlphaColors.DarkBlue); // 雷阵雨 4: Icon.Bitmap.Clear(TAlphaColors.SlateGray); // 阴 5: Icon.Bitmap.Clear(TAlphaColors.LightBlue); // 小雨 end;end;end.## 三、运行效果与调试### 3.1 运行时数据流分析当应用启动时:1. TWeatherDataModule创建并加载5条天气预报记录到WeatherMemTable2. LinkListControlToField1激活后,自动为每条记录创建TWeatherListBoxItem实例3. AfterClose事件触发时,遍历列表项并更新温度显示与天气图标4. 用户滚动列表时,LiveBindings自动管理虚拟化,确保内存高效使用### 3.2 常见问题处理问题1:列表项高度不正确 解决方案:在TWeatherListBoxItem.InitializeComponents中设置Height := 80,并确保ListBox1.ItemHeight属性匹配。问题2:内存表数据未刷新 解决方案:调用WeatherMemTable.Refresh或重新执行LoadWeatherData。## 四、总结本文通过完整的天气预报案例,演示了以下核心技术:1. 自定义列表项创建 :在包中定义TWeatherListBoxItem,实现高度定制化UI组件2. 内存表数据管理 :使用TFDMemTable存储动态天气预报数据,支持CRUD操作3. LiveBindings集成 :通过TBindSourceDBTLinkListControlToField实现声明式数据绑定4. 运行时数据填充 :利用AfterClose事件完成列表项初始化渲染这种架构的优势在于:- 可复用性 :自定义列表项可以封装为独立组件,跨项目使用- 性能优化 :LiveBindings的虚拟化机制确保大数据量下流畅滚动- 维护性 :数据与视图分离,便于后期修改UI或数据源实战建议:对于更复杂的天气数据(如未来7天预报),可以扩展自定义列表项包含多个子控件,并通过TLinkListControlToFieldOnCreateControl事件动态绑定不同字段。同时,结合TFDMemTable的持久化功能,可以缓存最近获取的天气数据,提升离线体验。

相关推荐
学逆向的2 分钟前
inilne HOOK
前端·网络安全·hook
Lydia 不加班13 分钟前
Windows 服务器 人大金仓 54321 端口放行完整步骤
运维·服务器·windows
web打印社区32 分钟前
Vue3 发票静默打印,我这边能跑通的一版
前端·javascript·vue.js·chrome·electron
嘟哩DuliDuli1 小时前
创作 Agent 的任务状态该如何保存
android·java·javascript
Token掘金室1 小时前
JSON模式结构化输出报错
java·服务器·json
一技安身1 小时前
【信创】外网打包ragflow镜像并导入内网银河麒麟V10arm64服务器
运维·服务器
1314lay_10071 小时前
asp文件的服务器控件要使用CssClass,否则会失效。导致上传服务器之后,按钮禁用时的效果出问题了,没有正确应用样式
服务器
T01156181 小时前
全栈项目实战手记|艺培场馆课时预约小程序全项目开发历程完整复盘总结
运维·服务器·小程序
库玛西1 小时前
深度解构高并发利器:纯事件驱动 Reactor 模式的设计哲学与工程实践
服务器·开发语言·c++·笔记·tcp/ip
lemon_sjdk1 小时前
JavaScript 常用关键字全解析
开发语言·javascript·ecmascript