Try it with a direct read AND write property:
property OnRolledChange: TNotifyEvent read fOnRolledChange write fOnRolledChange;
Well, you might be right. I did it and it works. OnRolledChange is loaded from file in IDE.
So I've tried another thing and I left SetOnRolledChange procedure, but I have commented first if:
procedure TRollButton.SetOnRolledChange(AValue: TNotifyEvent);
begin
{ if fOnRolledChange = AValue then
Exit;}
fOnRolledChange := AValue;
end;
And it also works! So it looks like "if fOnRolledChange = AValue" returns true and "fOnRolledChange := AValue;" never happens. I don't know why. I even added to constructor "fOnRolledChange := nil", but it didn't help.
PS: fRolledControl is just a TComponent and it has nothing to do with fOnRolledChange.
It even works now when SetOnRolledChange is in private section, so I think it's not true that setter has to be in published section.