2015-01-30 5 views
1

Я пытаюсь использовать livebindings для обновления свойств моих (некомпонентных) объектов. У меня есть TPrototypeBindSource, который я использую, чтобы привязывать компоненты к полям моих объектов и использовать TObjectBindSourceAdapter во время выполнения. Я могу заставить его работать, если вы звоните MyPrototypeBindSource.Refresh в событие onchange компонентов редактирования, но есть ли способ сделать это автоматически, не настраивая событие onchange для каждого компонента в моей форме?Использование TPrototypeBindSource для автоматического обновления свойств объекта

+1

Вы имеете в виду, кроме создания единого события OnChange и привязки его ко всем элементам управления редактированием? –

+0

Это мне не пришло в голову, но я также подумал, что живые привязки могут нажимать изменения без вызова ручного обновления? Или я ошибаюсь в том, как они работают? –

+0

Мне не удалось это сделать, хотя я должен признать, что мой опыт работы с LiveBindings ограничен несколькими меньшими приложениями. (У нас все еще есть большинство наших приложений в более ранней версии Delphi, которая их не поддерживает.) –

ответ

3

Хотя есть TPrototypeBindSource.AutoPost, который I suspect обрабатывает автоматическую запись данных управления объекту данных, который он не ... хорошо глядя на источник, это свойство влияет только на внутренний генератор данных.

Кажется, мы должны установить это свойство вручную при создании адаптера (и потому, что мы находимся в этой точке мы установим AutoEdit а):

procedure TForm1.PrototypeBindSource1CreateAdapter(Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter); 
begin 
    FPerson := TPerson.Create; 
    ABindSourceAdapter := TObjectBindSourceAdapter<TPerson>.Create(Self, FPerson); 
    ABindSourceAdapter.AutoEdit := True; 
    ABindSourceAdapter.AutoPost := True; 
end; 

Это сделает работу , каждый раз, когда вы оставьте a TEdit, но TCheckBox опубликует данные немедленно.

Чтобы изменить это просто использовать published методы

procedure TForm1.ControlChanged(Sender: TObject); 
begin 
    if Sender is TComponent 
    then 
    TLinkObservers.ControlChanged(Sender as TComponent); 
end; 

и назначить этого каждый необходимый контроль (например, TEdit.OnChange), чтобы получить данные непосредственно к объекту данных.

Здесь все в один присест

type 
    TPerson = class 
    private 
    FFirstname: string; 
    FLastname: string; 
    FActive: Boolean; 
    public 
    function ToString: string; override; 

    property Active: Boolean read FActive write FActive; 
    property Firstname: string read FFirstname write FFirstname; 
    property Lastname: string read FLastname write FLastname; 
    end; 

    TForm1 = class(TForm) 
    PersonSource: TPrototypeBindSource; { OnCreateAdapter -> PersonSourceCreateAdapter } 
    Edit1: TEdit; { OnChange -> ControlChanged } 
    Edit2: TEdit; { OnChange -> ControlChanged } 
    BindingsList1: TBindingsList; 
    LinkControlToField1: TLinkControlToField; 
    LinkControlToField2: TLinkControlToField; 
    Label1: TLabel; 
    ApplicationEvents1: TApplicationEvents; { OnIdle -> ApplicationEvents1Idle } 
    CheckBox1: TCheckBox; 
    LinkControlToField3: TLinkControlToField; 
    procedure PersonSourceCreateAdapter(Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter); 
    procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean); 
    private 
    FPerson: TPerson; 
    published 
    procedure ControlChanged(Sender: TObject); 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean); 
begin 
    // just for checking then object data 
    Label1.Caption := FPerson.ToString; 
end; 

procedure TForm1.ControlChanged(Sender: TObject); 
begin 
    if Sender is TComponent 
    then 
    TLinkObservers.ControlChanged(Sender as TComponent); 
end; 

procedure TForm1.PersonSourceCreateAdapter(Sender: TObject; var ABindSourceAdapter: TBindSourceAdapter); 
begin 
    FPerson := TPerson.Create; 
    ABindSourceAdapter := TObjectBindSourceAdapter<TPerson>.Create(Self, FPerson); 
    ABindSourceAdapter.AutoEdit := True; 
    ABindSourceAdapter.AutoPost := True; 
end; 

{ TPerson } 

function TPerson.ToString: string; 
begin 
    Result := FLastname + ', ' + FFirstname + ' ' + BoolToStr(FActive); 
end; 

LiveBindings:

 
Active : ftBoolean -> CheckBox1/CheckedState(Self) 
Firstname : ftString -> Edit1/Text 
Lastname : ftString -> Edit2/Text 

Если вы не хотите присвоить метод ControlChanged ко всем элементам управления можно заставить TPrototypeBindSource, чтобы отправить данных по телефону TPrototypeBindSource.Post. Но вы должны проверить в первую очередь, если он находится в режиме редактирования:

if PersonSource.Editing 
then 
    PersonSource.Post; 

Вызов этого всякий раз, когда вам нужно, чтобы данные размещены ... если в любое время просто назвать его в TApplicationEvents.OnIdle.

+0

Я предположил, что параметр AutoPost переносится с Prorotype. В большинстве случаев получение его при выходе будет достаточно хорошим для большинства целей. Благодарю. –

+0

Вы не одиноки с этим, и мне пришлось смотреть на источник, почему это не так: o) –

Смежные вопросы