AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Actions verwenden - Pre- und Post-Action

Ein Thema von mm1256 · begonnen am 5. Jul 2015 · letzter Beitrag vom 6. Jul 2015
Antwort Antwort
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
640 Beiträge
 
Delphi 10.1 Berlin Professional
 
#1

Actions verwenden - Pre- und Post-Action

  Alt 5. Jul 2015, 18:03
Hallo,

bin mir nicht sicher, ob hier der richtige Platz ist, darum bitte an die Mods, ggf. verschieben.

Ich habe folgendes Problem: Es geht um eine Anwendung mit mehreren Fenstern. Jedes Fenster hat ein Mainmenu und Buttons. Den Menü-Einträgen und Buttons ist größtenteils eine Action zugewiesen. Die TActionlist befindet sich in einem separaten Datenmodul, das von allen Fenstern verwendet wird. Soweit so gut.

Nun muss ich aber manchmal wenn eine Action ausgeführt wird, vorher und nachher am Formular Änderungen vornehmen, z.B. Button's disablen, damit die Funktion/Action nicht rekursiv aufgerufen wird. Ich müsste also praktisch vor und nach dem Ausführen der Action etwas ausführen.

Hat man daran nicht gedacht? Oder geht das, und ich seh den Wald vor Bäumen nicht?
Gruss Otto
Wenn du mit Gott reden willst, dann bete.
Wenn du ihn treffen willst, schreib bei Tempo 220 eine SMS
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.007 Beiträge
 
Delphi 12 Athens
 
#2

AW: Actions verwenden - Pre- und Post-Action

  Alt 5. Jul 2015, 18:24
z.B. Button's disablen, damit die Funktion/Action nicht rekursiv aufgerufen wird.
Das kann eigentlich nur dann vorkommen, wenn du in deinem Code Application.ProcessMessages aufrufst (was man ja nicht tun soll). Andernfalls wird der Event-Handler der Action als Antwort auf eine Message ausgeführt (Tastendruck, Mausklick oder so) und kann somit nicht von der Bearbeitung einer anderen Message unterbrochen werden.

Also stellt sich zunächst die Frage, warum du während des Events ünerhaupt einen Button disablen willst. Vielleicht, weil der Event zulange braucht under Benutzer aus Frust immer wieder auf den Button klickt?

Je nach Anwendungsfall gibt es da verschiedene Ansätze. Ein Wunsch nach einem Pre- und Post-Action-Event ist m.W. bisher noch nicht aufgetaucht.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
3.908 Beiträge
 
Delphi 12 Athens
 
#3

AW: Actions verwenden - Pre- und Post-Action

  Alt 5. Jul 2015, 21:29
Hallo mm1256,

wenn du meinst das während des Events Componenteneigenschaften geändert werden,
und dabei werden neue Actions getriggert, so das etwas rekursiv oder anders falsch läuft.

