一步一步学习使用LiveBindings(9) LiveBindings图像绑定与自定义绑定方法(2)
一步一步学习使用LiveBindings(9) LiveBindings图像绑定与自定义绑定方法(2)
这是《一步一步学习使用LiveBindings(8)》的接续,本章将学习如下知识点:
- 为TGrid应用列格式。
- 创建自定义的绑定方法。
- 实现表单级别的格式化方法。
上一节使用向导将TGrid绑定到ProtoTypeBindSource,它会创建TLinkGridToDataSource这个绑定链接。向导创建的绑定只是将PrototypeBindSource1的*与TGrid的*进行了绑定,这种绑定模式在运行时会自动创建Column,所以设计时没有办法去操控列。
绑定的正确方式应该是在PrototypeBindSource1的Field与TGrid的Column进行绑定,
1. Grid的列格式化
如果需要对单独的列进行操作,可以使用两种方法:
- 选中LinkGridToDataSourcePrototypeBindSource1,然后在属性编辑器中选择“Columns”属性,单击右侧的按钮,打开列编辑器,在这里手动添加新的列,并设置DataMember为相应的字段,或者单击“Add All Fields”按钮,将一次性添加所有的字段。
- 在LiveBindings Designer中将Field直接拖动到TGrid上,完成绑定操作。
在完成后,在LiveBindings Designer选中任意一条连接线,属性面板上均只显示LinkGridToDataSourcePrototypeBindSource1这个绑定链接,因此如果要添加公式,需要在属性面板中,打开Columns编辑器,选中某一个具体的Column进行设置。
每一个Column具有如下的一些属性:
- ColumnStyle : 默认情况下,列被创建为 TStringColumn 。但是,您可能希望选择一个与其内容相关的更好值(数字、日期值等)。
- CustomFormat : 此属性允许您指定用于在网格中渲染值的表达式。
- CustomParse : 此属性允许您指定用于将用户输入的值转换为列的适当值的表达式。
- Header : 该属性设置列的标题。
- MemberName : 该属性设置列的对应字段。
- ReadOnly : 该属性定义列是否可以被用户编辑。
- Visible : 该属性设置列的可见性(你可以创建列,然后决定每列的可见性)。
- Width : 该属性指定列的宽度。
CustomFormat和CustomParse格式表达式,与本系列在《一步一步学习使用LiveBindings(8)》中介绍的使用方式完全相同。
下图是接下来实现的效果:
这里为HireDate列应用了日期格式化,
CustomFormat:
FormatDateTime('MMMM yyyy',self.Value)
Salary列应用了货币格式化。
CustomFormat:
Format('%%m', self.Value + 0.0)
CustomParse:
SubString(%s, 1, 15)
在Grid最后添加了2列,一列是薪资等级,如果薪资高的,就加了一个绿色向上的手势,如果薪资不是那么高的,就加了一个绿色的手势。看上去就显得专业多了。
要实现这样的目的,在这里添加了2个新的列,一个列的ColumnStyle指定为GlyphColumn,另一个列指定为ProgressColumn列类型。
注意:虽然属性编辑器中,ColumnStyle下拉框并没有提供一个ProgressColumn类型,但仍然可以通过输入ProgressColumn来显示进度条。
GlyphColumn可以显示来自TImageList控件中的图片,因此在主窗体上添加了一个TImageList控件,将TGrid的Images属性指向它。
在这个ImageList控件中,仅放了2张图片,分别是2个手势,因此其ImageIndex分别为0和1。在CustomFormat中,写下如下的公式:
IfThen(Self.Value>60000, 0, 1)
如果年薪大于6万,则认为是高薪了,打个绿色的手势,否则显示红色的手势。
ProgressColumn将使用表达式给它一个当前最高薪资的比率。如果是Manager,则最高薪资为20万,否则最高薪资设为10万。公式如下:
100*(Self.Value /IfThen(Owner.Title.Value='Manager', 200000, 100000) )
可以看到在表达式中又套用了表达式,这个可以灵活应用。
2. 自定义绑定方法
货币格式目前的解析公式不能满足需求,SubString(%s, 1, 15)虽然简单的移除了前缀的货币符号,但是对于数字中的分隔符号就不能识别,因此会发生错误。系统内置的方法并没有好的解决方案,好在还可以创建自定义的绑定方法。
请按下面的步骤实现自定义的绑定方法:
1. 单击主菜单中的 File > New > Package ,创建一个新的Delphi包。
建议立即单击工具栏上的Save All按钮,将包保存为CurrencyBindingMethod.dproj。
然后在包中添加一个新的Unit,保存为Methods.FormatCurrency.pas。
创建自定义绑定方法需要调用System.Bindings.Methods单元中的MakeInvokable方法,它返回定义在System.Bindings.EvalProtocol单元中的IInvokable接口,需要在uses区中添加对这2个单元的引用。
完整代码如下所示,请参考代码步骤:
unit Methods.FormatCurrency;
interface
uses
SysUtils;
implementation
uses
//MakeInvokable 函数、 TMethodDescription 类型定义和 TBindingsMethodFactory 单例
System.Bindings.Methods,
//IValue,TValueWrapper 和 IInvokable 类型定义
System.Bindings.EvalProtocol;
//将货币类型专换为字符串类型
function CurrencyToStrInvokable: IInvokable;
begin
Result := MakeInvokable(
function (Args: TArray<IValue>): IValue
var
AValue:Currency;
CurrencyStr:string;
begin
// 1 - 输入参数识别并进行验证
if Length(Args) < 1 then
raise EEvaluatorError.Create('CurrencyToStr: 至少需要一个参数');
// 2 - 调用真实的转换CurrToStrF方法
AValue:=Args[0].GetValue.AsCurrency;
CurrencyStr:= CurrToStrF(AValue, ffCurrency, 2);
// 3 - 将结果值打包为TValueWrapper
Exit(TValueWrapper.Create(CurrencyStr));
end
);
end;
//将字符串类型专换为货币类型。
function StrToCurrencyInvokable: IInvokable;
begin
Result := MakeInvokable(
function (Args: TArray<IValue>): IValue
var
AValue:String;
CurrencyVal:Currency;
C: char;
LDigits: string;
begin
// 1 - 输入参数识别并进行验证
if Length(Args) < 1 then
raise EEvaluatorError.Create('StrToCurrency: 至少需要一个参数');
// 2 - 将参数转换为真实的参数类型,再进行实际的业务处理
AValue:=Args[0].GetValue.AsString;
for C in AValue do
case C of
'0'..'9',
'.':
LDigits := LDigits + C;
end;
CurrencyVal := StrToCurr(LDigits);
// 3 - 将结果装包装起来
Exit(TValueWrapper.Create(CurrencyVal));
end
);
end;
initialization
// 4 - 注册方法
TBindingMethodsFactory.RegisterMethod(
TMethodDescription.Create(
CurrencyToStrInvokable
, 'CurrencyToStr', 'CurrencyToStr', '', True
, '货币转换为字符串'
, nil
)
);
TBindingMethodsFactory.RegisterMethod(
TMethodDescription.Create(
StrToCurrencyInvokable
, 'StrToCurrency', 'StrToCurrency', '', True
, '字符串转换为货币'
, nil
)
);
finalization
// 5 - 卸载已经注册的方法
TBindingMethodsFactory.UnRegisterMethod('CurrencyToStr');
TBindingMethodsFactory.UnRegisterMethod('StrToCurrency');
end.
可以看到,代码中定义了CurrencyToStr和StrToCurrency这两个方法,它们都接收一个参数,并且调用了SysUtil中的CurrToStrF和StrToCurr函数进行了转换。
2. 在Project Manager窗口右击CurrencyBindingMethod项目名称,先Build一次,再单击"Install"菜单项进行安装。
安装完成后,回到LiveBindings_BindFormat.dproj项目,选中TBindingList控件,在属性编辑器中找到Methods属性,单击右侧的按钮,可以看到CurrencyToStr和StrToCurrency这两个方法已经出现在了列表中。
3. 要让我们自己的项目能够正确识别这2个方法,还需要将包中的Methods.FormatCurrency.pas单元添加到uMainForm.pas的uses区,否则会提示方法无法找到的错误。
请在Project > Options > Delphi Compiler > Search Path路径中添加了对Package代码的引用。
在uses区中添加如下的引用:
implementation
{$R *.fmx}
uses
System.Bindings.Helper, System.Bindings.Methods,
System.Bindings.EvalProtocol,Methods.FormatCurrency;
将Salary的公式改为如下:
CustomFormat:
CurrencyToStr(self.Value)
CustomParse
StrToCurrency(%s)
经过这样的处理,现在在货币的显示和输入上,就非常理想了,如下图所示:
4. 使用自定义的格式化方法
在《一步一步学习使用LiveBindings(8)》中曾经介绍过通过self.owner.owner,返回到了主窗体TMainForm,我们在主窗体上定义了一个属性MyProgName,可以通过self.owner.owner.MyProgName访问到此属性。同理,还可以在主窗体上定义一个函数,通过self.owner.owner进行访问,实现自定义的格式化方法。
实现过程如下:
1. 首先在uMainForm的public区定义了一个函数,实现根据指定的格式化字符串格式化数字,定义与实现如下所示:
public
{ Public declarations }
property MyProgName:string read GetProgName;
//根据指定的格式化字符串或区域格式化符点数。
function FormFormatFloat(const AFormat: string; const AValue: Extended; const ALocale: string): string;
end;
var
frmMain: TfrmMain;
implementation
{$R *.fmx}
uses
System.Bindings.Helper, System.Bindings.Methods,
System.Bindings.EvalProtocol,Methods.FormatCurrency;
function TfrmMain.FormFormatFloat(const AFormat: string; const AValue: Extended;
const ALocale: string): string;
var
LFormatSettings: TFormatSettings;
begin
LFormatSettings := FormatSettings;
if not ALocale.IsEmpty then
LFormatSettings := TFormatSettings.Create(ALocale);
Result := FormatFloat(AFormat, AValue, LFormatSettings);
end;
接下来,我使用LiveBindings Wizard向导新建了一个TEdit指向Salary的链接,然后为这个TEdit的绑定链接指定CustomFormat如下,使其保留4位小数:
Self.Owner.Owner.FormFormatFloat('#,#0.0000', self.Value, '')
效果如下:
可以看到,果然正确的实现了格式化显示。
右边的那个手势图标,是一个TGlyph组件,它可以连接到一个TImageList控件,通过在LiveBindings Designer中,将Salary绑定到其ImageIndex属性。最后应用了如下的公式:
IfThen(Self.Value>60000, 0, 1)
总结
本文介绍了格式化的几种进阶方法:
- 使用表达式列格式化。
- 自定义绑定方法。
- 使用自定义表单方法格式化。
强烈推荐使用自定义绑定方法,不是很推荐自定义表单方法,但有时候表单级别的方法能解决很多业务逻辑相关的格式化问题。所以具体如何架构,还是要具体问题,具体分析。
一步一步学习使用LiveBindings(9) LiveBindings图像绑定与自定义绑定方法(2)的更多相关文章
- 12.Linux软件安装 (一步一步学习大数据系列之 Linux)
1.如何上传安装包到服务器 有三种方式: 1.1使用图形化工具,如: filezilla 如何使用FileZilla上传和下载文件 1.2使用 sftp 工具: 在 windows下使用CRT 软件 ...
- (转) 一步一步学习ASP.NET 5 (四)- ASP.NET MVC 6四大特性
转发:微软MVP 卢建晖 的文章,希望对大家有帮助.原文:http://blog.csdn.net/kinfey/article/details/44459625 编者语 : 昨晚写好的文章居然csd ...
- (转) 一步一步学习ASP.NET 5 (二)- 通过命令行和sublime创建项目
转发:微软MVP 卢建晖 的文章,希望对大家有帮助. 注:昨天转发之后很多朋友指出了vNext的命名问题,原文作者已经做出了修改,后面的标题都适用 asp.net 5这个名称. 编者语 : 昨天发了第 ...
- 一步一步学习SignalR进行实时通信_1_简单介绍
一步一步学习SignalR进行实时通信\_1_简单介绍 SignalR 一步一步学习SignalR进行实时通信_1_简单介绍 前言 SignalR介绍 支持的平台 相关说明 OWIN 结束语 参考文献 ...
- 一步一步学习SignalR进行实时通信_8_案例2
原文:一步一步学习SignalR进行实时通信_8_案例2 一步一步学习SignalR进行实时通信\_8_案例2 SignalR 一步一步学习SignalR进行实时通信_8_案例2 前言 配置Hub 建 ...
- 一步一步学习SignalR进行实时通信_9_托管在非Web应用程序
原文:一步一步学习SignalR进行实时通信_9_托管在非Web应用程序 一步一步学习SignalR进行实时通信\_9_托管在非Web应用程序 一步一步学习SignalR进行实时通信_9_托管在非We ...
- 一步一步学习SignalR进行实时通信_7_非代理
原文:一步一步学习SignalR进行实时通信_7_非代理 一步一步学习SignalR进行实时通信\_7_非代理 SignalR 一步一步学习SignalR进行实时通信_7_非代理 前言 代理与非代理 ...
- 一步一步学习SignalR进行实时通信_5_Hub
原文:一步一步学习SignalR进行实时通信_5_Hub 一步一步学习SignalR进行实时通信\_5_Hub SignalR 一步一步学习SignalR进行实时通信_5_Hub 前言 Hub命名规则 ...
- 一步一步学习SignalR进行实时通信_6_案例
原文:一步一步学习SignalR进行实时通信_6_案例 一步一步学习SignalR进行实时通信\_6_案例1 一步一步学习SignalR进行实时通信_6_案例1 前言 类的定义 各块功能 后台 上线 ...
- 一步一步学习SignalR进行实时通信_4_Hub
原文:一步一步学习SignalR进行实时通信_4_Hub 一步一步学习SignalR进行实时通信\_4_Hub SignalR 一步一步学习SignalR进行实时通信_4_Hub 前言 创建Hub 配 ...
随机推荐
- 把PDF转换成指定后缀名的图片
生活中难免遇到各种文件类型转换的问题,尤其是在办理一些证件的时候.例如,申请居住证积分的时候,把PDF版本的毕业证扫描件转换成jpg或者png等.下面提供一个工具,用于把PDF转换成指定后缀名的图 ...
- SSH实现服务器之间免密登录
1.介绍 SSH(Secure Shell)是一种用于计算机之间安全远程登录和其他网络服务的协议,它通过加密通信来确保在不安全的网络中也能安全地传输数据.SSH可以用于登录远程主机.执行命令和管理远程 ...
- 记一次使用Flannel插件排错历程
记一次使用Flannel插件排错历程 原来使用的是Calico插件,这不准备学习K8s的网络,就准备换成Flannel了,然后噩梦就开始了... 直接使用kubectl apply -f 安装了fla ...
- idea里面怎么把自己项目添加maven
首先你要清楚什么是maven: maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件.Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具 ...
- 1分钟了解 GPT-1到GPT-3 演化过程
在研发ChatMoney这款产品的时候,我开始深入研究GPT的诞生,逐记录下来分享给大家. 前言 Generative Pre-trained Transformer(GPT)系列是由OpenAI开发 ...
- php链式调用
我们经常在项目中会写到 Mode::find()->where()->orderBy()->limit(); 链式调用,那么它是怎么实现的呢? 昨天看韩天峰大佬的视频,学到了 关键点 ...
- Java集合--LinkedList源码可视化
集合节点保存的都是对象的引用,而非具体值,文中案例仅仅为了方便实现原理的演示. 1. 底层数据结构 LinkedList 基于 双向链表 实现,内部通过 Node<E> 节点相互连接: p ...
- 数栈干货分享!babel-plugin-import最全源码详解
本文将带领大家解析babel-plugin-import 实现按需加载的完整流程,解开业界所认可 babel 插件的面纱. 首先供上babel-plugin-import插件 一.初见萌芽 首先 ...
- SpringBoot + Junit5 + MockMvc 写单元测试
1.1 junit5 版本5.6.0 pom文件如下: <properties> <junit.jupiter.version>5.6.0</junit.jupit ...
- Windows链接创建神器:一键生成符号链接与硬链接的智能批处理工具【NuGet】
[自用工具]NuGet 或各项目中共用部分目录或文件,利用DOS符号链接解决重复文件的多份拷贝,起到节省磁盘空间的作用. 告别复杂的命令行操作!这款增强版批处理脚本让Windows链接创建变得简单.直 ...