RAD Studio XE3 brought significant enhancements to LiveBindings. The LiveBindings Designer is the most obvious of these, but there have also been a lot of additions made in the process of enabling the designer, some of which I’m going to explore over the next few posts.
First up are BindSources. If you did any work with LiveBindings in XE2, you would have used BindScopes. BindScopes were the way that you exposed different sources of data to the binding engine. TBindScopeDB, for example, let you connect to a TDataSource, and then bind the exposed fields to controls using LiveBindings.
Well, BindScopes are still there, so your XE2 code will still work. BindSources, however, try to solve the same problem in a way that is simpler, designer-friendly, but still flexible.
There are a few different BindSources available out of the box, all ultimately descending from TBaseLinkingBindSource. We’ll look at all of them eventually but for now let’s focus on TBindSourceDB.
As an aside, TBaseLinkingBindSource descends from TBaseBindScopeComponent, which as the name might suggest, is an ancestor of the BindScope components mentioned earlier. So there is a family connection.
Let’s start with building a simple example. Fire up Delphi XE3 or C++Builder XE3 and create a new FireMonkey HD Application (LiveBindings works with VCL too, however I have to pick one for the example so I’m picking FireMonkey). Bring up the LiveBindings Designer by going to View | LiveBindings Designer menu, and if desired, dock the designer window somewhere convenient.
Next, drop a TClientDataset onto the form and set its Filename property to the fishfacts.cds file that ships in the RAD Studio samples (by default installed in C:\Users\Public\Documents\RAD Studio\10.0\Samples\LiveBindings\common) and then set its Active property to True. In the LiveBindings Designer you should see this:
Next, drop a TEdit onto the form, and in the LiveBindings Designer drag a line from the Category field in the ClientDataSet1 to the Text property of Edit1. This does a few things:
- It adds a BindingsList to our form, which just like in XE2, is the repository for all our bindings and expressions.
- Within that BindingsList it adds a TLinkControlToField binding with appropriate expressions to make a bi-directional connection between the Category field in our Dataset and the Text property of the Edit.
- It also adds a TBindSourceDB component to the form, which has a built in TDataSource property connected to our ClientDataset.
Looking in the LiveBindings Designer, you may not notice it at first, but the ClientDataSet is now nested within the BindSourceDB.
Now lets add some more controls. Drop down a TGrid, a TMemo and a TImageControl and wire them up in the LiveBindings Designer as below:
By the way, there is also another way to add controls and bindings. So far we’ve been adding the control, the wiring it up in the designer. You can go the other way as well. Right-click on one of the fields in the LiveBindings Designer and select “Link to new control…”. This will bring up a list of supported controls to choose from and will then add them to the form and wire up the binding.
It’s worth spending some time to look at the bindings that have been created for you in the BindingsList (double-click on the BindingsList1 component on your form designer) to get a feel for the different types of bindings and how they relate to the types of fields and controls you were binding between.
Right click on the BindSourceDB in the form designer, select Add Navigator and then run your app. You should now be able to step through your dataset and see the values changing in the various controls.
To go back to the BindingsList for a second, it’s worth noting that all the binding types from XE2 are still present. Not only is this important for backwards compatibility, there are still situations where you want to use those binding types rather than the QuickBindings created by the LiveBinding Designer. For example, say I want to bind to use an Expression to format the output before displaying it. Then double-click on the BindingsList, add a TBindExpression, set the SourceComponent and SourceExpression properties, and the equivalent ControlComponent and ControlExpression properties and you’re away.
One important thing to remember is that even though we’re binding to the dataset in a new way, under the covers the dataset is still behaving as you’d expect. As an example, drop another label and a button down on the form. In the button’s OnClick event, write the following code:
Label2.Text := ClientDataSet1.FieldByName('Category').AsString;
Basically I’m bypassing the whole LiveBindings engine and putting the value of the Category field from the ClientDataset into the label directly. Run the app and and edit the value in the Category field in the grid, however don’t click away to the next record. Instead, click on the button. You should see the label value update to your newly edited value, so LiveBindings has pushed our changes back to the dataset field. However as we’d expect, the dataset’s state is still dsEdit as we have not done a Post, either implicitly by clicking to the next record in the grid, or explicitly by clicking the Post button in the navigator or by calling ClientDataSet1.Post. Try clicking the Cancel button in the navigator. The values in the grid (and any other fields bound using LiveBingings) will change back to the value they had prior to editing, and clicking the button to update the label directly from the dataset field will show it has also returned.
My point is the rules haven’t all changed under your feet, this is still built on the DataSets you know, it just provides a much more flexible option to bind the values to your UI.
TBindSourceDBX works basically the same way as TBindSourceDB, however is DBExpress specific. As part of that, it not only has a nested DataSource, but also nested SQLConnection, SQLDataSet, DatasetProvider, and ClientDataSet, so you can avoid the conga-line of components you normally end up with when using DBExpress.
In my view this is finally delivering on the promise of LiveBindings. The power of the LiveBindings engine is still there and still accessible to you, but in a much more approachable fashion.
So that’s a high-level introduction to BindSources as the relate to DataSets, but there’s a bunch more you can do with them. To uncover some of that, in the next post we’ll look at TAdapterBindSource. I have also skipped over how these controls are notifying the LiveBinding Engine of changes, so I’ll come back to that in a later post as well.