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(nameof(NavigationConfiguration.NavigationConfigurationType), ExpressionType.Equal, EnumNavigationConfigurationType.RibbonNavigationGuid, EnumControlFilterApplyState.OptIn)]
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 / Detailansichten) 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.
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
HauptknotenNavigationGroupControl
NavigationsgruppeExtendedNavigationGroupControl
Erweiterte NavigationsgruppeClientActionBase
Basis aller AktionenDropDownAction
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(RibbonButtonItem ribbonItem, Dictionary<string, object> additionalClientData, EnumActionVisibleForParentType parentType, DevExUIModelBase uiModel, OrmBABase orm)
{
base.AdditionalRibbonButtonAssignment(ribbonItem, additionalClientData, parentType, uiModel, orm);
additionalClientData["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.
Rechte bei einer Maskenaktion
Aktionen sind häufig nur dann möglich, wenn der Benutzer bestimmte Rechte besitzt. Beispielsweise Bearbeitungsrechte auf einem Datensatz. 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["UserHasRole"] = [true/false];
Beispiel für die Bearbeitungsrechte
additionalClientData["UserHasRole"] = orm?.UserCanEdit() ?? true;
Rechte in einer Ansichtenaktion
Im Gegensatz zu einer Aktion in einer Maske, kann in einer Ansicht nicht die Rechte auf einen konkreten Datensatz geprüft werden. In diesem Fall werden die Rechte des Anwenders auf der Datenbanktabelle geprüft und abhängig von den selektierten Datensätzen und deren Typ, die Aktion aktiv/inaktiv geschaltet. Werden alle Datensätze der Ansicht selektiert, wird automatisch angenommen, das auch alle Typen die in der Ansicht dargestellt werden können, markiert sind. In diesem Fall wird keine Prüfung aller Datensätze vorgenommen.
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["TypesUserCanHandle"] = [Komma separiete Liste der Typ-Guid mit Großbuchstaben];
Beispiel für Bearbeitungsrechte
// Die Typen aller in der Ansicht konfigurierten Datentabellen ermitteln
// Basistypen werden dabei aufgelöst
IEnumerable<OrmDataSourceCacheModel> ormDataSources = Api.ORM.GetOrmTypeCacheValuesByBase(GuidSet.ParseGUIDs(gridConfiguration.OrmDataSource));
// Keine Basistypen (Von denen können keine Datensätze existieren) und alle Datentabelle auf die der Anwender Bearbeitungsrechte prinzipiell besitzen könnte
ormDataSources = ormDataSources.Where(ff => !ff.IsBaseType && Api.User.CurrentUserIsAllowed(ff.Guid, EnumTableOperations.Delete));
// Umwandeln in eine Komma separiete Guid-Liste mit Großbuchstaben
additionalClientData["TypesUserCanHandle"] = GuidSet.JoinGUIDs(ormDataSources.Select(ff => ff.Guid)).ToUpper();
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["TestValueContains"] = "Hallo";
additionalClientData["TestFormContains"] = "Subject";
Maskenwert beinhaltet einen definierten Wert nicht
DynamicClientVisibility.Add(EnumActionVisibility.IfFormValueNotContainsValue);
additionalClientData["TestValueNotContains"] = "Hallo";
additionalClientData["TestFormNotContains"] = "Subject";
Clientside Funktion liefert True zurück
DynamicClientVisibility.Add(EnumActionVisibility.IfMethodReturnsTrue);
additionalClientData["IfMethodReturnsTrueMethod"] = "BA.Customer.Project.Ui.Utils.CheckVisibility";
Type Script:
public static CheckVisibility(menuItem: BAClientRibbonItem | BAClientDetailGridMenuItem, customData: CustomData) { ... }
Sichtbar in Masken und/oder Ansichten
DynamicClientVisibility.Add(EnumActionVisibility.OnlyForFormMode);
DynamicClientVisibility.Add(EnumActionVisibility.OnlyForGridLocation);
Selektierte Datensätze sind von bestimmten Datetabellen
DynamicClientVisibility.Add(EnumActionVisibility.IfUserHasRightsOverAnySelectedRowType);
additionalClientData["TypesUserCanHandle"] = allowedTypes.ToString().ToUpper();