问题
I have 2 controls on a form, TCheckBox and TEdit.
I want to use Live Binding to perform this:
- When TCheckBox.Checked = True, set TEdit.PasswordChar = *
- When TCheckBox.Checked = False, set TEdit.PasswordChar = #0
How may I write ControlExpression to achieve this? It would be great if I can avoid register custom method.
回答1:
Here's a simple example. I couldn't find a boolean expression evaluator so I registered a new one, and also a string-to-char converter (seems to be missing, too).
The form:
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
and the code:
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.
来源:https://stackoverflow.com/questions/11573434/how-to-write-live-binding-expression-that-control-tedit-passwordchar-based-on-tc