Es wird eine neue C# Klasse benötigt. Typischerweise wird diese im Ordner „Configuration\Navigation\ClientAction“ abgelegt. Die Basisklasse ist ClientActionBase, und es müssen drei Attribute gesetzt werden. Wie alle anderen Konfigurationen muss auch diese serialisier bar sein, mit Toolbox wird die Aktion in der Toolbox für die Navigationen registriert und mit ControlFilter wird die Aktion nur für die Ribbon bar sichtbar gemacht.

[Serializable]
[Toolbox(EnumConfigurationType.NavigationConfigurationGuid, true)]
[ControlFilter("NavigationConfigurationType", ExpressionType.Equal, EnumNavigationConfigurationType.RibbonNavigationGuid, EnumControlFilterApplyState.IfPositive)]
public class ClientActionMyAction : ClientActionBase { }

Im Konstruktor werden die wichtigsten Eigenschaften einer Aktion festgelegt (Siehe Beispiel). Folgende Punkte müssen beachtet werden.

  • Anstatt Klartext sollte bei den Eigenschaften „ToolboxName“, „Caption“, „ToolboxGroupName“ und „DesignerHintText“ immer eine Translation Guid benutzt werden.
  • Der „ControlInitName“ sollte Eindeutig sein. Also immer mit eigenen Präfixen arbeiten.
  • Für „Id“ muss immer eine eigene Guid erzeugt werden.
public ClientActionMyAction() : base()
{
    ToolboxName = "Meine Aktion";
    Caption = "Meine Aktion";
    ControlInitName = "TrainingMyAction";
    ToolboxGroupName = "Training Aktionen"; // Translation Guid verwendbar
    Id = new Guid("[INSERT ACTION GUID]");
    Icon = "projector";
    IconName = Icon;
    DesignerHintText = "Meine Aktion tut genau das, was gewünscht wird."; // Translation Guid verwendbar
    VisibilityForParentTypes.Add(EnumActionVisibleForParentType.Form);
}

Mit dem Objekt VisibilityForParentTypes kann man steuern für welche Objekte (Masken / Ansichten) die eigene Aktion prinzipiell verwendet werden kann.
Damit ist schon eine eigene Aktion so implementiert, dass sie im Designer konfiguriert werden kann.

Die registrierte Aktion kann nun in dem Konstruktor der C# Klasse hinterlegt werden.

AdditionalClientData.AddOrUpdate("ActionMethodId", "BA.Training.ClientActionMyAction"); 

Damit ist das Grundgerüst einer konfigurierbaren Aktion erstellt.

Drag & Drop Regel

Bei jedem Steuerelement, welches im Designer zur Konfiguration genutzt werden soll, muss man darauf achten, dass die Drag & Drop Regeln korrekt gesetzt sind. Näheres dazu findet man in dem speziellen Kapitel.

Meistens werden für Aktionen auf Basis von ClientActionBase keine weiteren Regeln benötigt.

Wichtige Klassen zur Definition von Regeln

  • NavigationConfiguration Hauptknoten
  • NavigationGroupControl Navigationsgruppe
  • ExtendedNavigationGroupControl Erweiterte Navigationsgruppe
  • ClientActionBase Basis aller Aktionen
  • DropDownAction Aufklappelement

Eigenschaften

Den Aktionen kann man Eigenschaften geben, die in der Konfiguration angepasst werden. Beispiel:

[PropertiesGroup("Kundengruppe")] // Übersetzungs GUID verwendbar
[DisplayName("Toastermeldung")] // Übersetzungs GUID verwendbar
[Translate("Training")]
[HelpText("Das ist die Nachricht, die im Toaster ausgegeben wird.")] // Übersetzungs GUID verwendbar
public string Message { get; set; }

Übertragung von Werten an die Type Script Funktion

In der Methode AdditionalRibbonButtonAssignment können Daten in das AdditionalClientData Objekt geschrieben werden, welche anschließend in der Type Script Funktion verwendet werden können. Das Beispiel übersetzt den Inhalt einer Eigenschaft in die Sprache des Anwenders und überträgt den Wert.

