Providing Direction to LiveBindings

In my last couple of posts I have focused on one-way livebindings - updating a ‘control’ object when a ’source’ object changes - but what about bidirectional livebindings I hear you ask…

In this example, I am going to use a couple of TBindExpressions to demonstrate how a bidrectional livebinding works.  To kick things off, create a new FireMonkey HD Application and add the following controls to it:

TEdit: Name := edtObjectName
TEdit: Name := edtDamoObjStatus
TBindingsList: Name := blDirectionDemo
TBindScope: Name := bsDamoObj

My UI looks a little like this:

The goal of my example is to have a ‘Business Object’ (TDamo) be the source of my data.  I want to be able to populate a TEdit (edtObjectName) and I also want to give edtObjectName the ability to write back to my instance of TDamo.  I am using the second TEdit (edtDamoObjStatus) as proof that the liveBinding is indeed working.

All of the controls that I have set above are all familiar except for the TBindScope (bsDamoObj).  This component is useful as the object that I associate to it (via it’s Component property) and its children become available to be either source or control objects.  For example, I could refractor our last project that usedTBindExprItems  by adding a TBindScope to the form and setting its Component property to Form1.  I could then update my control expressions from Owner.<Object>.<Property> to <Object>.<Property> and make them a little more readable.

The next thing to do is to create a new unit to hold our TDamo class.  Create a New Unit (File | New | Other | Delphi Files | Unit), add the following declaration and implementation and save this as UDamoObject.pas:

interface

type TDamo = class
  private
    sName : String;
  public
    property Name : String read sName write sName;
    constructor Create(Name : String);
end;

implementation
{ TDamo }
constructor TDamo.Create(Name: String);
begin
  sName := Name;
end;
end.

Nice and simple.  Now, let’s create an OnCreate event for Form1 and in that event, create an instance of TDamo and assign it to the DataObject property of bsDamoObj (I have declared DamoObj as a global variable).

In this example, because TDamo doesn’t descend from TComponent, we don’t set the Component property of bsDamoObj, instead we will set the DataObject property on bsDamoObj.

procedure TForm1.FormCreate(Sender: TObject);
begin
  DamoObj := TDamo.Create('DamoObject');
  bsDamoObj.DataObject := DamoObj;
end;

Flip back to the Form Designer and we will add our TBindExpressions.  Double click on blDirectionDemo to open the LiveBinding Editor, click the New button, and choose TBindExpression.  Select your TBindExpression and set the following properties:

Name := bxDamoObjName
ControlComponent := edtObjectName
ControlExpression := Text
Direction := dirBidirectional
NotifyOutputs := True
SourceComponent := bsDamoObj
SourceExpression := Name

The first thing to note here is the Direction property.  This is where we can set the behaviour of the expression.  There are three options:

dirSourceToControl: The standard, one-way flow of data from source to the control object

dirControlToSource: One-way flow from the control back to a source object

dirBidirectional: The source and control objects can pass data back and forth between one another

If someone has a good reason to use dirControlToSource, please let me know!

The NotifyOutputs property is the second thing to notice.  If we have another expression where the source object of that expression is the same as the current expression and we want that other expression to fire then NotifyOutputs needs to be enabled.  In our example, we will create another expression that will display the name of our TDamo object in edtDamoObjStatus to prove that the bidirectional expression works but this expression won’t fire if NotifyOutputs on our first expression is false - to clarify, the source object, DamoObject will be updated, but the actual expression that displays the name in edtDamoObjStatus won’t fire automatically.

Third and finally, you will see that our SourceComponent is set to bsDamoObj.  This is the TBindScope which is associated to our TDamo object.  Because of this, I can simply set SourceExpression to Name (the property of our TDamo object).

In the LiveBinding Editor, click New again to create our second TBindExpression.  This is the expression that will be a typical Source-To-Control TBindExpression and its properties are set as follows:

Name := bxDamoObjStatus
ControlComponent := edtDamoObjStatus
ControlExpression := Text
SourceComponent := bsDamoObj
SourceExpression := Name

Close the LiveBinding Editor so that we are back to the Form Designer.  All that is left now is to notify the application when a change is made to our TDamo object.  This will happen when we execute an OnChange event in edtDamoObjName.  Create an OnChange event for edtDamoObjName and add the following line of code to it:

blDirectionDemo.Notify(Sender, 'Text');

Run the application and you should see both TEdit controls displaying the same name.  Make a change to the top TEdit and you should see the second TEdit reflect that change.  I also encourage you to play around with the NotifyOutput property and see how that affects your other LiveBindings.

Out. Damo.

2 Responses to “Providing Direction to LiveBindings”

  1. Vsevolod Leonov Says:

    Hi Damo, great posts! We all do need this simple, but descriptive texts, especially for LiveBindings!

    >>If someone has a good reason to use dirControlToSource, please let me know!

    Look, let’s just for a minute leave simple examples and think of some massive business models. In this case we can live in two worlds: world of GUI and world of business. Some processes can be isolated from each other.

    For example, you’re planning a massive change of business objects, some kind of transactional operations on a set, when relationships of objects are complicated. Sometimes, these changes can be also iterative. In this case you need to disable all the "bindings" until the changes are implemented. And vice versa: you can change many times the properties as they are exposed on GUI (like with your Edit components), and only after you’re pressing "Apply" button to propagate changes to the business model.

    So at the very beginning we’re splitting the system into "two worlds", but don’t know the future interaction pattern (and ways). May be, we can change the "bindings", you have two, switching them in turn. Anyhow, let’s ask you to move to more enhanced example :) and test the capabilities of LiveBidings.

Leave a Reply


Bad Behavior has blocked 0 access attempts in the last 7 days.

Close