Jump to content
Primož Gabrijelčič

Generating one-to-many on the fly with Live Bindings

Recommended Posts

I'm playing with Live Bindings and looking at how far I can push it 🙂 ...

 

I wanted to see if I can take a single-item source (edit box) and bind it to a list-type control (list box), somehow splitting the data in the process. This is what I ended at:

 

1. Bind expression that binds Edit1, Text to ListBox1, Items.DelimitedText.

 

2. OnAssigningValue event for that bind expression:

 

procedure TForm85.BindExpression1AssigningValue(Sender: TObject; AssignValueRec:
  TBindingAssignValueRec; var Value: TValue; var Handled: Boolean);
begin
  Value := StringReplace(Value.AsString, ', ', ',', [rfReplaceAll]);
end;

 

(This allows me to type in "1, 2, 3" or "1,2,3" and both split into "1", "2", and "3".)

 

3. Edit1.OnChangeTracking which updates the expression:

 

procedure TForm85.Edit1ChangeTracking(Sender: TObject);
begin
  BindingsList1.Notify(Sender, 'Text');
end;
 

4. Some initialization for DelimitedText to work correctly:

 

  ListBox1.Items.Delimiter := ',';
  ListBox1.Items.StrictDelimiter := true;

 

Demo project is attached.

 

Does anyone see a better solution for that? (Better = requires writing less code.)

 

(No need to tell me that my problem is stupid and that I should redesign my app so that I don't have to do any splitting of data. I know that. This is an exercise.)

liveb.zip

Share this post


Link to post

Hi,

 

Not to impose on your excercise 🙂 But Livebindigs are not usefull in "real" application on Android/iOs. I was forced, due to bad performance, to drop all bindigs and manually code everything.  

 

br,

Marjan 

Share this post


Link to post

I use LiveBindings all the time in mobile apps so not sure what mausmb is going on about.

 

Anyway, yeah, I don't see a way to make your code any less than it is. It's only 4 lines of code.

 

Trying to think if putting it into a TFDMemTable first helps at all and I don't see that it does.

 

In Edit1ChangeTracking with a for loop and TFDMemTable.AppendRecord you might be able to pack it into 3-4 lines. Might give you better flexibility with the data later.

Share this post


Link to post

@Eli M. The discussion concerning usability of LiveBindings in production on G+ was quite biased towards unusable. What is your typical data volume i.e. how many tables/fields/rows are bound to how many controls?

  • Like 1

Share this post


Link to post
3 minutes ago, Sherlock said:

@Eli M. The discussion concerning usability of LiveBindings in production on G+ was quite biased towards unusable. What is your typical data volume i.e. how many tables/fields/rows are bound to how many controls?

Maybe the problem is not specifically LiveBindings but trying to do too much on a single mobile screen at the same time.

 

This project uses a number of different livebinded fields:

https://community.embarcadero.com/article/16633-deep-dive-field-service-app-template-for-android-and-ios-with-rad-studio-10-2-tokyo

  • Like 2

Share this post


Link to post
On 2/6/2019 at 4:12 PM, Eli M. said:

Maybe the problem is not specifically LiveBindings but trying to do too much on a single mobile screen at the same time.

 

This project uses a number of different livebinded fields:

https://community.embarcadero.com/article/16633-deep-dive-field-service-app-template-for-android-and-ios-with-rad-studio-10-2-tokyo

Not going into "demo VS production" app area...Let's say (for the sake of the argument) that statement "but trying to do too much on a single mobile screen at the same time" is true .
With Livebindings performance is poor. Without Livebindigs performance is good. So what's your argument again ? 🙂

 

br,

m

Share this post


Link to post
On 2/8/2019 at 4:02 AM, mausmb said:

Not going into "demo VS production" app area...Let's say (for the sake of the argument) that statement "but trying to do too much on a single mobile screen at the same time" is true .
With Livebindings performance is poor. Without Livebindigs performance is good. So what's your argument again ? 🙂

 

br,

m

It doesn't matter to me whether you use LiveBindings or not. I use it where appropriate and it saves me time. Obviously in your use case you claim it did not save you time.

 

Use the right tool for the job.

  • Like 1

Share this post


Link to post
On 1/12/2019 at 12:05 PM, Primož Gabrijelčič said:

Does anyone see a better solution for that? (Better = requires writing less code.)

 

Not that I think that this would be a significant improvement with respect to your approach, but you can avoid the OnAssigningValue event-handler by introducing this public function to your form:

 

function TForm1.SanitizeStr(const AString: string): string;
begin
  Result := AString.Replace(' ,', ',', [rfReplaceAll]).Replace(', ', ',', [rfReplaceAll]);
end;

 

Then use as SourceExpression of your TBindExpression this value: 'Owner.SanitizeStr(Text)'.

AFAIK "Owner" here stands for the owner of the BindingList and the LB expression engine is capable of calling a method on the underlying object (your form instance).

 

Same lines of pascal code but one line left out from the XFM file (the one defining the event handler for OnAssigningValue event) and you can declare your function at your will (no prototype to match for the event handler).

Does this match your definition of Better = writing less code? :-)

 

Sincerely

 

  • Like 1

Share this post


Link to post

Another (small) addition (on the same path):

 

1) change SanitizeStr to this:

 

function TForm1.SanitizeStr(const AString: string; const ADelimiter: string): string;
begin
  Result := AString
    .Replace(' ' + ADelimiter, ADelimiter, [rfReplaceAll])
    .Replace(ADelimiter + ' ', ADelimiter, [rfReplaceAll]);
end;

2) change the SourceExpression to 'Owner.SanitizeStr(Text, Owner.ListBox1.Items.Delimiter)'

 

And you can avoid setting the Items.Delimiter for your listbox.

"It's a small step for man but..." :-)

  • Like 1

Share this post


Link to post

Nice additions, Andrea 🙂

 

Whether for the good or bad, who can tell 😉 

 

My initial approach was trying to get too much from LiveBindings anyway (intentionally). Your changes are definitely in direction of making my messy code more maintainable so they make it better. They, however, introduce more code, so from my original viewpoint they make it worse. 😉 

  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×