Sometimes, you need to override one or more attributes of a particular Data Access Class (DAC) field just for a particular screen, without changing the existing behavior for other screens.
Suppose the original DAC field attributes are declared as shown below:
public class ARInvoice : IBqlTable
{
[PXDBDecimal(4)]
[PXDefault(TypeCode.Decimal, "0.0")]
[PXUIField(DisplayName = "Commission Amount")]
public virtual Decimal? CommnAmt
{
get;
set;
}
}
The basic way to override the field's attributes in the graph is to declare a CacheAttached
event handler in the graph that follows the standard convention for naming graph events (note the absence of the EventArgs argument). The body of the event handler will not be executed, but any attributes that you place on the handler will replace the attributes on the corresponding DAC field:
[PXDBDecimal(4)]
[PXDefault(TypeCode.Decimal, "0.0")]
[PXUIField(DisplayName = "Commission Amount")]
[PXAdditionalAttribute(NecessaryProperty = true)]
protected virtual void ARInvoice_CommnAmt_CacheAttached(PXCache sender) { }
The set of attributes placed on the CacheAttached handler will redefine the whole set of the attributes placed on the field in the DAC. This is almost always overkill; note how in the previous example, in order to add just a single attribute to the field, you had to copy all other attribute declarations from the DAC. This leads to undesired code duplication, as well as the possibility of DAC and the graph going out of sync. It is very easy to imagine a situation when someone changes the defaulting logic of, for instance, PXDefaultAttribute
in the DAC, but forgets to update all the corresponding attributes placed on the CacheAttached
handlers in various graphs.
To remedy this problem, the Acumatica Framework provides a special attribute called PXMergeAttributesAttribute
. When this attribute is placed on a CacheAttached
handler, you can reuse the existing attributes defined in the DAC.
Appending an attribute using PXMergeAttributesAttribute
:
[PXMergeAttributes(Method = MergeMethod.Append)]
[PXAdditionalAttribute(NecessaryProperty = true)]
protected virtual void ARInvoice_CommnAmt_CacheAttached(PXCache sender) { }
In the above example, the whole set of attributes from the original DAC will be reused, appended by any attributes that you have declared on the CacheAttached
event handler.
PXMergeAttributesAttribute
has other merge behaviours, according to the following possible values for the Method property:
MergeMethod.Replace
replaces the DAC's attributes completely (equivalent to the absence of PXMergeAttributesAttribute
).MergeMethod.Append
appends the attributes from the CacheAttached
handler to the original DAC attributes.MergeMethod.Merge
is similar to Append
; however, it also checks whether there are any conflicting attributes between the handler attributes and the DAC field attributes. If there is a conflict, the CacheAttached
attribute takes precedence and the corresponding DAC attribute is discarded.A very common application development scenario occurs when you have to redefine just a single property of a DAC's attribute for a particular screen; consider the situation when you have to define the DisplayName
property of the PXUIFieldAttribute.
For that purpose, you can use yet another special attribute provided by the Acumatica Framework: PXCustomizeBaseAttributeAttribute
. Its constructor accepts three values:
nameof
operator in C# 6.0 for code maintainability)Suppose that there is a requirement to change the UI display name from Commission Amount to Base Currency Commission for only one screen. The following code example demonstrates how to implement the desired behavior.
[PXMergeAttributes(Method = MergeMethod.Append)]
[PXCustomizeBaseAttribute(typeof(PXUIFieldAttribute), nameof(PXUIFieldAttribute.DisplayName), "Base Currency Commission")]
protected virtual void ARInvoice_CommnAmt_CacheAttached(PXCache sender) { }
In this example, PXMergeAttributes
ensures that the original DAC attributes are preserved, and PXCustomizeBaseAttribute
allows the software engineer to override the UI field's display name for the graph in question.
Suppose that there is a requirement to replace a DAC field's PXDefaultAttribute
with PXDBDefaultAttribute
for only one screen.
This can be achieved in the following manner:
[PXMergeAttributes(Method = MergeMethod.Append)]
[PXRemoveBaseAttribute(typeof(PXDefaultAttribute))]
[PXDBDefault(typeof(SOShipment.siteID), PersistingCheck = PXPersistingCheck.Nothing)]
protected void SOOrderShipment_SiteID_CacheAttached(PXCache sender) { }
PXCustomizeBaseAttribute
PXRemoveBaseAttribute
PXMergeAttributes