在Delphi XE7中,我使用这个技巧根据ListView中的项目是否被选择来自动启用或禁用工具栏按钮(“编辑ListView项目”),以防止用户在没有选择的情况下单击该按钮列表视图项目已选择:
actTest
。 actTest
分配给按钮。 在
OnUpdate
操作的 actTest
事件中写入:
procedure TForm1.actTestUpdate(Sender: TObject);
begin
actTest.Enabled := ListView1.SelCount > 0;
CodeSite.Send('actTestUpdate'); // gets fired very often!
end;
现在您可以看到,该按钮根据是否选择了 ListView 中的项目而启用或禁用,与您是否使用鼠标、键盘或以编程方式选择/取消选择项目无关。
但是,在 CodeSite Live Viewer 中,我可以看到
actTestUpdate
事件被连续且频繁地触发,因此语句 actTest.Enabled := ListView1.SelCount > 0;
经常被执行。所以我的问题是:这会降低性能吗?如果是的话,还有什么技巧可以达到上述目的吗?
另外,如果您有很多操作,我建议您尝试使用 TForm.UpdateActions 而不是为每个操作定义 TAction.OnUpdate。这将使代码更具可读性。
当应用程序空闲或操作列表更新时发生。这可能是不使用它的一个原因。但您应该意识到,单个表达式的计算通常不会花费那么多时间。另外,请意识到,无论操作更新如何,您的应用程序都会对每次鼠标移动执行(更繁重的)计算和操作。
当您将操作更新事件中的代码持续时间保持在最短水平时,例如没有通过数据库连接进行密码检查,那么性能将显得正常。如果您有与更新操作相关的冗长操作,请在这些特定情况下依靠手动更新。
请注意,不使用 Actions 的各个
OnUpdate
事件,而是使用 ActionList 的
OnUpdate
事件,可以稍微提高性能,该事件有一个 Handled
参数来取消进一步的处理,还有以下额外好处:集中和分类。具体
ListView1.SelCount
向控件发送一条 WinAPI 消息以检索选择计数。这是一个很小的操作,我不会打扰它所需的时间。另一种方法是更新 ListView 的 事件中的操作。该事件将捕获由于鼠标和键盘交互而导致的所有选择更改,以及设置各个项目的
Selected
属性:
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
actTest.Enabled := ListView1.SelCount > 0;
end;
但是,ListView 和 VCL 不提供任何仅在 SelCount = 0
和
SelCount > 0
之间发出信号的信号,因此无论如何,您都会比严格必要的情况更多地评估该行代码。假设
MultiSelect
为 true,您也可以自己计算选择更改,从而无需调用
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;
或者测试所选项目是否为零:
procedure TForm1.ListView1SelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
actTest.Enabled := ListView1.Selected <> nil;
end;
但是话又说回来,确实没有理由不使用 OnUpdate
事件:
procedure TForm1.ActionList1Update(Action: TBasicAction; var Handled: Boolean);
begin
actTest.Enabled := ListView1.Selected <> nil;
Handled := True;
end;
OnExecute 操作的事件,并使用其 Action
指针参数来比较它是由哪个操作触发的。执行所需操作的代码后,您可以调用某种
UpdateControls()
过程,该过程可以为您更新按钮的启用/禁用状态。在这种情况下,
OnExecute
将被调用仅一次,并且仅在您触发特定操作后并进行适当的控件可见性更新。此外,通过这种方式管理,您可以获得集中的操作管理,而不是每个操作都有
OnExecute
事件。