Rád bych ukázal nejdříve princip toho jak LiveBinding (novinka v Delphi XE2) funguje, než budu ukazovat jak je to v IDE prováděno. Zdrojem mi bylo demo, jehož autorem je Pawel Glowacki a možná ho ukázal i v Praze a Bratislavě.
Uvedu nejprve kód, následně k tomu něco napíši.
program LiveBindingProgr;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Bindings.Expression,
System.Bindings.ObjEval,
System.Bindings.Helper;
type
TMyObject1 = class(TObject)
private
FIntegerValue: Integer;
FStringValue: String;
public
property IntegerValue: Integer read FIntegerValue write FIntegerValue;
property StringValue: String read FStringValue write FStringValue;
end;
TMyObject2 = class(TMyObject1);
TMyResultObject = class(TMyObject1);
var
MyObject1: TMyObject1;
MyObject2: TMyObject2;
MyResultObject: TMyResultObject;
BindingExpression1: TBindingExpression;
BindingExpression2: TBindingExpression;
begin
ReportMemoryLeaksOnShutdown := True;
MyObject1 := TMyObject1.Create;
MyObject2 := TMyObject2.Create;
MyResultObject := TMyResultObject.Create;
MyObject1.IntegerValue := 1;
MyObject1.StringValue := 'LiveBinding ';
MyObject2.IntegerValue := 2;
MyObject2.StringValue := 'power.';
{ a binding expression that binds the two Integer properties of the given objects }
BindingExpression1 := TBindings.CreateManagedBinding(
{ inputs }
[TBindings.CreateAssociationScope([
Associate(MyObject1, 'o1'),
Associate(MyObject2, 'o2')
])],
'(o1.IntegerValue + 10) * o2.IntegerValue',
{ outputs }
[TBindings.CreateAssociationScope([
Associate(MyResultObject, 'res')
])],
'res.IntegerValue',
nil);
{ a binding expression that binds the two String properties of the given objects }
BindingExpression2 := TBindings.CreateManagedBinding(
{ inputs }
[TBindings.CreateAssociationScope([
Associate(MyObject1, 'o1'),
Associate(MyObject2, 'o2')
])],
'(o1.StringValue) + "is "+ o2.StringValue',
{ outputs }
[TBindings.CreateAssociationScope([
Associate(MyResultObject, 'res')
])],
'res.StringValue',
nil);
TBindings.Notify(MyObject1, 'IntegerValue');
TBindings.Notify(MyObject2, 'StringValue');
Writeln('Result of add operation: ', MyResultObject.IntegerValue);
Writeln(MyResultObject.StringValue);
Readln;
MyObject1.Free;
MyObject2.Free;
MyResultObject.Free;
end.
Řádky 12 - 27 je deklarace tří tříd a jejich objektů se kterými budeme šachovat. Každá třída má property "IntegerValue" a "StringValue". Následně se tyto property nastaví na nějaké hodnoty.
Nyní se vytvoří dvě instance "vazeb", jedna pro integer hodnotu, druhá pro string hodnotu. V podstatě se definuje výraz, který určuje vazbu mezi zdrojovými "MyObject1" a "MyObject2" a cílovým MyResultObject.
V případě integer hodnot je to na řádku 51, ohledně string hodnot je to na řádku 66.
No a na nyní je jen třeba provést "šťouchnutí" do některého zdrojového objektu (tj. "MyObject1" nebo "MyObject2") - jakože došlo ke změně, neboli provést výpočet a aktualizaci cíle. Toto je ve VCL prováděno např. při OnChange TEdit nebo změně pozice v datasetu automaticky. Zde nic takového nemáme - tj. je třeba provést manuální aktualizaci. Zbytek je už jen omáčka kolem.
Výsledkem běhu je:
Result of add operation: 22
LiveBinding is power.
Celé vyhodnocování, resp. Live Bindings je postaveno na RTTI (Run Time Type Information).
Samozřejmě toto je jen jednoduchý případ a zdaleka nepostihuje možnosti Live Bindings, ale nějakou představu snad poskytne.
Jinak se můžete podívat na FishFacts Live Bindings pro FireMonkey video, které tu šlo už dříve.