Im Standard von Microsoft Dynamics AX besteht auf jeder Maske, auf der Artikel und deren Lagerdimensionen angezeigt werden, die Möglichkeit, die Lagerdimensionen, bzw. die angezeigten Felder der Lagerdimensionen, über die Funktion "Lager-Dimensionenanzeige" entsprechend zu steuern.
Die einzelnen Elemente (Felder) der Lagerdimension können über diese Funktion ein- bzw. ausgebledet werden.
Weiterhin ist es auch möglich, durch Parametrisierung zu bestimmen, ob ein Feld einer Lagerdimension eingeben werden muss (Mussfeld) oder ob überhaupt eine Eingabe möglich ist.
Ein gutes Beispiel hierfür ist die Maske "Aufträge".
Wie ist es nun, wenn eine neue Maske erstellt werden soll, welche Artikelinformation und Lagerdimensionen anzeigen soll?
Wie genau muss vorgegangen werden, um die bereits an vielen Stellen im Standard verwendete Funktionalität auch für die selbst erstellte Maske bereitzustellen?
Gehen wir einmal davon aus, es wurde eine neue Tabelle erstellt, welche die Artikelnummer (ItemId) und die Lagerdimensionsnummer (InventDimId) speichert.
Für diese Tabelle soll eine Maske erstellt werden, úm dem Benutzer die Möglichkeit zu geben, Datensätze zu erfassen, zu ändern oder einfach nur anzuzeigen.
Dies könnte z.B. so aussehen:

Um nun die Funktion der Lagerdimensionensteuerung einzubauen muss zuerst die Tabelle InventDim als DataSource der Maske hinzugefügt werden.
Anschließend müssen die Eigenschaften (Properties) der DataSource noch auf folgende Werte geändert werden.
|
Name |
InventDim |
|
JoinSource |
Haupt-Datenquelle (hier: AKUDemoTable) |
|
LinkType |
InnerJoin |
|
DelayActive |
No |
|
InsertAtEnd |
No |
|
InsertIfEmpty |
No |

Nun muss eine neue ButtonGroup (Name: "Inventory") im Designzweig der Maske erstellt werden. Diese sollte das LAbel "Lager" zugewiesen werden.
Nun noch das MenuItem "InventDimParmFixed" in diese ButtonGroup ziehen (z.B. per drag & drop aus dem AOT) und dem so erstellten MenuItemButton folgende Eigenschaften zuweisen.
|
Name |
InventDimParmFixed |
|
MenuItemName |
InventDimParmFixed |
|
DataSource |
Haupt-Datenquelle (hier: AKUDemoTable) |

Über das MenuItem (oder genauer über den erstellten MenuItemButton) wird nun wie im Standard, die Maske "Lagerdimensionen" zu öffnen.

Allerdings öffnet sich die Maske „Lagerdimensionen“ noch nicht wie gewünscht über den MenuItemButton. Hierfür sind noch weitere Anpassungen notwendig.
Damit sich die Maske „Lagerdimensionen“ wie gewünscht öffnet muss die neue Maske die Methode „inventDimSetupObject“ implementieren welche eine Instanz von „InventDimCtrl_Frm“ zurück gibt.
Die Klasse „InventDimCtrl_Frm“, bzw. eine der von ihr abgeleiteten Klassen, steuert z.B. welche Lagerdimensionen für den aktuellen Datensatz zulässig sind oder welche Dimensionen für den aktuellen Datensatz angegeben werden müssen, damit dieser gespeichert werden kann.
Da über die Parametrisierung der Lagersteuerungsgruppen und der Modulparameter hierfür durchaus unterschiedliche Einstellungen gewählt werden können, sind in Dynamics AX etliche Ableitungen dieser Klasse vorhanden (jede wird für eine oder mehrere andere Masken verwendet).

