Search code examples
delphifiremonkeytcombobox

Delphi FMX Unable to change the drop down text of a TCombobox TListItem at runtime


I am using Delphi 11 Alexandria and am building an FMX project for release on Windows, iOS, and Android.

I am building a manual language translation system, to this end I have generated a mapping document that maps language text to components mapped using the component name.

My customer has insisted that no auto translation technology should be used.

My code works fine for everything accept TComboBox and TListItem?

When I set the text value for the TListItem on startup, it works. For instance, the design time values are in English, and if the save state determines the last used language was Deutschland then this function successfully changes the drop down text and header text of the TComboBox (very odd).

However, when I change the language after startup to change all the text, it does not change the drop down text, but does change the header text value.

I.e. I initially load the text in English, the save state loads in English, and then I change to Deutschland.

When I change to Deutschland, the header text in the ComboBox says "Bereich" but the drop down value says "Area". This is true for all of the drop down values, only the header text changes and not the drop down values?

Please note: I have added the if statement already if cmp is TListBoxItem then for an easy place to position any additional code to make it work.

procedure setLangTextVal(cmp: TComponent; text: string);
var
  Ctx: TRttiContext;
  Prop: TRttiProperty;
begin
  Prop := Ctx.GetType(cmp.ClassType).GetProperty('Text');
  if (Prop <> nil) and (Prop.Visibility in [mvPublic, mvPublished]) then
  begin
    if cmp is TListBoxItem then
      Prop.SetValue(cmp, text)
    else
      Prop.SetValue(cmp, text);
    Exit;
  end;

  Prop := Ctx.GetType(cmp.ClassType).GetProperty('Caption');
  if (Prop <> nil) and (Prop.Visibility in [mvPublic, mvPublished]) then
  begin
    Prop.SetValue(cmp, text);
    Exit;
  end;
end;

Solution

  • This is indeed a bug not in TListBoxItem but in TComboBox component. It has an optimization that prevents the list of items from being recreated every time the drop down is shown, except when an item is added or removed or the whole list is replaced through the Items property. Seems that simply changing the text of items doesn't trigger such drop down recreation.

    A workaround is to disable this optimization by copying the source file FMX.ListBox.pas to your project folder and commenting out the FItemsChanged check at the TCustomComboBox.InitPicker procedure:

    // if FItemsChanged then          <-- disable this check
    // begin
      AListPicker.Values := Items;
      FItemsChanged := False;
    // end;
    

    Note this is based on Delphi 11.0 source files. Workaround may be different for previous/future versions of Delphi.