Search code examples
delphifiremonkeytlistbox

Firemonkey TListBox.OnClick - which item is clicked?


Delphi 10.2.2 mobile

Starting with a blank mobile project, I drop a TListBox on the form. I add two TListBoxItems.

procedure TForm1.ListBox1Click(Sender: TObject);
begin
  ShowMessage('ListBoxItem.itemindex = ' + ListBox1.ItemIndex.ToString);
end;

When I click on the first item in Windows and Macintosh, the OnClick() correctly reports that item index 0 has been clicked.

When I click on the first item in mobile (iOS and Android) the OnClick() reports the item index as -1 (not 0 as it should). Then it goes on to highlight the first item.

If I then click on the second item in mobile, the OnClick() reports the item index as 0 (not 1 as it should). Then it goes on to highlight the second item.

How can I get the correct item in OnClick() when clicking in a TListBox on mobile?


Solution

  • Clearly the OnClick event is being triggered before the ItemIndex is updated. So you will have to delay processing until after the ItemIndex has a chance to be updated first. You can:

    • use TThread.ForceQueue() (10.2 Tokyo+ only):

      procedure TForm1.ListBox1Click(Sender: TObject);
      begin
        TThread.ForceQueue(nil,
          procedure
          begin
            ShowMessage('ListBoxItem.itemindex = ' + ListBox1.ItemIndex.ToString);
          end
        );
      end;
      
    • use TThread.Queue():

      procedure TForm1.ListBox1Click(Sender: TObject);
      begin
        TThread.CreateAnonymousThread(
          procedure
          begin
            TThread.Queue(nil,
              procedure
              begin
                ShowMessage('ListBoxItem.itemindex = ' + ListBox1.ItemIndex.ToString);
              end
            );
          end
        ).Start;
      end;
      
    • use a short timer:

      procedure TForm1.ListBox1Click(Sender: TObject);
      begin
        Timer1.Enabled := True;
      end;
      
      procedure TForm1.Timer1Timer(Sender: TObject);
      begin
        Timer1.Enabled := False;
        ShowMessage('ListBoxItem.itemindex = ' + ListBox1.ItemIndex.ToString);
      end;