Home/Code tips, Uncategorized/Updating listview item attributes on the fly when using LiveBindings

Updating listview item attributes on the fly when using LiveBindings

Views:
350

This entry is specifically related to my mobile news client, iNews, which can compile for iOS and Android, however it could be applied to any platform that FireMonkey supports, e.g. Windows and OSX.

When creating a mechanism for subscribing to groups available on a news server, I needed to figure out a way of the user being able to check or uncheck groups that they wanted to subscribe/unsubscribe to. Enter the EditMode property of TListView. When EditMode is set to True, a “checkbox” becomes visible in front of each item.

Because EditMode is being set to True after the items have been loaded, I figured I’d need to iterate the items and set the Checked property of each item depending on whether a flag was set in the database for that group. I thought no problem, I’ll just set ItemIndex to the loop variable  and the dataset will be pointing to the corresponding record, right? Wrong; that only happens if a user actually clicks the item; probably a good thing. So I looked for a way of “faking” the item being clicked, without success. Then I looked for what the code does when a user actually clicks the item. Eureka! TLinkObservers.SelectionChanged causes the dataset to point to the correct record. Sadly, it became clear that doing this when iterating over all items is a performance killer, especially on the device.

Fortunately with the help of Jim Tierney, I discovered I was looking at this from the wrong way. With LiveBindings, you can create a link between the dataset and the Synch binding of the TListView. This causes the TListView to be populated with the records in the dataset, and synch the record pointer with the item in the TListView without having to write any code. When the item is being populated, LiveBindings calls the OnFilledListItem event on the link (which is a TLinkListToControlField link). There, I could check the flag and set the corresponding item’s Checked property, since the record pointer is at the record in question:

procedure TfrmMain.LinkListControlToField2FilledListItem(Sender: TObject; const AEditor: IBindListEditorItem);
var
  LItem: TListViewItem;
begin
  if not FGroupSubscribeUpdate and FSubscribeMode and (AEditor.CurrentIndex >= 0) then
  begin
    LItem := lvGroups.Items
[AEditor.CurrentIndex]; LItem.Checked := dmNews.qryGroupsSubscribed.Value = 1; end; end;

I also needed to find a way to update the database when the user actually checked/unchecked the item. The answer is to use the OnButtonChange event:

procedure TfrmMain.lvGroupsButtonChange(const Sender: TObject; const AItem: TListViewItem; const AObject: TListItemSimpleControl);
var
  Button: TListItemGlyphButton;
begin
  if FSubscribeMode and (AObject is TListItemGlyphButton) then
  begin
    Button := TListItemGlyphButton(AObject);
    if Ord(Button.Checked) <> dmNews.qryGroupsSubscribed.AsInteger then
    begin
      FGroupSubscribeUpdate := True;
      try
        dmNews.qryGroups.Edit;
        dmNews.qryGroupsSubscribed.AsInteger := Ord(Button.Checked);
        dmNews.qryGroups.Post;
      finally
        FGroupSubscribeUpdate := False;
      end;
    end;
  end;
end;

You’ll note that I’m using a flag called FGroupSubscribeUpdate. This is because when posting the record, LiveBindings calls the OnFilledListItem event, and in this case I don’t want the Checked property being reset. I also use a similar technique for assigning a bitmap to items in the message list, to indicate that there are attachments with it:

procedure TfrmMain.LinkListControlToField3FilledListItem(Sender: TObject; const AEditor: IBindListEditorItem);
var
  LItem: TListViewItem;
begin
  if AEditor.CurrentIndex >= 0 then
  begin
    LItem := lvMessages.Items[AEditor.CurrentIndex];
    if dmNews.MessageHasAttachments then
      LItem.Objects.ImageObject.Bitmap.Assign(imgAttach.Bitmap);
  end;
end;

I hope the information above will be useful for anyone interested; it took me some time to work out what to do, however I felt I should share it.

 

By | 2017-02-16T18:02:36+00:00 September 26, 2013 9:06 am|Code tips, Uncategorized|3 Comments

Share This Story, Choose Your Platform!

About the Author:

3 Comments

  1. Cierra May 18, 2014 at 7:12 pm - Reply

    Hi there just wanted too give youu a quick hads up aand let you know a few of the images aren’t loadig correctly.
    I’m not suure why but I thinbk itts a linking issue. I’ve tried it iin ttwo different browsers and both show the same
    outcome.

    • admin June 4, 2014 at 7:56 am - Reply

      Which images, on which pages?

  2. Irwan June 24, 2015 at 1:34 pm - Reply

    hello sir,
    if possible i add two image to left and right in listview item?
    need your help

Leave a Reply

Show Buttons
Hide Buttons