Acumatica - remove generic style vent handler - acumatica

How to remove a event handler if it is defined with generic event handler syntax..
I am not getting the syntax to remove it like we have with old style of event handler defination

Since no version was provided, this was done in 2021 R1
There isn't much information provided here but from what I believe you're asking, the means to override event handlers is very similar. Take ARInvoiceEntry as an example. There exists an event handler for the RowSelected event of ARAdjust _(Events.RowSelected<ARAdjust> e).
To override this in your graph extension you need the following method declaration:
public virtual void _(Events.RowSelected<ARAdjust> e, PXRowSelected del)
{
del?.Invoke(e.Cache, e.Args); //This line calls the core Acumatica code, if you desire to remove the call completely remove this line (or comment it out)
}

In some circumstances you need to remove the event explicitly.
There doesn't seem to be much difference from old events in Acumatica latest version. The method name convention is different and uses underscore character. The event handler needs a public or protected access modifier to be referenced.
public class UserProfileMaintExt : PXGraphExtension<MyProfileMaint>
{
public override void Initialize()
{
Base.RowSelected.RemoveHandler<Users>(_);
}
protected virtual void _(Events.RowSelected<Users> e)
{
}
}

We are getting error -
can not convert from 'method group' to 'pxrowupdated

Related

Acuminator gives warnings when using bql queries in rowselected/Initialize events, where to use them?

I'm using the userLoginType and the userRoles to enable/disable some fields in my Row_Selected events, but using Acuminator https://github.com/Acumatica/Acuminator I get the PX1049 warning : https://github.com/Acumatica/Acuminator/blob/dev/docs/diagnostics/PX1049.md
my code is the following :
public class OpportunityMaintExt : PXGraphExtension<OpportunityMaint>
{
public PXSelectJoin<EPLoginType, InnerJoin<Users, On<Users.loginTypeID, Equal<EPLoginType.loginTypeID>>>,
Where<Users.pKID, Equal<Current<AccessInfo.userID>>>> userLoginType;
public PXSelect<Contact, Where<Contact.userID, Equal<Current<AccessInfo.userID>>>> userContact;
public PXSelect<UsersInRoles, Where<UsersInRoles.username, Equal<Current<AccessInfo.userName>>>> userRoles;
public string userLoginTypeName;
protected virtual void CROpportunity_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
CROpportunity o = e.Row as CROpportunity;
CROpportunityExt myOpp = sender.GetExtension<CROpportunityExt>(sender.Current);
userLoginTypeName = TRLoginInfo.getCurrentUserLoginType(userLoginType.SelectSingle(), userRoles);
enabledisablefields();
}
The problem is with the userLoginType.SelectSingle(), the Acuminator tells me that : "In Rowselected Handler, bql and databasequeries should be avoided". But If I place this in Initialize() it gives the same warning.
So, where am I supposed to put these bql/database queries If I want them to be processed when I watch a record ?
Thanks a lot !
Ideally - you should fire your BQL in the RowSelecting Event within a new PXConnectionScope (BQL within RowSelecting Events MUST be done within a new PXConnectionScope to prevent issues), assign non-db-backed fields within your DAC Extension, then use their values in your RowSelected Event to determine whether or not certain fields should be enabled.

Acumatica - Remove RowSelected Event for Service Order Screen

I would like to override the standard method of the RowSelected event on the Service Orders screen. Specifically, the DocDesc field gets populated when you select a row item for the Labor tab. It will set the TranDesc to the DocDesc and I would like to keep this from happening. I am using Acumatica 6.1 which means that the Service Management Module is not standard in Acumatica during this time. I would like the method that populates this field to not run when the labor line is populated, so the DocDesc field would remain null or blank, this way the user can input their own description.
You should be able to customize the ServiceOrderEntry graph like any other graph :
protected virtual void FSServiceOrder_RowSelected(PXCache sender, PXRowSelectedEventArgs e, PXRowSelected bs)
{
...
}
See https://help.acumatica.com/(W(3))/Main?ScreenId=ShowWiki&pageid=4a05d4c2-cd8b-4131-bf3b-d05861de3ae6
You could override the method if it is virtual, like this :
public delegate void PersistDelegate();
[PXOverride]
public void Persist(PersistDelegate baseMethod)
{
...
baseMethod();
...
}
See https://help.acumatica.com/(W(3))/Main?ScreenId=ShowWiki&pageid=635c830e-4617-4d5c-9fa5-035952311aa9
You could also modify the base customization, but since you are not the owner it could get difficult to maintain and track the changes.

How can I execute code from the Release / Release All buttons in the Release AR Documents screen

I've got a customization to the Invoice & Memo screen where I execute some custom code (web service calls) when the Release action is activated. This works fine - I knew how to replace the PXAction code and proceeded from there. Now I want to use the Release AR Documents processing screen to do the same thing, but I'm having trouble understanding where / what to override, or where to place my code.
I see the ARDocumentRelease graph constructor with the SetProcessDelegate in the source code, but I'm not sure how to proceed - whether this is where I need to be looking or not. I need to execute my code for each line being released, using the RefNbr in my code.
Since it's an static method, you can't override it. Also, you can't do like it's done in the T300, because you are in processing graph and you can't override the release button with your own. I was able to achieve it by passing callback for each AR document that have been processed.
You can call the Initialize method of the ARDocumentRelease graph to override the logic like you said. After you just have to call ReleaseDoc that uses a callback parameter instead of using the default one.
Here's the code that I came with:
public class ARDocumentRelease_Extension : PXGraphExtension<ARDocumentRelease>
{
public override void Initialize()
{
ARSetup setup = Base.arsetup.Current;
Base.ARDocumentList.SetProcessDelegate(
delegate (List<BalancedARDocument> list)
{
List<ARRegister> newlist = new List<ARRegister>(list.Count);
foreach (BalancedARDocument doc in list)
{
newlist.Add(doc);
}
AddAdditionalLogicToRelease(newlist);
}
);
Base.ARDocumentList.SetProcessCaption("Release");
Base.ARDocumentList.SetProcessAllCaption("Release All");
}
public delegate void PostPorcessing(ARRegister ardoc, bool isAborted);
private void AddAdditionalLogicToRelease(List<ARRegister> newlist)
{
ARDocumentRelease.ReleaseDoc(newlist, true, null, delegate(ARRegister ardoc, bool isAborted) {
//Add your logic to handle each document
//Test to check if it was not aborted
});
}
}
Please note that you must always call static methods from within long running process and create necessary objects there.
Processing delegate logic is implemented as long running process which creates worker thread to execute the processing logic.
You have AddAdditionalLogicToRelease() method which requires object instance in order to call and will fail during thread context switches and hence the issue. So, you must have create object instance inside the thread context and then call instance method.
In general, method that gets called from long running processes are declared static and required objects/graphs are created inside this static method to do some work. See below example how to properly override ARDocumentRelease graph for this purpose:
public class ARDocumentRelease_Extension : PXGraphExtension<ARDocumentRelease>
{
public override void Initialize()
{
Base.ARDocumentList.SetProcessDelegate(
delegate (List<BalancedARDocument> list)
{
List<ARRegister> newlist = new List<ARRegister>(list.Count);
foreach (BalancedARDocument doc in list)
{
newlist.Add(doc);
}
// use override that allows to specify onsuccess routine
ARDocumentRelease.ReleaseDoc(newlist, true, null, (ardoc, isAborted) =>
{
//Custom code here, such as create your GL
});
}
);
}
}
I think it's the function
public static void ReleaseDoc(List<ARRegister> list, bool isMassProcess, List<Batch> externalPostList, ARMassProcessDelegate onsuccess)
under ARDocumentRelease businesss logic.

Monotouch - Getting notified when network status changed

