Как выполнить элемент ActionList из TListViewItem
Я пытаюсь выполнить действие (TakePhotoFromCameraAction) в TActionList, когда выбран TListViewItem.
Ни TlistView, ни TListViewItem не имеют свойства Action, поэтому я попытался вызвать ActionList[0].Execute в событии, но ничего не происходит.
Есть идеи?
Далее: код очень прост, так как это был всего лишь тест для этой проблемы. Я сосредоточился на ActionList, так как именно это я буду использовать (когда я разберусь). Button1 не работает (всегда происходит сбой, даже если кнопка 2 не работает), тогда как (новая) Button2 работает нормально.
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;
2 ответа
Вы можете использовать старый добрый tag
свойство TListViewItem для хранения указателя на TAction, который вы хотите использовать с этим элементом. Конечно, вы не можете установить его в инспекторе объектов, но можете сделать это программно в событии TForm.onCreate или в другом удобном месте. Он имеет тип NativeInt, размер которого равен указателю, будь то 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;
Может быть, лучше представить вашего собственного потомка TListViewItem, который имеет свойство Action, таким образом, вам придется заполнять свой список только в коде, добавляя не базовый TListViewItem, а TActionListViewItem (имя вашего класса), который должен выполнять больше работы, но даст более понятный код.
Там нет никакой разницы (кроме того, чтобы быть некрасивым), чтобы позвонить ActionList1[0].Execute;
против Action1.Execute;
,
Вы не показали .fmx
файл, поэтому я не могу знать, какую связь вы можете настроить между компонентами, но, похоже, вы ничего не назначили для события OnExecute действия, и, следовательно, не получить ожидаемый ответ на Execute
вызов.
Версия документации FMX не очень понятна, но версия VCL (IMO) лучше (в кратком тесте я не вижу различий в реальной функциональности): Из документации:
Отвечает, когда клиентский элемент управления "срабатывает".
Выполнение вызывается автоматически, когда клиентский элемент управления "срабатывает" (например, когда пользователь нажимает кнопку или выбирает пункт меню). Он возвращает True, если найден обработчик события для обработки действия, False, если не было обработчика события или действие не было включено.
но вы можете, конечно, также позвонить Execute
прямо как ты пытался. И далее
Выполнить первым гарантирует, что действие будет обновлено. Затем, если свойство Enabled имеет значение True, оно пытается обработать действие, генерируя событие OnExecute в списке действий, который содержит это действие (если действие принадлежит списку действий). Если обработчик события OnExecute списка действий не обрабатывает действие, Execute генерирует событие OnActionExecute для самого приложения. Если ни список действий, ни приложение не обрабатывают действие в ответ на эти события, Execute генерирует событие OnExecute для себя. Если у этого действия нет обработчика события OnExecute, команда Execute указывает приложению найти текущий целевой элемент управления и вызвать метод ExecuteTarget, который представляет собой механизм, с помощью которого предопределенные классы действий выполняют свою функцию.
Обратите внимание, что вы можете обрабатывать действия в TActionList.OnExecute
или в TAction.OnExecute