5
votes

I'm using FMX on Delphi 10.1 Berlin.

I read this (which is the behavior I want):

https://stackoverflow.com/a/42933567/1343976

Changing ItemIndex programmatically does not result in the OnChange event being fired. It fires only in response to user interaction.

Is this true only for VCL?

I'm asking for this because, unfortunately for me, from what I can test, modifying the ItemIndex property in code triggers the OnChange event.

If this is true, how can I achieve the same behaviour as VCL in FireMonkey?

2
Set the OnChange to nil before changing the ItemIndex and restore the OnChange handler afterwards.LU RD
@LURD That is on my opinion the worse approach you could use. Why? Before setting OnChange to nil you would need to store its current value in order to be able to restore it later which means you need to introduce another variable into your code.SilverWarior
Rather than reset the event itself, you could set a variable that the event looks at and exits immediately if the variable is set. But that is still introducing a variable. Which is not the end of the world...Remy Lebeau
@LURD: This would have been better: procedure SetItemIndex(ix : Integer; cb: TComboBox); var original: TNotifyEvent; begin original := cb.OnChange; cb.OnChange := nil; try cb.ItemIndex := ix; finally cb.OnChange := original; end; end;Remy Lebeau
@kobik, done. Thanks.LU RD

2 Answers

2
votes

Is this true only for VCL?

Many things are handled in a different way in FMX.

If this is true, how can I achieve the same behaviour as VCL in FireMonkey?

A simple workaround is to nil the OnChange event property before changing the ItemIndex, and afterwards restore event.

A simple routine to do this would be someting like this (as outlined by @Remy):

procedure SetItemIndex(ix : Integer; cb: TComboBox);
var
  original : TNotifyEvent;
begin
  original := cb.OnChange;
  cb.OnChange := nil;
  try
    cb.ItemIndex := ix;
  finally
    cb.OnChange := original;
  end;
end;  
0
votes

The proper way of dealing with this problem is to first find out where the OnChange handler is being called from. This is being done in the TCustomComboBox.DoChange() method.

So, what you need to do is either:

  1. override the default DoChange() method to not fire the OnChange event method.

  2. override the ItemIndex property setter to use different logic which won't call the DoChange() method.

Both of these approaches require you to create a new class for your modified ComboBox.