Overriding Attributes of a DAC Field in the Graph

You can override one or more attributes of a DAC field for a particular screen without changing the existing attribute behavior for all other screens.

You can do the following to override the attributes of a DAC field:
  • Replace the whole set of attributes
  • Append an attribute
  • Override a single property of an attribute
  • Replace one attribute with another

To override attributes, you should declare a CacheAttached event handler in the graph that corresponds to the screen for which you want to change the DAC field's behavior. With the declared CacheAttached event handler, you use special attributes, depending on what you want to do with the original attributes, as described in the following sections.

Replacing the Whole Set of Attributes

To override all attributes at once, you should only declare a CacheAttached event handler in the graph.

Suppose that the original DAC field attributes are declared as shown in the following code.
public class ARInvoice : PXBqlTable, IBqlTable
{    
    [PXDBDecimal(4)]    
    [PXDefault(TypeCode.Decimal, "0.0")]    
    [PXUIField(DisplayName = "Commission amount")]    
    public virtual Decimal? CommAmt     
    {         
        get;         
        set;     
    }
}

To override a DAC field by using the CacheAttached event handler, in the graph corresponding to the screen whose behavior you want to change, declare the CacheAttached event handler for the field. The event handler must be named according to the standard conventions for naming graph events, which are described in the Types of Graph Event Handlers topic.

For the CommAmt field, the code for the event handler looks like the following.
[PXDBDecimal(4)]
[PXDefault(TypeCode.Decimal, "0.0")]
[PXUIField(DisplayName = "Commission Amount")]
[PXAdditionalAttribute(NecessaryProperty = true)]
protected virtual void _(Events.CacheAttached<ARInvoice.commAmt> e) { }

In this example, we’ve added the PXAdditionalAttribute to the list of the CommAmt field attributes.

The set of attributes on the CacheAttached handler redefines the whole set of attributes placed on the specified DAC field. This results in undesired copying of all unmodified attributes, and the DAC and the graph no longer act synchronously. Therefore, we do not recommend using this method unless you intend to override all attributes of a field.

Appending an Attribute

MYOB Acumatica Framework provides a special attribute called PXMergeAttributes. When placed on a CacheAttached event handler for the corresponding DAC field, this attribute gives you the ability to reuse the existing attributes of a DAC field.

To append an attribute, you declare the CacheAttached event handler with the PXMergeAttributes attribute and the new attribute (or attributes), as shown in the following code.

[PXMergeAttributes(Method = MergeMethod.Append)]
[PXAdditionalAttribute(NecessaryProperty = true)]
protected virtual void _(Events.CacheAttached<ARInvoice.commAmt> e) { }

This example works similarly to the previous one: It adds the PXAdditionalAttribute attribute to the list of the CommAmt field attributes, but without code duplication.

Overriding a Single or Multiple Properties of an Attribute

The MYOB Acumatica Framework provides the following strongly typed customization attributes in the PXCustomize static class that give you the ability to redefine one or more properties of their target attributes:

Tip: You can use the strongly typed customization attributes described in the list above to customize the descendants of their target attributes. For example, you can use the PXCustomize.PXDBFieldAttributeAttribute attribute to customize the PXDBIntAttribute and PXDBStringAttribute attributes, which are descendants of the PXDBFieldAttribute attribute.

The framework also provides PXCustomize.AnyAttributeAttribute. This attribute can be used to customize any attribute derived from the PXEventSubscriberAttribute attribute. It works similarly to the deprecated PXCustomizeBaseAttribute attribute.

We recommend that you:

  • Use the strongly typed customization attributes wherever they’re applicable.
  • Use the PXCustomize.AnyAttributeAttribute attribute only for cases where the strongly typed customization attributes can't be used.

To use any of the strongly typed customization attributes or the PXCustomize.AnyAttributeAttribute attribute, you place the attribute on a CacheAttached event handler for the corresponding DAC field.

For example, suppose that you need to change the UI display name from Commission Amount to Base Commission for only one screen. In this case, we recommend that you use the strongly typed PXCustomize.PXUIFieldAttributeAttribute attribute to customize the DisplayName property of the PXUIFieldAttribute attribute for the corresponding DAC field, as shown below.

