How can I use an action to determine a control's visibility?
delphi
Solution
Your diagnosis is correct. Actions have worked that way since they were first introduced to Delphi.
I expect it's by design (an optimization to avoid excessive updating of the text and other visual aspects of invisible controls, probably), but that doesn't mean the design is good.
Any workaround I can imagine will involve your checkbox code directly manipulating the affected actions, which isn't very elegant since it shouldn't have to be aware of everything else it might affect — that's what the `OnUpdate` event is supposed to do for you. When the checkbox gets checked, call `Action1.Update`, or if that doesn't work, then `Action1.Visible := True`.
You could also put your action-updating code in the `TActionList.OnUpdate` event instead.
Problem
I'm trying to use an action to control the visibility of a control. My code looks like this: Pascal file ``` unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ActnList, StdCtrls; type TForm1 = class(TForm) Button1: TButton; ActionList1: TActionList; Action1: TAction; CheckBox1: TCheckBox; procedure Action1Update(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Action1Update(Sender: TObject); begin (Sender as TAction).Visible := CheckBox1.Checked; end; end. ``` Form file ``` object Form1: TForm1 object Button1: TButton Left = 8 Top = 31 Action = Action1 end object CheckBox1: TCheckBox Left = 8 Top = 8 Caption = 'CheckBox1' Checked = True State = cbChecked end object ActionList1: TActionList Left = 128 Top = 8 object Action1: TAction Caption = 'Action1' OnUpdate = Action1Update end end end ``` When the form first runs the button is visible and the check box is checked. Then I un-check the check box and the button disappears. When I re-check the check box the button fails to re-appear. I think the reason for this can be found inside the following local function in `TCustomForm.UpdateActions`: ``` procedure TraverseClients(Container: TWinControl); var I: Integer; Control: TControl; begin if Container.Showing and not (csDesigning in Container.ComponentState) then for I := 0 to Container.ControlCount - 1 do begin Control := Container.Controls[I]; if (csActionClient in Control.ControlStyle) and Control.Visible then Control.InitiateAction; if (Control is TWinControl) and (TWinControl(Control).ControlCount > 0) then TraverseClients(TWinControl(Control)); end; end; ``` The check of `Control.Visible` appears to block my action ever getting a chance to update itself again. Have I diagnosed the issue correctly? Is this by design or should I submit a QC report? Does anyone know of a workaround?