I've been programming in acumatica for a year, but I still can't quite understand how certain things work. For example, how the graphs work in the following code, logic is being added, however, I do not understand how the information is passed to the next page if this logic is added before the base method. I have read the documentation but I still do not understand somethimes, do you know where I can find better information?
public delegate IEnumerable createSalesOrder(PXAdapter adapter);
[PXOverride]
public virtual IEnumerable CreateSalesOrder(PXAdapter adapter, createSalesOrder baseMethod)
{
PXTrace.WriteInformation("try ");
PXGraph.InstanceCreated.AddHandler<SOOrderEntry>((graph) =>
{
graph.RowInserted.AddHandler<SOOrder>((sender, e) =>
{
SOOrder order = (SOOrder)e.Row;
SOOrderExt orderExt = PXCache<SOOrder>.GetExtension<SOOrderExt>(order);
orderExt.UsrCustomOne = "Howdy"; //assign anything you want here*/
});
});
return baseMethod(adapter);
}
It is obvious that an eventhandler is being added to an instance of a graph but how does it specifically pass that information to the next object that is being created within the base method or how is it that it adds this logic to the new SOORDER
CodePudding user response:
Your example is adding an event handler before the base method is called. During execution, Acumatica creates a composite of the base elements with the defined extensions. Since you have overriden a base method, your method is called via the delegate, for which you then must tell C# if/when to execute the base code. You could call baseMethod.Invoke(adapter) at the beginning of this code if you need your code to execute afterwards, but in this case you specifically told C# to execute your code and then run the base method.
Unless your approach was included in either very old training material or very new training material, your way of adding an event handler is a little foreign to me. I've seen something similar in standard code, but it doesn't seem common. The only instance I recall is where I was advised to inject an event handler in my code for a different standard graph that needs to do something only when my graph is used but not when the standard screen is executing the graph code. I'm not sure if the event handler itself is removed automatically at the end of your method or if it is instantiated every time you execute that method as I don't use your approach.
Regardless, what happens in your example is that the event handler is added before the base method is invoked because you told it to create the event handler when the method is invoked, and the delegate causes your override to execute first. The base method is called at the end, but only because you said to do so. Had you not specifically told C# to execute the base method, the delegate would have made your code execute and never run the base code. Simply put, it's in the mechanics of a delegate/override.
The way I was trained to add the event handler like this...
using PX.Data;
using PX.Objects.SO;
namespace Blog
{
public class SOOrderEntryExt : PXGraphExtension<SOOrderEntry>
{
public static bool IsActive() =>
Common.FeatureInstalled<Common.CMMSFeaturesSet.main>();
protected virtual void _(Events.RowInserted<SOOrder> e, PXRowInserted baseEvent)
{
SOOrder order = (SOOrder)e.Row;
SOOrderExt orderExt = PXCache<SOOrder>.GetExtension<SOOrderExt>(order);
orderExt.UsrCustomOne = "Howdy"; //assign anything you want here*/
if (baseEvent != null) baseEvent.Invoke(e.Cache, e.Args);
}
}
}
By defining it directly in the graph extension, it is initialized with the graph extension which ensures the event will fire anytime a row is inserted. I suspect your code either fires only when the method is executed or creates multiple instances of the event with every time the method is called. Again, I'm just not too familiar with how adding the event handler your way is scoped.
Assuming your method of adding the event handler scopes it to the method where it was added, it would not execute unless the Sales Order is created via the specific method. If it is persistent for the graph once it has been added, then any other method of adding the SOOrder on insert would fail to call your event handler until your method has been called to add the event handler.
CodePudding user response:
PXGraph.InstanceCreated
is a static property; you’re setting up the event handler before the graph is created.
When you call the base method (using return baseMethod(adapter)
) it will create a new instance of the SOOrderEntry
graph. During initialization of the new instance, the graph will look for any InstanceCreated
event handlers and invoke the code, which in your case will add a RowInserted
event handler to the new graph. Your InstanceCreated
handler will live for the duration of the callback.
This is the cleanest way to customize the logic when multiple graphs are involved (creation of order from opportunity, creation of shipment from order, etc…).