1
votes

I'm making a multi-device application in Delphi XE8 which uses LiveBindings to a dataset.

There are a number of LB-specific Actions for FMX, including TFMXBindNavigateDelete. I'm trying to use this in a button-click handler like this:

Button Click Code:

procedure TForm1.Button1Click(Sender: TObject);
begin
  if cdsOrdersSTATUS.Value='READY' then
  begin
    ShowMessage('Your Order Is Already READY/PENDING!');
  end
  else
  begin
    TAction(ActionList1.Actions[0]).Execute; //Not working,why?
  end;
end;

The first (and only) item in ActionList1's Actions is my FMXBindNavigateDelete1.

The problem is, even if the code TAction(ActionList1.Actions[0]).Execute executes, the current dataset record is not deleted, so apparently TFMXBindNavigateDelete's Action has no effect. Why is this, and how can I make it work?

Pic. ActionList1:

ActionList

2
Changing the Name of an Action does not invoke the action, only change its identifier. What's wrong with simply assigning the Action to the TButton.Action property and let the button invoke it automatically? What are you really trying to accomplish?Remy Lebeau
if cdsOrdersSTATUS.Value='READY' then begin ShowMessage('Your Order Is Already READY/PENDING!'); end else begin ActionList1.Actions[0].Name:='LiveBindingsBindNavigateDelete1'; end;Alex Kirov
I don't understand what you are trying to say. If you just want to invoke the OnExecute event of an Action, call its Execute() method.Remy Lebeau
@Dear Remy I need to put On Button manual code to call ActionList.action[0]. how to call on Button by code?Alex Kirov
if .....then begin // end else begin ActionList1.Actions[0].Name:='LiveBindingsBindNavigateDelete1'; //this is not working ? end;Alex Kirov

2 Answers

4
votes

Actually, I think this is a good question and doesn't deserve the downvote.

I can reproduce your problem. I put two buttons on the FMX form. I set Button1's OnClick to your Button1Click and Button2's Action to LiveBindingsBindNavigateDelete1.

Clicking Button2 pops up the standard 'Delete record?' confirmation and deletes the current record if I answer "Yes", as expected.

However, when clicking Button1, even if your else block executes, the 'Delete record?' confirmation does not appear, so the record has no chance of being deleted.

The reason is in the code

function TCustomAction.Execute: Boolean;
begin
  Result := False;
  if Supported and not Suspended then
  begin
    Update;
    if Enabled and AutoCheck then
      if (not Checked) or (Checked and (GroupIndex = 0)) then
        Checked := not Checked;
    if Enabled then
      Result := ((ActionList <> nil) and ActionList.ExecuteAction(Self)) or
        ((Application <> nil) and Application.ExecuteAction(Self)) or inherited Execute or
        ((Application <> nil) and Application.ActionExecuteTarget(Self));
  end;
end;

The Enabled property seems by default to be set to False during the call to Update so the if Enabled then ... never executes. I haven't managed to find a way to get Enabled set to True during the call to Update. Perhaps someone else knows how to do that.

In the case of Button2, execution then passes to TComponent.ExecuteAction and it is the call to Action.ExecuteTarget(Self) in it which results in the record-deletion routine executing.

So, from that, your problem seemed to me to become how to adjust the code so that TComponent.ExecuteAction gets executed, in other words, how to associate the Action with a component. The answer was fairly obvious.

All that's needed is this

procedure TForm1.Button1Click(Sender: TObject);
begin
 if cdsOrdersSTATUS.Value='READY' then
  begin
    ShowMessage('Your Order Is Already READY/PENDING!');
  end
  else
  begin
    Button1.ExecuteAction(LiveBindingsBindNavigateDelete1);  //  <- this works
    //LiveBindingsBindNavigateDelete1.Execute; //Not working,why?
  end;
end;
0
votes

I didn't understand exactly what you wanted to do but if you trigger the action by it's index, you can do something like this:

TAction(ActionList1.Actions[0]).Execute;