Search code examples
firemonkeytobjectlist

TObjectList finding an Item


I'm constructing a TObjectList which will store objects of class tButton:

...    
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
  public
    function FindButton (const aButtonName: string; var aButton: tButton) : Boolean;
  end;
...    

var ButtonObjectList : TObjectList<TButton>;

function TForm1.FindButton (const aButtonName: string; var aButton: tButton) : Boolean;
...
var b : Integer;
begin
Result := False;
for b := Low (ButtonObjectList.Count) to High (ButtonObjectList.Count) do

    if ButtonObjectList.Items [b].Name = aButtonName then begin
       Result  := True;
       aButton := ButtonObjectList.Items [b];
    end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
ButtonObjectList := TObjectList<TButton>.Create(True);
ButtonObjectList.Add(Button1);
ButtonObjectList.Add(Button2);
ButtonObjectList.Add(Button3);
end;

further, in unit untRetrieveButton:

...
var Button : TButton;
procedure FindAButton;
begin
if Form1.FindButton ('Button 1', Button) then
   ShowMessage ('Button found')
else
   ShowMessage ('Button not found')
end;

I want to get back an arbitrary button stored in the ButtonObjectList, but at this point, I only know the button's name. From what I've learn at the TObjectList documentation, the only way to achieve this, is traversing the entire Items list, and compare the parameter aButtonName with the Button's name in the TObjectList, as in

function TForm1.FindButton (const aButtonName: string; var aButton: tButton) : Boolean;

Is this right, or there is a better and most efficient way to retrieve an arbitrary Button by it's name?


Solution

  • I think, if you have only limited amount of buttons it doesn't matter and the speed should be ok.

    If I have such cases I often use a solution like this:

    var
      ButtonDict: TDictionary<String,TButton>;
      FoundButton: TButton;
    begin
    
      ...
    
      ButtonDict.Add(UpperCase(Button1.Name),Button1);
      ButtonDict.Add(UpperCase(Button2.Name),Button2);
      ButtonDict.Add(UpperCase(Button3.Name),Button3);
    
      ... 
    
      //fast access...
      if ButtonDict.TryGetValue(UpperCase(NameOfButton),FoundButton) then
      begin
        //... now you got the button... 
      end else
      begin
        // Button not found...
      end;
    
      ...
    
    end;