[PXCustomize.PXUIFieldAttribute(DisplayName = "Base Commission")]
protected virtual void _(Events.CacheAttached<ARInvoice.commAmt> e) { }
Tip: The double Attribute suffix (such as PXCustomize.PXUIFieldAttributeAttribute in the example above) is dropped from the name of the customization attribute when you use it in code. The dropping of the suffix is intentional because it makes it easy for you to recognize the attribute that the customization attribute is targeting because it mirrors the name of the targeted attribute.

The example above redefines the PXUIFieldAttribute attribute by using the PXCustomize.PXUIFieldAttributeAttribute attribute.

You can also redefine multiple properties of an attribute by using a single instance of a strongly typed customization attribute. Suppose that for the previous code example, you also need to set the Enabled property to true for the PXUIFieldAttribute attribute. The following code shows this addition.

[PXCustomize.PXUIFieldAttribute(DisplayName = "Base Commission", Enabled = true)]
protected virtual void _(Events.CacheAttached<ARInvoice.commAmt> e) { }

Although we recommend that you use strongly typed customization attributes wherever possible, you can technically use the PXCustomize.AnyAttributeAttribute attribute to customize the same attributes that are customized by strongly typed customization attributes. In the case of the preceding code example, which used the PXCustomize.PXUIFieldAttributeAttribute attribute, this looks like the following.

[PXCustomize.AnyAttribute(typeof(PXUIFieldAttribute), 
  nameof(PXUIFieldAttribute.DisplayName), "Base Commission")]
protected virtual void _(Events.CacheAttached<ARInvoice.commAmt> e) { }

Note that when you use PXCustomize.AnyAttributeAttribute, you need to specify the type of the attribute that you want to customize as a separate parameter, along with the property to be updated and its new value. Also, if you intend to redefine multiple properties of an attribute, you need to declare an instance of PXCustomize.AnyAttributeAttribute for each property. Suppose that for the previous code example, you also need to set the Enabled property to true for the PXUIFieldAttribute attribute. The complete code would look like the following when you use the PXCustomize.AnyAttributeAttribute attribute.

[PXCustomize.AnyAttribute(typeof(PXUIFieldAttribute), 
  nameof(PXUIFieldAttribute.DisplayName), "Base Commission")]
[PXCustomize.AnyAttribute(typeof(PXUIFieldAttribute), 
  nameof(PXUIFieldAttribute.Enabled), true)]
protected virtual void _(Events.CacheAttached<ARInvoice.commAmt> e) { }

Replacing One Attribute with Another

MYOB Acumatica Framework provides a special attribute called PXRemoveBaseAttribute. When placed on a CacheAttached event handler for the corresponding DAC field, this attribute gives you the ability to remove the specified attribute.

For example, suppose that you need to replace PXDefaultAttribute with PXDBDefaultAttribute for only one screen. Further suppose that the original field declaration looks the one shown in the following code.

[Site(DisplayName = "Warehouse ID", 
  DescriptionField = typeof(INSite.descr))]
[PXDefault(typeof(SOShipment.siteID), 
  PersistingCheck = PXPersistingCheck.Nothing)]
public virtual Int32? SiteID { get; set; }

Then replacing PXDefaultAttribute with PXDBDefaultAttribute looks as shown in the following code.

[PXRemoveBaseAttribute(typeof(PXDefaultAttribute))]
[PXDBDefault(typeof(SOShipment.siteID), 
  PersistingCheck = PXPersistingCheck.Nothing)]
protected virtual void _(Events.CacheAttached<SOOrderShipment.SiteID> e) { }

In this example, the PXDefaultAttribute is removed by the PXRemoveBaseAttribute attribute, and the new PXDBDefault attribute is declared.

Application Order of the Custom Attributes

The customization attributes described above are applied in the following order:

  1. Customization attributes of the PXCustomize static class
  2. PXRemoveBaseAttribute
  3. PXMergeAttributes