2012-07-20 1 views
2

폼에 TCheckBox와 TEdit이라는 두 개의 컨트롤이 있습니다.TCheckBox.Checked를 기반으로 TEdit.PasswordChar를 제어하는 ​​라이브 바인딩 표현식을 작성하는 방법?

  1. 진정한 TCheckBox.Checked =이 설정되면 TEdit.PasswordChar = *
  2. 때 TCheckBox.Checked = 거짓, 설정 TEdit.PasswordChar = # 0 :

    나는이 작업을 수행하기 위해 라이브 바인딩을 사용하려면

어떻게 이것을 구현하려면 ControlExpression을 작성할 수 있습니까? 만약 내가 커스텀 메소드를 등록하는 것을 피할 수 있다면 좋을 것이다.

+4

더 나은 할당 작업에 체크 박스 및 실행의 "기본"코드를 작성합니다. 라이브 바인딩을 사용하는 일부 경우에는 이유가있을 수 있지만, 게으른 프로그래머에게는 그렇지 않을 수도 있습니다.) – Marcodor

답변

2

다음은 간단한 예입니다. 부울 식 계산기를 찾을 수 없으므로 새 목록을 등록하고 문자열 - 문자 변환기 (누락 된 것으로 보임)도 등록했습니다.

형태 :

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. 
+4

이 예제는 라이브 바인딩 디자인이 얼마나 우스 꽝 스러운지 보여줍니다. 수많은 코드를 작성하고 ** 여전히 ** OnClick 이벤트를 구현해야합니다. –

+0

** 여기에 표시된 것처럼 ** OnClick 이벤트 핸들러를 구현하지 않아도됩니다 **. 다른 가능성이 있습니다 (예 : Actions와 유사한 모든 활성 바인딩을 자동으로 재평가하는 일반 코드가있는 'Application.OnIdle'). –

+0

더욱 악화됩니다. 구성 요소는 바인딩 인식을해야하며 이론적으로는 afaik 데이터 세트로 작업 할 때 사용되는 bindlink를 지원하기 때문에 사용됩니다. 그러나 단순한 데이터 개체 바인딩에 대한 구성 요소에서 구성 요소 또는 구성 요소로 제대로 작동하지 않습니다. –

관련 문제