There is only one major rule when it comes to defining key fields in a DAC:
The standard PXInsert action provided by the framework preserves values of all key fields, except the last one. If you want the Insert button to clear values of all key field, it's possible to inherit from the PXInsert<TNode>
class and clear Searches array before base logic gets executed:
public class MyGraph : PXGraph<MyGraph>
{
public class PXInsertCst<TNode> : PXInsert<TNode>
where TNode : class, IBqlTable, new()
{
public PXInsertCst(PXGraph graph, string name)
: base(graph, name)
{
}
public PXInsertCst(PXGraph graph, Delegate handler)
: base(graph, handler)
{
}
[PXUIField(DisplayName = ActionsMessages.Insert,
MapEnableRights = PXCacheRights.Insert,
MapViewRights = PXCacheRights.Insert)]
[PXInsertButton]
protected override IEnumerable Handler(PXAdapter adapter)
{
adapter.Searches = null;
return base.Handler(adapter);
}
}
public PXSave<MyPrimaryDAC> Save;
public PXCancel<MyPrimaryDAC> Cancel;
// The standard PXInsert type was replaced with the custom PXInsertCst type
public PXInsertCst<MyPrimaryDAC> Insert;
public PXDelete<MyPrimaryDAC> Delete;
public PXCopyPasteAction<MyPrimaryDAC> CopyPaste;
public PXFirst<MyPrimaryDAC> First;
public PXPrevious<MyPrimaryDAC> Previous;
public PXNext<MyPrimaryDAC> Next;
public PXLast<MyPrimaryDAC> Last;
}
In case it's required to show the only DAC key field bound an identity column in the UI, but users don't want to see a temporary negative value generated for a new record, you should implement FieldSelecting and FieldUpdating event handlers for the DAC's identity column mapped field following the code sample below:
public class MyGraph : PXGraph<MyGraph>
{
protected void MyDAC_IdentityField_FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
if (e.Row != null && e.ReturnValue is int?)
{
if ((e.ReturnValue as int?).GetValueOrDefault() < 0)
{
e.ReturnValue = null;
}
}
}
protected void MyDAC_IdentityField_FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
if (e.Row != null && e.NewValue == null && sender.Inserted.Count() == 1)
{
var defaultValue = sender.GetValue<MyDAC.identityField>(sender.Inserted.FirstOrDefault_());
if (defaultValue != null)
{
e.NewValue = defaultValue;
}
}
}
}
For a more generic approach on the DAC level, you can implement a custom attribute inherited from PXDBIdentityAttribute
and override FieldSelecting and FieldUpdating event handlers following the code sample below:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter |
AttributeTargets.Class | AttributeTargets.Method)]
public class PXDBNewIdentityAttribute : PXDBIdentityAttribute
{
public override void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
{
base.FieldSelecting(sender, e);
if (e.Row != null && e.ReturnValue is int?)
{
if ((e.ReturnValue as int?).GetValueOrDefault() < 0)
{
e.ReturnValue = null;
}
}
}
public override void FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
if (e.Row != null && e.NewValue == null && sender.Inserted.Count() == 1)
{
var defaultValue = sender.GetValue(sender.Inserted.FirstOrDefault_(), FieldOrdinal);
if (defaultValue != null)
{
e.NewValue = defaultValue;
}
}
base.FieldUpdating(sender, e);
}
}