Die Idee des Dialogsystems unterscheidet den Dialogentwickler von dem Entwickler, der den Dialog nutzt. Der Entwickler implementiert einen Dialog, der über Parameter gesteuert eine Aufgabe erfüllt. Über ein Objekt wird das Ergebnis des Dialoges zur Verfügung gestellt.
Der Nutzer des Dialoges ruft den Dialog auf und setzt die Parameter entsprechend seinen Anforderungen. In einer Callbackfunktion wird ihm das Ergebnis des Dialoges zurückgeliefert. Damit wird sichergestellt, dass der Dialog beliebig technisch umgestellt werden kann, da der Nutzer keinen Zugriff auf den Dialog hat.
Dialogklasse
Ein Dialog besteht aus einer Dialogklasse mit zwei Methoden.
[DialogImplementation("BA.Customer.Project.MyDialog")]
public class MyDialog : DialogImplementationBase
{
public override void CreateDialogContent(
DevExFormModel formModel, // Das Formmodel zur Darstellung des Dialoges
HttpRequestBase request, // Der HttpRequest
ModelStateDictionary modelState, // Der Status des verwendeten Models
Dictionary<String, Object> parameter, // Die Parameter des Dialoges
object bindObject = null // Das Model mit den Daten
)
{ .... }
public override DialogResultModel HandleAction(
HttpRequestBase request, // Der HttpRequest
ModelStateDictionary modelState, // Der Status des verwendeten Models
Dictionary<String, Object> parameter, // Die Paramter des Dialoges
String buttonId, // Die ID des gedrückten Buttons
object bindObject, // Das Model mit den Daten
string propertyPrefix = "" // Der mögliche Prefix von Werten
)
{
DialogResultModel result = base.HandleAction(request, modelState, parameter, buttonId,
bindObject, propertyPrefix);
return result;
}
}
Die Klasse muss zwei Voraussetzungen erfüllen
- Sie muss die Klasse
DialogImplementationBase
erweitern. - Über das Attribute
DialogImplementation
wird der Dialogidentifier festgelegt
Die Methode HandleAction
muss nicht überschrieben werden.
CreateDialogContent
In dieser Methode wird der Inhalt des Dialoges implementiert. Diese Methode wird bei allen Aktualisierungen aufgerufen und kann jeweils einen anderen Inhalt generieren.
Einfacher Dialog mit einer Textbox
public override void CreateDialogContent(DevExFormModel formModel, HttpRequestBase request, ModelStateDictionary modelState, Dictionary<String, Object> parameter, object bindObject = null)
{
formModel.Title = "Dialogtitel";
formModel.DataSource = null;
TextEditControl textControl = new TextEditControl()
{
Id = "4095021E-6762-4894-8B42-9164EBC1281F".ToGuid(),
Caption = "Text"
};
Controls.Add(textControl);
formModel.AddButton(DialogButtonIds.OkButton, "OK", true);
formModel.AddButton(DialogButtonIds.CancelButton, "Cancel", false, "BA.Ui.Dialog.DialogManager.DialogDefaultCancel");
}
Mit Hilfe eines Datenmodels werden die Maskensteuerelemente gebunden
public override void CreateDialogContent(DevExFormModel formModel, HttpRequestBase request, ModelStateDictionary modelState, Dictionary<String, Object> parameter, object bindObject = null)
{
formModel.Title = "Dialogtitel";
MyDialogModel datenModel;
if (bindObject == null)
{
datenModel = new MyDialogModel();
datenModel.TextEdit = "Vorgabewert";
}
else
datenModel = (MyDialogModel)bindObject;
formModel.DataSource = datenModel;
TextEditControl textControl = new TextEditControl()
{
Id = "4095021E-6762-4894-8B42-9164EBC1281F".ToGuid(),
Caption = "Text",
OrmFieldName = "TextEdit"
};
Controls.Add(textControl);
formModel.AddButton(DialogButtonIds.OkButton, "OK", true);
formModel.AddButton(DialogButtonIds.CancelButton, "Cancel", false,
"BA.Ui.Dialog.DialogManager.DialogDefaultCancel");
}
public class MyDialogModel
{
public String TextEdit { get; set; }
}
Buttons
Mit AddButton()
werden Buttons zu Dialogen hinzugefügt. Entweder gibt man die 4 wichtigsten Parameter direkt an:
formModel.AddButton(DialogButtonIds.CancelButton, "37857EB7-EDBC-4419-9823-6FC107794621".Translate(), false, "BA.Ui.Dialog.DialogManager.DialogDefaultCancel");
Oder man erstellt ein DialogButtonDefinition
Model mit allen Eigenschaften und übergibt dieses als Parameter:
DialogButtonDefinition okButton = new DialogButtonDefinition() {
ButtonId = DialogButtonIds.OkButton,
Caption = Api.Text.Format("68B063D1-9626-4015-BCC8-8D41C76B8596"),
ServerCallback = true,
IsEnabled = true,
HintText = "Jetzt Speichern"
};
formModel.AddButton(okButton);
Im Folgenden eine Übersicht möglicher Parameter.
ButtonId
Die ID des Buttons.Caption
Die Beschriftung des Buttons.ServerCallback
Gibt es ein Server-CallbackFunctionName
Der Name (mit Pfad) der Client-Action.
Nur wenn es kein Server-Callback ist.IsEnabled
Optional: Soll der Button aktiv sein (Vorgabe:true
)HintText
Optional: Hinweistext / Tooltip wenn die Maus über dem Button ist.
HandleAction
In HandleAction
werden die Buttons verarbeitet, die auf serverCallback=true
stehen. Per Default wird der Dialog geschlossen. Ein anderes Verhalten wird an dieser Stelle implementiert. In dem Beispiel wird das Feld TextEdit
validiert und eine entsprechende Fehlermeldung ausgegeben.
public override DialogResultModel HandleAction(HttpRequestBase request, ModelStateDictionary modelState, Dictionary<String, Object> parameter, String buttonId, object bindObject, string propertyPrefix = "")
{
DialogResultModel result = base.HandleAction(request, modelState, parameter, buttonId, bindObject, propertyPrefix);
if (buttonId == DialogButtonIds.OkButton)
{
MyDialogModel dlgData = (MyDialogModel)bindObject;
if (String.IsNullOrWhiteSpace(dlgData.TextEdit))
{
result.Message = "Es ist ein Fehler aufgetreten!";
result.MessageType = EnumToastNotificationType.Error;
result.InvalidFields.Add("TextEdit");
result.FieldMessages.Add("Das Textfeld ist leer.");
result.Action = "";
}
}
return result;
}
Ergebnis für den Anwender, wenn die Validierung fehlschlägt.
Browser Funktionalitäten
Werden im Browser Funktionalitäten implementiert, muss beachtet werden, dass die Maskensteuerelemente in den Dialogen mit einem Präfix versehen sind. Um den korrekten Namen eines Steuerelementes zu erhalten, steht eine entsprechende Methode im DialogManager zur Verfügung. Beispiel:
public static MyDialogButton(button: BADialogButton, evt: ASPxClientButtonClickEventArgs) {
let textBoxName: string = BA.Ui.Dialog.DialogManager.GetDialogControlName(button, "TextEdit");
if (window[textBoxName]) {
let box: BAClientTextBox = <BAClientTextBox>window[textBoxName];
box.SetValue("Neuer Wert");
}
}
Höhe und Breite / Adaptives Layout
Das Prinzip in der Darstellung der Dialoge basiert auf einer vorgegebenen Breite und einer automatisch berechneten Höhe. Die Standardbreite eines Dialoges ist 600 Pixel. Bei der Implementierung sollte man für seinen Dialog die entsprechende Breite angeben.
formModel.Width = 600;
Die Höhe wird anschließend von dem System automatisch berechnet. Alternativ kann man die Höhe ebenfalls definieren.
Das Framework der Maskensteuerelemente unterstützt das Adaptive Layout von DevExpress. Siehe dazu auch die DevExpress Online Dokumentation. Folgende Screenshots desselben Dialoges mit unterschiedlichen Breiten verdeutlichen die Möglichkeiten.
Breiter Dialog (Zweispaltig / Labels vor dem Feld)
Mittlerer Dialog (Zweispaltig / Labels über dem Feld)
Schmaler Dialog (Einspaltig / Labels über dem Feld)
Basis ist ein LayoutPanelControl
. Beispiel
LayoutPanelControl layout = new LayoutPanelControl()
{
Id = "DEB77CD6-1823-445F-A70D-A0E6001E4351".ToGuid(),
ColumnCount = 2,
WrapContentAtWidth = 500,
StretchLastItem = true,
};
layout.AddBreakpoint(new BreakpointRule() { Name = "S", ColumnCount = 1, MaxWidth = 700 });
layout.AddBreakpoint(new BreakpointRule() { Name = "M", ColumnCount = 2, MaxWidth = 1000 });
Bei den Steuerelementen wird dann jeweils deren Verhalten definiert.
TextEditControl textControl = new TextEditControl()
{
Id = "4095021E-6762-4894-8B42-9164EBC1281F".ToGuid(),
Caption = "Text",
OrmFieldName = "TextEdit",
ColSpan = 2,
};
textControl.AddSpanRule((new SpanRule() { BreakpointName = "S", ColumnSpan = 1 });
textControl.AddSpanRule((new SpanRule() { BreakpointName = "M", ColumnSpan = 2 });
Bei Gruppenelementen legt man sowohl die Breakpoints für die Gruppe als auch die eigenen Spanrules fest.
var group = new GroupControl
{
Id = "E398BFE6-202D-4F14-9B09-FE059B314E2A".ToGuid(),
Caption = "",
WrapContentAtWidth = 500,
StretchLastItem = true,
ColumnCount = 2
};
group.AddBreakpoint(new BreakpointRule() { Name = "S", ColumnCount = 1, MaxWidth = 300 });
group.AddBreakpoint(new BreakpointRule() { Name = "M", ColumnCount = 2, MaxWidth = 500 });
group.AddSpanRule(new SpanRule() { BreakpointName = "S", ColumnSpan = 1 });
group.AddSpanRule(new SpanRule() { BreakpointName = "M", ColumnSpan = 2 });
Maskensteuerelemente für Dialoge
In eigenen Dialogen können alle Maskensteuerelemente genutzt werden, die das Attribut [EnabledForFreeDialogs]
haben. Es können in der Regel die Steuerelemente nicht genutzt werden, die zwingend einen Datensatz erfordern. Beispielsweise sind das Relationsauswahlelemente.
Werden eigene Maskensteuerelemente implementiert und sollen diese in eigenen Dialogen genutzt werden, müssen sie mit dem Attribut [EnabledForFreeDialogs]
versehen werden.
Aufruf
Der Aufruf eines Dialoges erfolgt über den DialogManager
BA.Ui.Dialog.DialogManager.OpenDialog(
"BA.Customer.Project.MyDialog ", // Dialog Identifier
{ "para1": "Wert" }, // Parameterobjekt
customData, // CustomData Objekt. Wird 1 zu 1 an die resultFunc übergeben
resultFunc // Function die beim Beenden des Dialoges aufgerufen wird
);
Signatur der Ergebnisfunktion
function (result: BA.Ui.Dialog.DialogResult, customData: CustomData) { }
Standarddialoge modifizieren
Unter Umständen ist es notwendig das Verhalten eines Standarddialoges zu modifizieren. Dies birgt immense Risiken und sollte nur sehr bedacht getan werden. Auch sollte nach jedem Update diese Anpassung kontrolliert werden, da Änderungen an den Standarddialogen nicht kommuniziert werden.
Zwei Methoden können überschrieben werden, um in abgeleiteten Dialogen Änderungen an den erstellten Controls und an den erstellten MVCxFormLayoutItems
zu machen:
void AfterContentCreated(DevExFormModel formModel, HttpRequestBase request, ModelStateDictionary modelState, Dictionary<string, object> parameter, object bindObject)
Abfolge ist:
CreateDialogContent
- Übernahme von
formModel.DataSource
als bindObject AfterContentCreated
Das bedeutet, dass man in AfterContentCreated
Änderungen an this.Controls
durchführen kann, bevor die Controls in MVCx-Items umgewandelt werden.
Theoretisch erfüllt ein Überschreiben von CreateDialogContent
mit Aufruf von base.CreateDialogContent
den gleichen Zweck, man spart sich bei der Verwendung von AfterContentCreated
allerdings, dass man an den base-Aufruf denken muss, d.h. AfterContentCreated
ist die offizielle Schnittstelle, um Änderungen an den vom Dialog erstellten Controls zu machen.
void AfterControlsRendered(DevExFormModel formModel, HttpRequestBase request)
Hier können Änderungen an den umgewandelten MVCx-Items gemacht werden.
Diese finden sich unter formModel.LayoutPanels
(Liste von DevExFormPartModel
) und sind nach ihrer Hierarchie angeordnet (d.h. wenn man nicht weiß, nach was man wo sucht, muss man wahrscheinlich zunächst FlattenControls
bemühen müssen).