我在表单上有 2 个控件,TCheckBox 和 TEdit。
我想使用 Live Binding 来执行此操作:
- 当 TCheckBox.Checked = True 时,设置 TEdit.PasswordChar = *
- 当 TCheckBox.Checked = False 时,设置 TEdit.PasswordChar = #0
我该如何编写 ControlExpression 来实现这一点?如果我可以避免注册自定义方法,那就太好了。
我在表单上有 2 个控件,TCheckBox 和 TEdit。
我想使用 Live Binding 来执行此操作:
我该如何编写 ControlExpression 来实现这一点?如果我可以避免注册自定义方法,那就太好了。
这是一个简单的例子。我找不到布尔表达式评估器,所以我注册了一个新的,还有一个字符串到字符的转换器(似乎也丢失了)。
表格:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 282
ClientWidth = 418
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object CheckBox1: TCheckBox
Left = 24
Top = 24
Width = 97
Height = 17
Caption = 'CheckBox1'
TabOrder = 0
OnClick = CheckBox1Click
end
object Edit1: TEdit
Left = 24
Top = 56
Width = 121
Height = 21
TabOrder = 1
Text = 'Edit1'
end
object BindingsList1: TBindingsList
Methods = <>
OutputConverters = <>
UseAppManager = True
Left = 212
Top = 13
object BindExpression1: TBindExpression
Category = 'Binding Expressions'
ControlComponent = Edit1
SourceComponent = CheckBox1
SourceExpression = 'iif(Checked, '#39'*'#39', '#39#39')'
ControlExpression = 'PasswordChar'
NotifyOutputs = True
Direction = dirSourceToControl
end
end
end
和代码:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Data.Bind.EngExt, Vcl.Bind.DBEngExt, System.Rtti,
Vcl.Bind.Editors, Data.Bind.Components, System.Bindings.Outputs;
type
TForm1 = class(TForm)
CheckBox1: TCheckBox;
Edit1: TEdit;
BindingsList1: TBindingsList;
BindExpression1: TBindExpression;
procedure CheckBox1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
System.TypInfo,
System.Bindings.EvalProtocol,
System.Bindings.Methods;
resourcestring
sIifArgError = 'Expected three variables for Iif() call';
sIifExpectedBoolean = 'First argument to Iif() must be a boolean';
function MakeIif: IInvokable;
begin
Result := MakeInvokable(
function(Args: TArray<IValue>): IValue
var
V: IValue;
B: Boolean;
begin
if Length(Args) <> 3 then
raise EEvaluatorError.Create(sIifArgError);
V := Args[0];
if (V.GetType^.Kind <> tkEnumeration) or (V.GetType^.Name <> 'Boolean') then
raise EEvaluatorError.Create(sIifExpectedBoolean);
B := V.GetValue.AsBoolean;
if B then
Result := TValueWrapper.Create(Args[1].GetValue)
else
Result := TValueWrapper.Create(Args[2].Getvalue);
end
);
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
BindingsList1.Notify(CheckBox1, 'Checked');
end;
initialization
TBindingMethodsFactory.RegisterMethod(TMethodDescription.Create(MakeIif, 'iif', 'iif', '', True, '', nil));
TValueRefConverterFactory.RegisterConversion(TypeInfo(string), TypeInfo(Char),
TConverterDescription.Create(
procedure(const I: TValue; var O: TValue)
var
S: string;
begin
S := I.AsString;
if Length(S) = 1 then
O := S[1]
else
O := #0;
end,
'StringToChar', 'StringToChar', '', True, '', nil));
finalization
TValueRefConverterFactory.UnRegisterConversion('StringToChar');
TBindingMethodsFactory.UnRegisterMethod('iif');
end.