Delphi 如何从TListViewItem执行ActionList项

Delphi 如何从TListViewItem执行ActionList项,delphi,firemonkey,tlistview,tactionlist,Delphi,Firemonkey,Tlistview,Tactionlist,当选定一个TListViewItem时,我试图在TActionList中执行一个动作(TakePhotoFromCameraAction) TlistView和TListViewItem都没有Action属性,因此我尝试调用ActionList[0]。在事件中执行,但什么都没有发生 有什么想法吗 进一步: 代码非常简单,因为它只是针对这个问题的一个测试。我把注意力集中在行动列表上,因为这是我将使用的(当我整理它时)。 按钮1不工作(它总是失败,即使按钮2不工作),而(新)按钮2工作正常 type

当选定一个TListViewItem时,我试图在TActionList中执行一个动作(TakePhotoFromCameraAction)

TlistView和TListViewItem都没有Action属性,因此我尝试调用ActionList[0]。在事件中执行,但什么都没有发生

有什么想法吗

进一步: 代码非常简单,因为它只是针对这个问题的一个测试。我把注意力集中在行动列表上,因为这是我将使用的(当我整理它时)。 按钮1不工作(它总是失败,即使按钮2不工作),而(新)按钮2工作正常

type
  TForm1 = class(TForm)
    ActionList1: TActionList;
    Memo1: TMemo;
    TakePhotoFromCameraAction1: TTakePhotoFromCameraAction;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
     ActionList1[0].Execute;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
     if TakePhotoFromCameraAction1.Execute
     then
         Memo1.Lines.add('Photo OK')
     else
         Memo1.Lines.add('Photo Fail');
end;

您可以使用TListViewItem的良好旧
标记
属性来存储指向要用于此项目的战术的指针。当然,您不能在对象检查器中进行设置,但可以在TForm.onCreate事件或其他方便的地方进行编程。它具有与指针大小相同的Nativent类型(无论是32位还是64位体系结构),因此应该可以正常工作

大概是这样的:

//in formCreate or other place to initialize actions:
TakePhotoItem.Tag:=NativeInt(TakePhotoFromCameraAction);
SavePhotoItem.Tag:=NativeInt(SavePhotoAction);
//...

//onitemchange event handler
if AItem.Tag<>0 then
  TAction(AItem.Tag).Execute;
//在formCreate或其他地方初始化操作:
TakePhotoItem.Tag:=nativent(TakePhotoFromCameraAction);
SavePhotoItem.Tag:=NativeInt(SavePhotoAction);
//...
//onitemchange事件处理程序
如果是AItem.Tag0,那么
TAction(AItem.Tag)。执行;
也许最好引入您自己的TListViewItem的后代,它具有Action属性,这样您就只能在代码中填充listview,而不是添加基本的TListViewItem,而是添加TActionListViewItem(类的名称),它有更多的工作要做,但会产生更易于理解的代码。

没有区别(丑陋的除外)调用
ActionList1[0]。执行;
Action1.Execute;

您没有显示
.fmx
文件,因此我不知道您可能在组件之间设置了什么链接,但是,您似乎没有为actions OneExecute事件指定任何内容,因此无法获得对
Execute
调用的预期响应

文档的FMX版本不是很清楚,但VCL版本(IMO)更好(在一个简短的测试中,我看不到实际功能的任何差异): 发件人:

当客户端控件“激发”时响应

当客户端控件“激发”时自动调用Execute(用于 例如,当用户单击按钮或选择菜单项时) 如果找到处理该操作的事件处理程序,则返回True,否则返回False 如果没有事件处理程序或操作未启用

当然,您也可以在尝试时直接调用
Execute
,而且更进一步

首先执行确保操作已更新。然后,如果 属性为True时,它尝试通过生成 包含此操作的操作列表上的OneExecute事件(如果 操作属于操作列表)。如果操作列表为OneExecute 事件处理程序不处理该操作,Execute生成 应用程序本身上的OnActionExecute事件。如果 列表,应用程序也不会处理响应这些操作的操作 事件,Execute在其自身上生成OneExecute事件。如果此操作 没有OneExecute事件处理程序,Execute指示应用程序 找到当前目标控件并调用ExecuteTarget方法, 预定义动作类执行的机制是什么 它们的功能


请注意,您可以在
TActionList.OnExecute
TAction.OnExecute

中处理动作,获得动作的方式有很多种,但是如果asker不能让Execute做任何事情,为什么获得动作的不同途径会改变事情呢?@DavidHeffernan对我来说,OP似乎愿意多次使用tested方法启动操作,但仅分配操作属性,未找到该属性,尝试以其他方式执行,而现在什么都不起作用,则将责任归咎于actionList[0]。执行,尽管此行应该有效(使用预定义索引调用操作的坏习惯,但不管怎样).你说得对,OP应该检查是否调用了action.Execute,以及为什么action什么都不做。我完全同意
ActionList[0]
不好。但是我认为提问者需要被引导去问一个真正的问题。因为我们知道
Execute
是有效的,所以我们必须问到底是什么问题。感谢你的回答和评论。我想基本的问题是在代码中执行操作的最好方式,而不是作为属性。答案是我不明白为什么直接访问列表似乎不起作用。既然我们知道
execute
起作用,那么手动执行一个操作就很简单了,在这种情况下:从CameraAction1.execute拍摄照片;我不明白为什么直接访问列表似乎不起作用。因为我们知道
execute
起作用,显然您的代码中存在缺陷。请oduce a.好的,问题解决了。我不得不在虚拟机上重新安装Windows 7和Delphi,重新安装了所有程序,问题消失了。其他一些事情有点奇怪-例如,我无法登录Slack。