public override void AdditionalRibbonButtonAssignment(DevExpress.Web.RibbonButtonItem ribbonItem, EnumActionVisibleForParentType parentType, DevExUIModelBase uiModel = null)
{
    base.AdditionalRibbonButtonAssignment(ribbonItem, parentType, uiModel);
    AdditionalClientData.AddOrUpdate("Message", Api.Text.Format(Message));
}

Der Wert kann nun in der Type Script Funktion verwendet werden.

public static ClientActionMyAction(event: any, customData: CustomData) {
    alert(customData.Message as string);
}

Aktiv / Inaktiv der Aktion

Wenn Aktionen in Masken verwendet werden, kann es Situationen geben, in denen die Aktionen nicht ausgeführt werden dürfen. Dazu verwendet man das Objekt DynamicClientVisibility und fügt diesem bestimmte Verhalten hinzu.

Fehlende Rechte

Falls der Benutzer keine Bearbeitungsrechte auf den aktuellen Datensatz hat, sollen bestimmte Aktionen nicht möglich sein.
Falls dies bei der eigenen Aktion der Fall ist, muss im Konstruktor folgende Zeile hinzugefügt werden:

DynamicClientVisibility.Add(EnumActionVisibility.IfUserHasRole);

Benötigte Client Daten

AdditionalClientData.AddOrUpdate("UserHasRole", true/false);

Des Weiteren muss das Interface IOrmSecurityHandler implementiert und die Methode CanHandleOrm überschrieben werden. Mit dem Setzen des Wertes auf true wird signalisiert, dass der aktuelle Benutzer den Datensatz bearbeiten darf.

public bool CanHandleOrm(object DataObject, OrmBABase orm) { .... }

Beispiel

public bool CanHandleOrm(object DataObject, OrmBABase orm)
{
    bool canHandle;
    if (orm != null)
        canHandle = orm.IsAllowed(EnumTableOperations.Edit);
    else
    {
        OrmEntityConfiguration entityConfig = Api.Config.OrmEntity(EnumDataSourceExtension.MyDataTable.ValueGuid);
        canHandle = entityConfig.IsAllowed(EnumTableOperations.Edit) != EnumTableOperations.Denied;
    }

    AdditionalClientData.AddOrUpdate("UserHasRole", canHandle);
    return canHandle;
}

Weitere Möglichkeiten

Die Auswahlliste EnumActionVisibility beinhaltet eine Reihe weiterer Möglichkeiten. Die prinzipielle Verwendung ist immer identisch. Im Konstruktor wird das Verhalten definiert und die dazu benötigten Daten werden in das AdditionalClientData Objekt geschrieben. Ein paar Beispiele:

Datensatz muss gespeichert sein

DynamicClientVisibility.Add(EnumActionVisibility.OnlyWhenSaved);

Maskenwert beinhaltet einen definierten Wert

DynamicClientVisibility.Add(EnumActionVisibility.IfFormValueContainsValue);
AdditionalClientData.AddOrUpdate("TestValueContains", "Hallo");
AdditionalClientData.AddOrUpdate("TestFormContains", "Subject");

Maskenwert beinhaltet einen definierten Wert nicht

DynamicClientVisibility.Add(EnumActionVisibility.IfFormValueNotContainsValue);
AdditionalClientData.Add("TestValueNotContains", "Hallo");
AdditionalClientData.Add("TestFormNotContains", "Subject");

Clientside Funktion liefert True zurück

DynamicClientVisibility.Add(EnumActionVisibility.IfMethodReturnsTrue);
AdditionalClientData.AddOrUpdate("IfMethodReturnsTrueMethod", "BA.Customer.Project.Ui.Utils.CheckVisibility"); 

Sichtbar in Masken und/oder Ansichten

DynamicClientVisibility.Add(EnumActionVisibility.OnlyForFormMode);
DynamicClientVisibility.Add(EnumActionVisibility.OnlyForGridLocation);