Programatically Binding Created Objects
Go Up to Tutorial: Using LiveBinding Programatically
- Caution: The programmatic method described here is NOT the standard way to implement binding expressions. Typically, you would use the Object Inspector (the standard method) at design time. You might never need to use the programmatic way of creating binding expressions. This tutorial demonstrates, however, that it is possible to manually create such expressions.
- For examples of using LiveBindings in the standard way, see:
Now, for the binding part, you need to create a binding expression that instructs the LiveBinding engine how to bind objects to each other and what operations to do with bound properties.
The following code snippet shows you how to bind the two properties of the input (MyObject1 and MyObject2) objects to the output (MyResultObject) object. The syntax is a little bulky and will be explained below, after the code snippet.
Delphi:
var
BindingExpression1: TBindingExpression;
BindingExpression2: TBindingExpression;
begin
{ 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 + 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 + o2.StringValue',
{ outputs }
[TBindings.CreateAssociationScope([
Associate(MyResultObject, 'res')
])],
'res.StringValue',
nil);
end;
C++:
TBindingExpression *BindingExpression1, *BindingExpression2;
OpenArray<_di_IScope>InputScopes
(TBindings::CreateAssociationScope
(OPENARRAY(TBindingAssociation, (Associate(MyObject1, "o1"),
Associate(MyObject2, "o2")))));
OpenArray<_di_IScope>OutputScopes
(TBindings::CreateAssociationScope
(OPENARRAY(TBindingAssociation, (Associate(MyResultObject,
"res")))));
BindingExpression1 = TBindings::CreateManagedBinding(InputScopes,
InputScopes.GetHigh(), "o1.IntegerValue + o2.IntegerValue",
OutputScopes, OutputScopes.GetHigh(), "res.IntegerValue", NULL);
BindingExpression2 = TBindings::CreateManagedBinding(InputScopes,
InputScopes.GetHigh(), "o1.StringValue + o2.StringValue",
OutputScopes, OutputScopes.GetHigh(), "res.StringValue", NULL);
The syntax above is used to create a managed binding expression. For more information regarding managed binding expressions, please refer to the appropriate API reference topic, System.Bindings.Helper.TBindings.CreateManagedBinding. In this code snippet above, we used the second CreateManagedBinding overloaded method to create a managed binding expression.
The syntax is similar for the two binding expressions (that affect either IntegerValue or StringValue), so only the first binding expression syntax will be explained below.
The array of input scopes (RealObject, ScriptObject) is given as:
Delphi:
[TBindings.CreateAssociationScope([
Associate(MyObject1, 'o1'),
Associate(MyObject2, 'o2')
])]
C++:
OpenArray<_di_IScope>InputScopes
(TBindings::CreateAssociationScope
(OPENARRAY(TBindingAssociation, (Associate(MyObject1, "o1"),
Associate(MyObject2, "o2")))));
The binding expression for the input scope is a simple addition between the two Integer properties of the two objects.
Delphi:
'o1.IntegerValue + o2.IntegerValue'
C++:
"o1.IntegerValue + o2.IntegerValue"
Examining the BindingExpression1 syntax reveals that the array of output scopes and the binding expression for the output scope are similar to the one described above, but they affect the result object (MyResultObject).
For a binding expression to be evaluated and compiled, therefore used, you need to issue a notify command. When the value specified by a property of an object changes, you need to notify the binding engine about this. This is done as described in the following code snippet.
Delphi:
{ if the IntegerValue or StringValue for MyObject1 changes, use the following lines of code }
TBindings.Notify(MyObject1, 'IntegerValue');
TBindings.Notify(MyObject1, 'StringValue');
{ if the IntegerValue or StringValue for MyObject2 changes, use the following lines of code }
TBindings.Notify(MyObject2, 'IntegerValue');
TBindings.Notify(MyObject2, 'StringValue');
{ or any other combination of the two above, depending on which value changes }
C++:
// if the IntegerValue or StringValue for MyObject1 changes, use the following lines of code
TBindings::Notify(MyObject1, "IntegerValue");
TBindings::Notify(MyObject1, "StringValue");
// if the IntegerValue or StringValue for MyObject2 changes, use the following lines of code
TBindings::Notify(MyObject2, "IntegerValue");
TBindings::Notify(MyObject2, "StringValue");
// or any other combination of the two above, depending on which value changes