Generally
Yes, an OnUpdate
event handler takes time, just as any other routine does. Multiple handlers take a multiple of that time. The gross of all that code will evaluate conditions resulting in just nothing to do. In that sense, you could conclude that this update mechanism degrades performance. Especially considering these update events occur quite often:
Occurs when the application is idle or when the action list updates.
That could be a reason to spare its use. But you should realize that the evaluation of a single expression mostly does not take that much time. Also, realize that regardless of action updates, your application performs (much more heavy) calculations and operations on every single mouse move.
When you keep the code duration in action update events to a minimal, e.g. no password checking via a database connection, then performance will appear just normal. If you háve lengthy operations linked to updating actions, then fall back on manual updates in those specific situations.
Note that performance can be slightly gained by not using the individual OnUpdate
events of the Actions, but the OnUpdate
event of the ActionList instead which has a Handled
parameter to cancel further processing, with the additional benefit of centralization and categorization.
Specifically
Your ListView1.SelCount
sends a WinAPI message to the control to retrieve the selection count. That is a tiny operation and I would not bother its time needed.
An alternative is to update the action in the ListView's OnSelectItem
event. That event will catch all selection changes due to mouse and keyboard interaction, as well as setting the individual items'
Selected
property:
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
actTest.Enabled := ListView1.SelCount > 0;
end;
However, the ListView nor the VCL do not provide anything to signal only between SelCount = 0
and SelCount > 0
, so you will evaluate that line of code more then strictly necessary anyway.
Assuming MultiSelect
is true, you could also count the selection changes yourself to eliminate the need for calling SelCount
:
private
FListViewSelected: Longbool;
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
if Selected then
Inc(FListViewSelected)
else
Dec(FListViewSelected);
actTest.Enabled := FListViewSelected;
end;
Or test for the selected item being nil:
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
actTest.Enabled := ListView1.Selected <> nil;
end;
But then again, there really is no reason left for not using the OnUpdate
event:
procedure TForm1.ActionList1Update(Action: TBasicAction; var Handled: Boolean);
begin
actTest.Enabled := ListView1.Selected <> nil;
Handled := True;
end;
TAction.OnUpdate
intention is to do what you are doing, see docwiki.embarcadero.com/CodeExamples/XE7/en/… – IntumesceOnUpdate
way may lead to doing it unsafely late. I'm trying to completely avoidOnUpdate
personally. – AppalOnSelectItem
event should be fired only when the selection state of an item changes and it is so the ideal trigger for this update (whether you update a model, or the action itself when having no view model concept). That's better than wasteful sending ofLVM_GETSELECTEDCOUNT
messages to get the selected item count whenever the application goes idle (and nothing in the selection actually changes). – AppalOnUpdate
, occurs when the application is idle..., that's where the wasting origins. – AppalTApplication.OnMessage
event to verify that. – AgeoldApplication.ActionUpDateDelay
to higher value so that the event fires less often. – Odiliaodille