Je nachdem, was für eine Funktionalität bzw. was für ein Business-Prozess erstellt werden soll, kann entweder eine der bereits im Standard vorhandenen Klassen verwendet werden oder es muss eine neue Klasse geschrieben werden, um die benötigte Funktionalität zu liefern (z.B. welche Dimensionen immer angezeigt werden müssen).
Das Erstellen einer neuen Klasse, welche von „InventDimCtrl_Frm“ abgeleitet ist, ist recht einfach.
Es sollte immer die Methode „new“ überschrieben werden und mindestens die statischen Methoden „construct“ und „newFromForm“ erstellt werden.
class AKUInventDimCtrl_Frm_Demo extends InventDimCtrl_Frm
{
}
protected void new()
{
super();
}
public static AKUInventDimCtrl_Frm_Demo construct()
{
return new AKUInventDimCtrl_Frm_Demo();
}
static AKUInventDimCtrl_Frm_Demo newFromForm(FormRun _formRun)
{
AKUInventDimCtrl_Frm_Demo inventDimCtrl = AKUInventDimCtrl_Frm_Demo::construct();
InventDimAxFormAdapter adapter = InventDimAxFormAdapter::newFromForm(_formRun);
;
inventDimCtrl.parmCallingElement(adapter);
inventDimCtrl.init();
return inventDimCtrl;
}
Weiterhin können noch andere Methoden überschrieben werden, um z.B. zu steuern, welche Felder der Tabelle „InventDim“ beim Aufruf der Maske angezeigt werden sollen.
Weitere Informationen hierzu sind im Microsoft Dynamics AX Developer Center zu finden: http://msdn.microsoft.com/en-us/library/cc618009.aspx
NoYes mustShowGridField(fieldId _dimFieldId)
{
NoYes ret;
ret = super(_dimFieldId);
//always show InventLocationId in Grid
if(_dimfieldId == fieldnum(InventDim, InventLocationId))
{
ret = NoYes::Yes;
}
return ret;
}
Wie zuvor beschrieben muss nun die Methode „inventDimSetupObject“ auf der Maske implementiert werden. Das diese eine Instanz von „InventDimCtrl_Frm“ zurück geben muss, ist diese ebenfalls zu erzeugen. Als erstes muss eine Objektvariable für das „InventDimCtrl_Frm“ Objekt erstellt werden.
public class FormRun extends ObjectRun
{
InventDimCtrl_Frm inventDimFormSetup;
}
Anschließend kann die Methode „inventDimSetupObject“ erstellt werden.
Object inventDimSetupObject()
{
return inventDimFormSetup;
}
Da die Objektvariable durch diesen Quelltext noch nicht initialisiert wird, muss noch entsprechender Code zur Initialisierung geschrieben werden.
void updateDesign(InventDimFormDesignUpdate mode)
{
inventDimParm inventDimParmShow;
inventDimParm inventDimParmEnabled;
;
switch (mode)
{
case InventDimFormDesignUpdate::Init :
if (!inventDimFormSetup)
{
inventDimFormSetup = AKUInventDimCtrl_Frm_Demo::newFromForm(element);
}
inventDimFormSetup.parmSkipOnHandLookUp(true);
case InventDimFormDesignUpdate::Active :
inventDimFormSetup.formActiveSetup(
inventTable::find(AKUDemoTable.ItemId).dimGroupId);
inventDimFormSetup.formSetControls(true);
break;
case InventDimFormDesignUpdate::FieldChange :
inventDimFormSetup.formActiveSetup(
inventTable::find(AKUDemoTable.ItemId).dimGroupId);
inventDim.clearNotSelectedDim(inventDimFormSetup.parmDimParmEnabled());
inventDimFormSetup.formSetControls(true);
break;
default :
throw error(strfmt("@SYS54195",funcname()));
}
}
public void init()
{
;
super();
element.updateDesign(InventDimFormDesignUpdate::Init);
}
Da die Logik, welche durch die Methode „updateDesign“ bereit gestellt wird, mehrfach benötigt wird, erfolgt die Initialisierung des „InventDimCtrl_Frm“ Objekts nicht direkt in der „init“ Methode.
Damit die in der Maske erstellten Datensätze auch richtig gespeichert werden können, müssen nun noch einige weitere Anpassungen an den Methoden der Datenquellen vorgenommen werden.
Datasource „AKUDemoTable“ (Hauptdatenquelle):
Hier sind die Methoden „write“, „validateWrite“ und „active“ zu überschreiben.
public void write()
{
;
ttsbegin;
AKUDemoTable.inventDimId = InventDim::findOrCreate(InventDim).inventDimId;
super();
if(AKUDemoTable.inventDimId != InventDim.inventDimId)
{
InventDim.data(InventDim::find(AKUDemoTable.inventDimId));
InventDim_ds.setCurrent();
}
ttscommit;
}
public boolean validateWrite()
{
boolean ret;
;
AKUDemoTable.InventDimId = inventDim::findOrCreate(InventDim).inventDimId;
ret = super();
return ret;
}
int active()
{
int ret;
;
ret = super();
element.updateDesign(InventDimFormDesignUpdate::Active);
inventDim_DS.active();
return ret;
}
Datasource „InventDim“:
Hier müssen die Methoden „initValue“ und „write“ überschrieben werden.
public void initValue()
{
;
InventDim.data(InventDim::find(AKUDemoTable.inventDimId));
super();
}
public void write()
{
//super();
}
Hierbei muss unbedingt beachtet werden, dass der „super“ Aufruf in der „write“ Methode der Datasource „InventDim“ auskommentiert wird, um das Speichern von falschen InventDim Datensätzen zu verhindern.
Als letzte Methode sollte nun noch die Methode „modified“ des DataSource-Field „ItemId“ der Datasource „AKUDemoTable“ überschrieben werden, damit auf eine Änderung der Artikelnummer reagiert werden kann (z.B. Artikelabhängige Anzeige der Lagerdimensionen).
public void modified()
{
;
super();
element.updateDesign(InventDimFormDesignUpdate::FieldChange);
}
Somit sind alle benötigten Quelltextanpassungen durchgeführt, sodass nur noch die Feldgruppe „InventoryDimensions“ der DataSource „InventDim“ mit in das Grid gezogen werden muss um die Lagerdimensionen auf der Maske anzuzeigen. Optional kann diese auch in die TabPage „Dimensions“ gezogen werden um ein standardkonformes Aussehen der Maske zu erhalten.

Das vorgestellt Bespiel steht hier als Download bereit um die einzelnen Schritte genau ansehen/nachvollziehen zu können.
AKU_Demo_InventDimFrm.rar (2,71 KB)