Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

A class can contain actions that are generally shown as buttons or links in a UI and run some code when pressed.

A build adds an action with Action(), shown below.

Eine Klasse kann verschiedene Aktionen beinhalten welche im Kontext der Entität ausgeführt werden können.

Die Konfiguration ist dabei analog einem normalen Property mit einigen zusätzlichen Möglichkeiten:

  • Zuweisen der Aktion die ausgeführt werden soll inklusive Rückgabewert

  • Definition wie die Aktion angezeigt werden soll (in Listen, Detail etc.)

Die Builder Methode sieht wie folgt aus:

Code Block
Builder.Add.Action(...)

The action defined above doesn't do anything yet.

While a product can of course include code directly, it's strongly recommended to make some sort of method container that can be tested. The following example from the Sandbox passes the call to DeletePerson to a _businessLogic. The Result is a hint to the caller so that it can update the UI.

Code Block
private void DeletePerson([NotNull] object sender, [NotNull] MetaActionEventArgs args)
{
  if (sender is Person person)
  {
    _businessLogic.DeletePerson(person);

    args.Result = MetaActionResult.CallingObjectChanged;
  }

  args.Result = MetaActionResult.None;
}

A product can attach code using the Body(...) method.

Code Block
Builder.Add
  .Action("DeletePerson")
  .Body(DeletePerson)

Actions with Parameters

Some action require more context than other to work properly.

For example the given action will require a “Contact” as a parameter:

Code Block
languagec#
// Builder
Elements.Person.Add.Action<Person, Contact>("AddContact", nameof(Elements.Contact), AddContact)
        .Caption(German, "Kontakt hinzufügen...")
        .Caption(English, "Add contact...");
  
// Method      
private void AddContact([NotNull] Person person, [NotNull] Contact contact, MetaActionExecutionContext executionContext)
{
  if (person == null) { throw new ArgumentNullException(nameof(person)); }
  if (contact == null) { throw new ArgumentNullException(nameof(contact)); }

  person.Contacts.Add(contact);
  person.Save();
}        

This will lead to a popup once the action is invoked and the user will have to fill out the popup before being able to execute the action.

Actions with Confirmation

...

ClassBuilder.Add.Action(...)

Um einen Body zuzuweisen stehen folgende Overloads zur Verfügung:

Methode

Beschreibung

Body<Person, PersonService>((person, service) => service.Execute(person))

Der PersonService wird über den IoC ausgelöst und die Aktion Execute mit der aktuellen Person ausgeführt.

Body<PersonService>((personService) => personService.Execute)

Direkte Zuweisung eines Delegate. Die Signatur der Methode muss dabei einen Parameter vom Typ IDataObject oder einer Ableitung davon zur Verfügung stellen.

Body<Person, PersonService>()

Der PersonService muss das Interface IActionAware<in IDataObject> implementieren. Der PersonService selbst wird über den IoC aufgelöst.

Die generische Methode um eine Aktion direkt mit den MetaActionEventArgs auszuführen steht ebenfalls zur Verfügung. Es wird aber davon abgeraten diese zu verwenden. Die Abkapslung in Services erhöht die Testbarkeit der jeweiligen Aktionen und verhindert das Business-Logik direkt in die Builders geschrieben wird.

Jede Aktion kann definieren welche Änderungen sie vorgenommen hat und drückt diese über den Rückgabetyp aus.

Rückgabetyp

Beschreibung

MetaActionResult.None()

Keine Änderungen. Die Daten im Client werden nicht neu geladen.

MetaActionResult.CallingObjectChanged()

Das aufgerufene Objekt muss neu geladen werden.

MetaActionResult.MultipleObjectsChanged()

Das aufgerufene und alle verlinkten Objekte müssen neu geladen werden.

Als optionaler Parameter kann bei allen Methoden folgendes definiert werden:

Parameter

Beschreibung

FeedbackType

Kann definieren ob die Aktion erfolgreich war:

  • None (keine Meldung wird angezeigt)

  • Success

  • Warning

  • Error

DynamicString

Meldung die dem Benutzer angezeigt wird.

Soll zusätzlich zur Rückmeldung noch eine Navigation erfolgen so kann die Klasse NavigationLinkActionResult verwendet werden. Der NavigationLinkAspect muss dabei als Parameter zur Verfügung gestellt werden.

Aktionen mit Parameter

Einige Aktionen erfordern eine Eingabe um erfolgreich ausgeführt werden zu können.

Um eine Aktion mit Parametern auszustatten stehen dieselben Methoden wie oben beschrieben zur Verfügung mit der Ergänzung eines zusätzlichen Type-Argument welches den Parameter-Typ identifiziert.

Methode

Beschreibung

Body<Person, Contact, PersonService>((person, contact, service) => service.Execute(person, contact))

Der PersonService wird über den IoC ausgelöst und die Aktion Execute mit der aktuellen Person ausgeführt.

Body<PersonService>((personService) => personService.Execute)

Direkte Zuweisung eines Delegate. Die Signatur der Methode muss dabei einen Parameter vom Typ IDataObject und des entsprechenden Parameter enthalten oder einer Ableitung davon zur Verfügung stellen.

Body<Person, Contact, PersonService>()

Der PersonService muss das Interface IActionAware<in TDataObject, TParameter> implementieren. Der PersonService selbst wird über den IoC aufgelöst.

Der Parameter für die Aktion wird im Client über ein Popup abgefragt und danach an die entsprechende Aktion weitergeleitet. Es stehen dieselben Rückgabetypen wie bei einer normalen Aktion zur Verfügung.

Aktionen mit Bestätigung

Aktionen können optional eine Bestätigung des Benutzers einholen. Dies ist hilfreich wenn eine Aktion potentiell schwerwiegende Konsequenzen haben könnte.

Das folgende Snippet fragt nach der Bestätigung des Benutzers bevor die Aktion ausgeführt wird:

Code Block
languagec#
builder.Get.Class(nameof(elements.Person)).Add.Action("TestActionWithConfirmation")
        .RequiresConfirmation()
        .Content(German, "Inhalt")
        .Title(German, "Titel")
        .ContinueCaption(German, "Weiter")
        .CancelCaption(German, "Abbrechen");

Die Captions für die einzelnen Bereich können dabei auch leer gelassen werden um die Standardübersetzungen zu verwenden.

Placement of actions in a List

If an action is added to a list via LinkAction the placement can be controlled with the following options:

Code Block
list.Add.LinkAction(metadata.Person.LowerCaseNameListAction).ShowInListSelection().IsOverflowByDefault();
list.Add.LinkAction(metadata.Person.UpperCaseNameListAction).ShowInListRow();

Placement of actions in a Detail

If an action is added directly to a detail layout the action will be displayed in the sidebar

Code Block
detail.Add.LinkAction(metadata.Person.LowerCaseNameListAction);
detail.Add.LinkAction(metadata.Person.UpperCaseNameListAction);

To show an action in a layout add it to the parent element e.g a group:

Code Block
group.Add.LinkAction(metadata.Person.LowerCaseNameDetailAction);

...

sind optional. Wird nichts angegeben werden die Standard-Übersetzungen verwendet.

Platzierung von Aktionen

// TODO