Man kann ja die OnChange Events vor solchen Veränderungen
kurz abklemmen (OnChange := nil),
Werte, z.B. Text ändern,
und danach wieder anklemmen (OnChange := oldEvent.
Wenn das nur ein einzelnes Problem betrifft.

Aber vielleicht wäre es sauberer wenn du vielleicht ein MultiEvent-System von Spring4D anschaust, ob das evtl. deine Probleme löst.

Rollo
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Actions verwenden - Pre- und Post-Action

  Alt 5. Jul 2015, 21:53
Siehe mein Tutorial http://www.delphipraxis.net/185749-f...-callback.html da mache ich genau das
Delphi-Quellcode:
procedure TFoo.BarActionExecute( Sender: TObject );
begin
  TAction(Sender).Enabled := False;
  FService.DoSomething(
    procedure ( AResult: TBar; AException: Exception )
    begin
      // Verarbeitung der Rückgabe
      TAction(Sender).Enabled := true;
    end );
end;
Alle Buttons, die mit dieser Action verbunden sind, folgen der Enabled Eigenschaft.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
640 Beiträge
 
Delphi 10.1 Berlin Professional
 
#5

AW: Actions verwenden - Pre- und Post-Action

  Alt 6. Jul 2015, 09:17
Hallo,

erst mal vielen Dank für eure Antworten.

Der Tipp von Sir Rufo löst das Problem teilweise, d.h. bei einigen Actions passt das prima.

Bei anderen Actions die gegeneinander verriegelt werden müssen und länger dauern können (z.B. alle Aktionen die Änderungen am Datenbestand vornehmen wie Daten-Import, Daten-Export...) wird es problematischer. Ich hab mich nun dazu entschlossen, die Actions im Public-Bereich der TActions zu deklarieren und entsprechend zu verwenden. Erscheint mir momentan der brauchbarste Kompromiss zu sein.

Das ursächliche Problem hier ist - wie Uwe schon richtig vermutet hat - das "Verbotene". In dem Fall bei der Fortschritt-Anzeige.
Gruss Otto
Wenn du mit Gott reden willst, dann bete.
Wenn du ihn treffen willst, schreib bei Tempo 220 eine SMS
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Actions verwenden - Pre- und Post-Action

  Alt 6. Jul 2015, 10:58
Hmmm, jede Action hat ein OnUpdate Event und dort kann man z.B. die Eigenschaften der Action verändern (dafür ist der Event da).

Und genau dort stellt man dann die Abhängigkeiten zwischen den Actions her. Einfach ein paar Flags die beim Starten einer Action gesetzt werden und dann im OnUpdate die Enabled Eigenschaft der jeweiligen Action setzen.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
640 Beiträge
 
Delphi 10.1 Berlin Professional
 
#7

AW: Actions verwenden - Pre- und Post-Action

  Alt 6. Jul 2015, 12:42
@SirRufo: Das haut leider nicht hin, denn "OnUpdate" wird bereits gefeuert, wenn das Menü gezeichnet wird.

TActionList.OnExecute wäre als Pre-Event geeignet, die infrage kommenden Actions zu disablen, aber das ist mir auch zu umständlich zu implementieren. Aber, ich glaub ich hab die Lösung. Der Grundgedanke ist, in der Action die erforderlichen Actions zu disablen, und nach Ausführung der Action diese wieder zu enablen.

Code-Auszug:

Delphi-Quellcode:
type
  TActionArray = array of TAction;
  TActions = class(TDataModule)
    MyActionList: TActionList;
    acImport: TAction;
    acExport: TAction;
    . . .
  public
    { Public-Deklarationen }
    procedure Actions_Disable(aActionsToDisable: TActionArray);
    procedure Actions_Enable;
  end;

implementation

procedure TActions.Actions_Disable(aActionsToDisable: TActionArray);
var
  i, Lst: integer;
begin
  for i := 0 to Pred(Actions.MyActionList.ActionCount) do begin
    for Lst := Low(aActionsToDisable) to High(aActionsToDisable) do begin
      if Actions.MyActionList.Actions[i] = aActionsToDisable[Lst] then begin
        if Actions.MyActionList.Actions[i].Enabled then begin // Actions die bereits disabled sind ausschließen
          Actions.MyActionList.Actions[i].Tag := 1; // Flag setzen, dass die Action disabled wurde
          Actions.MyActionList.Actions[i].Enabled := false;
        end;
      end;
    end;
  end;
end;

procedure TActions.Actions_Enable;
var
  i: integer;
begin
  for i := 0 to Pred(Actions.MyActionList.ActionCount) do begin
    if Actions.MyActionList.Actions[i].Tag > 0 then begin
      Actions.MyActionList.Tag := 0;
      Actions.MyActionList.Actions[i].Enabled := true;
    end;
  end;
end;

procedure TActions.acImportExecute(Sender: TObject);
begin
  Actions_Disable([acImport,acExport]);
  try
    // Export durchführen
  finally
    Actions_Enable;
  end;
end;
Ein bischen Q&D aber so funktioniert's erst mal. Verbesserungsvorschläge sind gerne willkommen.
Gruss Otto
Wenn du mit Gott reden willst, dann bete.
Wenn du ihn treffen willst, schreib bei Tempo 220 eine SMS
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Actions verwenden - Pre- und Post-Action

  Alt 6. Jul 2015, 13:40
Du machst dir einfach das Leben zu schwer ...
Delphi-Quellcode:
procedure TFoo.BarActionUpdate(Sender:Tobject);
begin
  TAction(Sender).Enabled = not FBarRunning;
end;

procedure TFoo.BarActionExecute(Sender:TAction);
begin
  BarRunning := True;
  FService.DoBar(
    procedure (AResult:TBar; AException:Exception)
    begin
      // ...
      BarRunning := False;
    end );
end;
Das OnUpdate wird immer wieder ausgelöst und hat als Hauptaufgabe, den Status einer Action zu setzen. Also genau das, was du brauchst.

Im OnUpdate sollst du NICHT irgendeine Aktion ausführen, sondern NUR den Status einer Action setzen.

Wenn du dich jetzt auf einige Flags einigen kannst, dann sieht so eine OnUpdate Methode z.B. auch so aus:
Delphi-Quellcode:
procedure TFoo.SomeAction(Sender:TObject);
begin
  TAction(Sender).Enabled := ( not BarRunning and FooRunning ) or FooBarRunning;
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
640 Beiträge
 
Delphi 10.1 Berlin Professional
 
#9

AW: Actions verwenden - Pre- und Post-Action

  Alt 6. Jul 2015, 14:52
Das hab ich schon kapiert (dass ich im OnUpdate nur die Flags setzen soll) aber da bin ich auf ein paar Probleme bzw. Nachteile gestoßen:

- Neue Action bedeutet manchmal auch neues Flag, da kommt eine ansehnliche Anzahl an Flags zusammen. Wobei die Anzahl nicht das Problem ist, sondern die Lesbarkeit des daraus resultierenden Codes.

- Wenn eine Action (sprich ein Menüpunkt oder ein Button) durch etwas Anderes Disabled wurde (z.B. die Benutzerrechte) dann muss ich das bei den Flags zusätzlich mit berücksichtigen. Sonst schalten mir die Flags wieder Menüpunkte ein, die vorher disabled waren. Das wird langfristig gesehen schwer zu pflegender Code. Hinzu kommt, die Benutzerrechte und die "Verriegelung" der Actions untereinander sind zwei Schichten, die ich nicht miteinander vermischen möchte.

Bei der aktuellen Variante muss ich mir lediglich bei der Ausführung der Action Gedanken machen, welche Actions disabled werden sollen
Code:
Actions_Disable([.....])
und das Enablen passiert automatisch. Dadurch wird übrigens nicht das Tag der Menü-Items/Buttons beeinflusst, d.h. ich kann deren Tag unabhängig davon weiter verwenden.

Ich werde es jetzt mal so weiter verfolgen. Vielleicht tauchen ja noch neue Probleme auf, und ich muss doch noch auf irgendwelche Flags zurückgreifen.
Gruss Otto
Wenn du mit Gott reden willst, dann bete.
Wenn du ihn treffen willst, schreib bei Tempo 220 eine SMS
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: Actions verwenden - Pre- und Post-Action

  Alt 6. Jul 2015, 15:26
Oh ja, die Benutzrechte sind ja sooo schwer da mit reinzubringen:
Delphi-Quellcode:
TAction(Sender).Enabled :=
  CurrentUser.HasRight( 'Foo' ) and
  not FooRunning;
und auch noch total unübersichtlich ...

Mit den Flags meine ich nicht die Eigenschaften der Actions, sondern ob irgendetwas aktiv gerade läuft. Die Eigenschaften der Actions setzt man dann im OnUpdate und zwar abhängig von diesen Flags.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz