@naveenBCF Hi Naveen,
Yes, you can extend PXGraph globally, but it is highly discouraged if your goal is just to apply logic to 10 specific screens.
While doing public class MyClassExt : PXGraphExtension<PXGraph> is technically valid, here is a breakdown of why this approach is problematic, followed by the two best-practice alternatives for your scenario.
The Drawbacks of a Global PXGraph Extension
If you extend the base PXGraph, the Acumatica framework will forcefully inject your extension into every single graph instantiated across the entire ERP.
- Global Performance Penalty: Whenever a user logs in, opens a screen, runs a processing task, or triggers a REST/SOAP API call, Acumatica uses reflection to instantiate your extension and wire up its event handlers. Multiplying milliseconds across thousands of daily operations creates an unnecessary system-wide performance drag.
- Unintended Side Effects: Your logic may inadvertently fire in system processes, background threads, or integration APIs (like pushing data to the mobile app) where the cache happens to be modified. Managing concurrency, locks, and ensuring your code doesn't crash unrelated functionality becomes incredibly difficult.
Best Practice Alternatives
Instead of maintaining 10 separate, duplicated graph extensions or taking the risk of 1 global extension, you should use one of the two native Acumatica patterns below.
Alternative 1: Custom Event Subscriber Attribute (Best for Data/Field Logic)
If your custom logic is strictly tied to standard cache events (like FieldUpdated, FieldDefaulting, or RowSelected), the cleanest architectural approach is to encapsulate that logic into a custom Attribute. Attributes automatically execute their logic on any screen that uses the DAC field.
1. Create the custom Attribute code:
public class MyBusinessLogicAttribute : PXEventSubscriberAttribute, IPXFieldUpdatedSubscriber, IPXRowSelectedSubscriber
{
public void FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
// Your logic here. 'sender' is the exact cache instance
// belonging to whichever graph triggered the event.
}
public void RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
// Your UI enabling/disabling logic here
}
}
2. Attach it to your DAC extension:
[PXDBString(50)]
[PXUIField(DisplayName = "My Cross-Screen Field")]
[MyBusinessLogic] // <--- Attach your custom logic here!
public virtual string UsrMyField { get; set; }
public abstract class usrMyField : PX.Data.BQL.BqlString.Field<usrMyField> { }
Why this is great: Zero repetitive graph extensions, perfectly isolated execution, and it is highly performant.
Alternative 2: Abstract Generic Graph Extension (Best for UI & Complex Logic)
If your logic is more complex—for example, you need to add custom Actions (buttons) to all 10 screens or you need to coordinate between multiple different DACs—you should use an abstract base class.
1. Write your shared logic once in an abstract generic class:
// The base class contains all the heavy lifting
public abstract class MySharedLogicExt<TGraph> : PXGraphExtension<TGraph>
where TGraph : PXGraph
{
protected virtual void _(Events.FieldUpdated<MyDAC, MyDAC.usrMyField> e)
{
// Shared logic executed across all implementing screens
}
// You can even add shared Actions here!
public PXAction<MyDAC> MyCustomButton;
[PXButton, PXUIField(DisplayName = "Do Something")]
protected virtual IEnumerable myCustomButton(PXAdapter adapter)
{
return adapter.Get();
}
}
2. Create explicitly targeted "empty" derived extensions:
public class SOOrderEntry_SharedBaseExt : MySharedLogicExt<SOOrderEntry> { }
public class POOrderEntry_SharedBaseExt : MySharedLogicExt<POOrderEntry> { }
public class APInvoiceEntry_SharedBaseExt : MySharedLogicExt<APInvoiceEntry> { }
// ... etc. for the remaining 7 screens
Why this is great: You only write the code once, but the Acumatica framework only loads it into the 10 specific screens you explicitly declare, eliminating the global performance penalty.
Summary recommendation: Use Alternative 1 if you are just validating or defaulting data based on field changes. Use Alternative 2 if you are interacting heavily with the UI, pushing buttons, or spanning multiple Caches.