Search code examples
delphidelphi-10.1-berlinlivebindingscustom-formatting

Delphi LiveBindings TPrototypeBindSource and customFormat


I use business classes with a TPrototypeBindSource. I will use CustomFormat to concatenate 2 fields. I am coming with a TBindSourceDB but not with the TPrototypBindSource.

I use an TEdit and a TLinkControlToField.

If I use : %s + " text" => it's work fine. When I use it with a TBindSourceDB, that works fine

%s + " - " + Self.Owner.FieldByName('Enseigne').text

But I don't understand how to access of data when I work with TPrototypeBindSource.

enter image description here

enter image description here

Could you give me the syntax for concatenate 2 fields with business classes bind ?


Solution

  • I thought I'd have another go at an answer as you didn't seem to have much enthusiasm for my first one.

    Before addressing your q, let's try a little experiment. In a project that has a DataSet with persistent fields FieldA and FieldB, say, set up a BindSourceDB and BindingList and add two TLinkControlToFields to link these fields to two TEdits, edFieldA and edFieldB.

    Test that it works as expected, then add another TEdit, edOther, and another TLinkControlToField, LinkControlToField3. Set its control to edOther, DataSource to the BindSourceDB and its FieldName to FieldA. Set its CustomFormat to

    Name
    

    Compile and run, and you should find that edOther displays the name of FieldA's Field component, DataSetFieldA or similar. What's going on, obviously, is that LiveBinding's expression evaluator is using the TField component of FieldA as the "scope" it uses to identify which Name property is being referred to.

    Now, replace Name by Owner.Name

    and at run-time edOther should display Form1 or similar, because persistent fields are owned by their containing form or datamodule. So, referring to Owner.Name broadens the scope within which identifiers in the Format expression can be resolved and their values extracted.

    So, using a BindSourceDB as the link's datasource, you can set the CustomFormat to something quite complex, e.g.

    LowerCase(Owner.DataSet.IndexFieldNames) + ' ' + Owner.DataSet.FieldByName('ID').Text
    

    Unfortunately, this does not work with the default set-up of a PrototypeBindSource.

    Continuing our experiment, set up a project using a PrototypeBindSource with two fields FieldA and FieldB and three TEdits, as before. Notice that this time, if you try to set the CustomFormat of LinkControlToField3 to Name you will get an error message 'Could not find Name', I think because the LB machinery is unable to resolve the reference to Name because of the abstracted implementation of fields in TPropotypeBindSource.

    However, all is not lost. Remove LinkControlToField3 and instead, add to the Form's BindingList a BindExpression.

    Set the BindExpression's ControlComponent to edOther, its ControlExpression to Text and its SourceComponent to Form1.

    With that done, in the SourceExpression, we can refer to properties of Form1 and its components, with an expression like this one

    edFieldA.Text + ':' + edFieldB.Text
    

    which works fine for me.

    One thing that I haven't managed to find out yet is which the SourceExpression can't include things like LowerCase. However that's easily worked around, by adding a MyLowerCase function to Form1 and LB is quite happy with that.

    So, I think that answers your q of how to concatenate the contents to two controls (or fields). Personally, I would still prefer to use a concatenated property of the business object, but ymmv.