I'm familiar with the "reachability" class to check if there is an internet connection:
https://github.com/xamarin/monotouch-samples/blob/master/ReachabilitySample/reachability.cs
I was now wondering if there is any way to get notified when the Network status has changed?
Let's say that my collection is loaded when there is no internet. The images will not get loaded. I would like to trigger the download again if the iPad suddenly gets internet connection again.
In the reachability class, I see following code:
public static event EventHandler ReachabilityChanged;
static void OnChange (NetworkReachabilityFlags flags)
{
var h = ReachabilityChanged;
if (h != null)
h (null, EventArgs.Empty);
}
However, if I set a breakpoint in the "OnChange" method, it's not called when I switch off Wifi.
Any ideas?
Regards, Matt
Ok, I should have find the answer myself actually.
You should call following functions first before you will be notified:
Reachability.InternetConnectionStatus ();
Reachability.LocalWifiConnectionStatus ();
Reachability.RemoteHostStatus ();
Calling these 3 static function calls will initialize all the necessary objects. Those 3 objects will get notified when there is a change and call "OnChange" in the Reachability call (which notifies your Event Handler).
(off course, even better is to create a special function which initialize all the needed objects so you don't need to call these 3 functions as they will really test the network connection already)
You should be able to simply add an event handler to the ReachabilityChanged event, something like (the not test compiled);
Reachability.ReachabilityChanged += c_ReachabilityChanged;
static void c_ReachabilityChanged(object sender, EventArgs e)
{
Console.WriteLine("Here I can handle that network reachability changed.");
}
Just calling this would work, can be written in AppDelegate
Reachability.RemoteHostStatus ();
Reachability.ReachabilityChanged += ReachabilityChanged;
static void ReachabilityChanged(object sender, EventArgs e){//Do Something};

DNN 5 - Can't get current ModuleId from nested user control in custom module

I'm writing a custom module for DNN 5, and I need a "Manage" link to be on every control in the module. I created a new UserControl ("ManagerLink") that inherits from PortalModuleBase, put my link into that control, and dropped that control on ALL OF MY MAIN CONTROLS.
The problem is that ModuleId and TabId are always -1 in "ManagerLink" nested control. PortalId works just fine, and I can get a TabId by doing PortalSettings.ActiveTab.TabID.
Why can't I get ModuleId and TabId in from "ManagerLink" control, even though it inherits from PortalModuleBase?
Is there an alternative method to get ModuleId (equivalent of PortalSettings.ActiveTab.TabID)
UPDATE 2014:
Just saw another answer that's way better than the original (and accepted it).
If you're using DNN 6 and earlier, replace ModuleBase with PortalModuleBase
William Severance from DNN forum answered this one for me, I'll post the answer here as well.
Since the child control inherits from PortalModuleBase, I would do the
following in the Page_Load handler of
the parent control
Note: ManagerLink is assumed to be a reference to the child control
VB.NET:
With ManagerLink
.ModuleConfiguration = Me.ModuleConfiguration
.LocalResourceFile = Me.LocalResourceFile
End With
C#:
protected void Page_Load(System.Object sender, System.EventArgs e)
{
ManagerLink.ModuleConfiguration = this.ModuleConfiguration;
ManagerLink.LocalResourceFile = this.LocalResourceFile
}
The above allows the child control to use the parent's ModuleConfiguration (which will include ModuleId) and LocalResourceFile for any localization.
I just wanted to add my 2 cents here, using the answer of #roman-m and extending on it,
I was able to do it in the nested control itself like so:
//fires first in the sequence, calling initialise components
override protected void OnInit(EventArgs e)
{
InitializeComponent();
base.OnInit(e);
}
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
//this binds a handler to the parent's init event
this.Parent.Init += new EventHandler(this.Parent_Init);
}
//the handler gets called, at this point we can cast the parent as a module base
//and load the configuration and resource file into the nested control
private void Parent_Init(object sender, System.EventArgs e)
{
this.ModuleConfiguration = ((ModuleBase)this.Parent).ModuleConfiguration;
this.LocalResourceFile = ((ModuleBase)this.Parent).LocalResourceFile;
}
This means that in the Page_Load event of the nested control it will already have the configuration and local resource file on hand.
It also means you don't have to load the configuration and local resource file in on every parent control which uses the child control.
This will only work when the parent is of type ModuleBase of course
And to be even more specific, this works in version 7.00.06

Resources