Skip to main content
Solved

How to automatically update/refresh a grid lines?

  • January 7, 2026
  • 2 replies
  • 58 views

Hello everyone,
I'm having the following scenario: I’m having the following code related with the Shipments screen in which I’m supposed to have 2 grids a separate tab called “Truck Information”, the grids are one for the Truck Information and the other is for Related Purchase Receipt Information. What I’m trying to achieve is when there’s an existing truck information data, when the user selects that row, the linked PR;s with this truck should be automatically displayed (reloading the graph or better updating the cache if possible). At the moment it’s almost working but the user has to automatically refresh the Related PR’s grid using the actions refresh button and the idea is that to be automated. There’s an existing functionality made by Acumatica in another screen (Complete Bidding) and the tab with the same functionality is called Bidding Results. The idea is the same but I’m not able to automatically refresh or update visually the cache. The selection does work. I’m open for any advice’s. I have tried updating the cache in the event handler for the selected row but it’s incorrectly to use cache manipulation there or at least that’s what the error was saying. The version of Acumatica I’m using is 2025 r2

Here’s the code I’m having at the moment:

public class SOShipmentEntryExt_TruckInfo : PXGraphExtension<SOShipmentEntry>
{
public static bool IsActive() => true;

#region Views

[PXCopyPasteHiddenView]
public PXSelect<SOShipmentTruckInfo,
Where<SOShipmentTruckInfo.shipmentNbr, Equal<Current<SOShipment.shipmentNbr>>>> TruckInformation;

public PXSelectJoin<SOShipmentTruckPRLink,
LeftJoin<POReceipt,
On<POReceipt.receiptNbr, Equal<SOShipmentTruckPRLink.receiptNbr>>>,
Where<SOShipmentTruckPRLink.truckInfoID, Equal<Argument<int?>>>>
RelatedPRInfo;

#endregion

#region Delegate Methods

public virtual IEnumerable relatedPRInfo(
[PXInt]
int? truckInfoID)
{
int? currentTruckInfoID = truckInfoID ?? (TruckInformation.Current != null ? TruckInformation.Current.TruckInfoID : null);

foreach (PXResult<SOShipmentTruckPRLink, POReceipt> item in
PXSelectJoin<SOShipmentTruckPRLink,
LeftJoin<POReceipt,
On<POReceipt.receiptNbr, Equal<SOShipmentTruckPRLink.receiptNbr>>>,
Where<SOShipmentTruckPRLink.truckInfoID, Equal<Required<SOShipmentTruckPRLink.truckInfoID>>>>
.Select(this.Base, currentTruckInfoID))
{
yield return item;
}
}

#endregion

#region Event Handlers - SOShipmentTruckInfo

protected virtual void _(Events.RowSelected<SOShipmentTruckInfo> e)
{
if (e.Row == null) return;

SOShipment shipment = Base.Document.Current;
if (shipment == null) return;

bool isEditable = shipment.Status != SOShipmentStatus.Completed;

PXUIFieldAttribute.SetEnabled(e.Cache, e.Row, isEditable);

RelatedPRInfo.View.RequestRefresh();
}

protected virtual void _(Events.RowInserted<SOShipmentTruckInfo> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}

protected virtual void _(Events.RowUpdated<SOShipmentTruckInfo> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}

protected virtual void _(Events.RowDeleted<SOShipmentTruckInfo> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}

#endregion

#region Event Handlers - SOShipmentTruckPRLink

protected virtual void _(Events.RowSelected<SOShipmentTruckPRLink> e)
{
if (e.Row == null) return;

SOShipment shipment = Base.Document.Current;
if (shipment == null) return;

bool isEditable = shipment.Status != SOShipmentStatus.Completed;

PXUIFieldAttribute.SetEnabled<SOShipmentTruckPRLink.receiptNbr>(e.Cache, e.Row, isEditable);
}

protected virtual void _(Events.FieldSelecting<SOShipmentTruckPRLink.pONbr> e)
{
var row = e.Row as SOShipmentTruckPRLink;
if (row == null || string.IsNullOrEmpty(row.ReceiptNbr))
return;

// Query POReceiptLine to get PO Number
POReceiptLine firstLine = PXSelectReadonly<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>>>
.SelectSingleBound(Base, null, row.ReceiptNbr);

if (firstLine != null)
{
e.ReturnValue = firstLine.PONbr;
}
}

protected virtual void _(Events.FieldSelecting<SOShipmentTruckPRLink.pOLineNbr> e)
{
var row = e.Row as SOShipmentTruckPRLink;
if (row == null || string.IsNullOrEmpty(row.ReceiptNbr))
return;

// Query POReceiptLine to get PO Line Number
POReceiptLine firstLine = PXSelectReadonly<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>>>
.SelectSingleBound(Base, null, row.ReceiptNbr);

if (firstLine != null)
{
e.ReturnValue = firstLine.LineNbr;
}
}

protected virtual void _(Events.FieldSelecting<SOShipmentTruckPRLink.contractNbr> e)
{
var row = e.Row as SOShipmentTruckPRLink;
if (row == null || string.IsNullOrEmpty(row.ReceiptNbr))
return;

// Query POReceiptLine to get PO information first
POReceiptLine firstLine = PXSelectReadonly<POReceiptLine,
Where<POReceiptLine.receiptNbr, Equal<Required<POReceiptLine.receiptNbr>>>>
.SelectSingleBound(Base, null, row.ReceiptNbr);

if (firstLine != null)
{
// Query POLine to get Contract Number
POLine poLine = PXSelectReadonly<POLine,
Where<POLine.orderType, Equal<Required<POLine.orderType>>,
And<POLine.orderNbr, Equal<Required<POLine.orderNbr>>,
And<POLine.lineNbr, Equal<Required<POLine.lineNbr>>>>>>
.SelectSingleBound(Base, null, firstLine.POType, firstLine.PONbr, firstLine.LineNbr);

if (poLine != null)
{
var poLineExt = poLine.GetExtension<POLineExt>();
e.ReturnValue = poLineExt?.UsrContractNbr;
}
}
}

protected virtual void _(Events.FieldUpdated<SOShipmentTruckPRLink.receiptNbr> e)
{
var row = e.Row as SOShipmentTruckPRLink;
if (row == null) return;

// Force FieldSelecting events to fire for unbound fields to refresh UI
object fieldValue = null;
e.Cache.RaiseFieldSelecting<SOShipmentTruckPRLink.pONbr>(row, ref fieldValue, false);
e.Cache.RaiseFieldSelecting<SOShipmentTruckPRLink.pOLineNbr>(row, ref fieldValue, false);
e.Cache.RaiseFieldSelecting<SOShipmentTruckPRLink.contractNbr>(row, ref fieldValue, false);

// Mark shipment as updated to enable Save button
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}

protected virtual void _(Events.RowInserted<SOShipmentTruckPRLink> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}

protected virtual void _(Events.RowUpdated<SOShipmentTruckPRLink> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}

protected virtual void _(Events.RowDeleted<SOShipmentTruckPRLink> e)
{
if (e.Row == null) return;
SOShipment shipment = Base.Document.Current;
if (shipment != null)
{
Base.Document.Cache.MarkUpdated(shipment);
}
}

#endregion

#region Event Handlers - SOShipment

protected virtual void _(Events.RowSelected<SOShipment> e)
{
if (e.Row == null) return;

bool isEditable = e.Row.Status != SOShipmentStatus.Completed;

TruckInformation.AllowInsert = isEditable;
TruckInformation.AllowDelete = isEditable;
TruckInformation.AllowUpdate = isEditable;
TruckInformation.Cache.AllowInsert = isEditable;
TruckInformation.Cache.AllowDelete = isEditable;
TruckInformation.Cache.AllowUpdate = isEditable;

RelatedPRInfo.AllowInsert = isEditable;
RelatedPRInfo.AllowDelete = isEditable;
RelatedPRInfo.AllowUpdate = isEditable;
RelatedPRInfo.Cache.AllowInsert = isEditable;
RelatedPRInfo.Cache.AllowDelete = isEditable;
RelatedPRInfo.Cache.AllowUpdate = isEditable;

var linkedPRsInvalidStatus = PXSelectJoin<POReceipt,
InnerJoin<SOShipmentTruckPRLink,
On<SOShipmentTruckPRLink.receiptNbr, Equal<POReceipt.receiptNbr>>,
InnerJoin<SOShipmentTruckInfo,
On<SOShipmentTruckInfo.truckInfoID, Equal<SOShipmentTruckPRLink.truckInfoID>>>>,
Where<SOShipmentTruckInfo.shipmentNbr, Equal<Required<SOShipmentTruckInfo.shipmentNbr>>,
And<POReceipt.status, NotEqual<POReceiptStatus.released>>>>
.Select(Base, e.Row.ShipmentNbr);

bool hasLinkedPRsInvalidStatus = linkedPRsInvalidStatus.Count > 0;

if (hasLinkedPRsInvalidStatus)
{
PXUIFieldAttribute.SetWarning<SOShipment.shipmentNbr>(e.Cache, e.Row,
TruckInfo.Messages.CannotConfirmShipmentPRInvalidStatus);
}

// Disable Confirm Shipment action when there are linked PRs with invalid status
PXAction confirmAction = Base.Actions["ConfirmShipment"];
if (confirmAction != null)
{
confirmAction.SetEnabled(!hasLinkedPRsInvalidStatus);
}
}



 

Best answer by Rakshanda

Hi ​@nikola74 ,

Can you try implementing this by making ASPX changes?
You need to pass Grid1 (with ID grid) as a parameter to the second grid with ID gridBidding.
Please verify the highlighted section in this context.

----------------------------------------------------------------------------------------------------------------------------

    <px:PXTabItem Text="Bidding Results" Overflow="Hidden" LoadOnDemand="true">
        <Template>
            <px:PXSplitContainer runat="server" ID="sp1" SplitterPosition="300" SkinID="Horizontal" Height="200px" Panel1MinSize="175" Panel2MinSize="175">
                <AutoSize Enabled="true" />
                <Template1>
                    <px:PXGrid ID="grid" runat="server" DataSourceID="ds" Width="100%" SkinID="DetailsInTab" Caption="Requisition Details" SyncPositionWithGraph="true">
                        <Levels>
                            <px:PXGridLevel DataMember="Lines">
                                <Columns>
                                    <px:PXGridColumn DataField="LineNbr" TextAlign="Right" Visible="False" />
                                    <px:PXGridColumn DataField="InventoryID" DisplayFormat="&gt;AAAAAAAAAA" />
                                    <px:PXGridColumn DataField="SubItemID" DisplayFormat="&gt;A" />                           
                                </Columns>
                            </px:PXGridLevel>
                        </Levels>
                        <Layout FormViewHeight="600px" />
                        <Mode AllowAddNew="false" AllowUpdate="false" AllowDelete="false" />
                        <AutoCallBack Target="gridBidding" Command="Refresh">
                        </AutoCallBack>
                        <AutoSize Enabled="true" MinHeight="180"/>
                    </px:PXGrid>
                </Template1>
                <Template2>
                    <px:PXGrid ID="gridBidding" runat="server" DataSourceID="ds" Style="z-index: 100; height: 167px;" Width="100%" SkinID="DetailsInTab"
                        Caption="Bidding Details">
                        <CallbackCommands>
                            <Save CommitChanges="true" CommitChangesIDs="gridBidding" RepaintControls="None" />
                            <FetchRow RepaintControls="None" />
                        </CallbackCommands>
                        <Levels>
                            <px:PXGridLevel DataMember="Bidding">
                                <RowTemplate>
                                    <px:PXLayoutRule runat="server" StartColumn="True" LabelsWidth="SM" ControlSize="M" />
                                    <px:PXNumberEdit ID="edLineNbr" runat="server" DataField="LineNbr" />                               
                                <Columns>
                                    <px:PXGridColumn AllowNull="False" DataField="Selected" TextAlign="Center" Type="CheckBox" AllowCheckAll="True" AutoCallBack="true" />
                                    <px:PXGridColumn AllowShowHide="False" DataField="LineNbr" TextAlign="Right" Visible="False" />
                                    <px:PXGridColumn DataField="VendorID" DisplayFormat="&gt;AAAAAAAAAA" AutoCallBack="true" />
                                    <px:PXGridColumn DataField="VendorID_Vendor_AcctName" />                             
                                </Columns>
                            </px:PXGridLevel>
                        </Levels>
                        <Mode AllowAddNew="true" AllowUpdate="true" AllowDelete="true" />
                        <Parameters>
                            <px:PXControlParam ControlID="form" Name="reqNbr" PropertyName="NewDataKey[&quot;ReqNbr&quot;]" Type="string" />
                            <px:PXControlParam ControlID="grid" Name="lineNbr" PropertyName="DataValues[&quot;LineNbr&quot;]" Type="Int32" />
                            <px:PXSyncGridParam ControlID="grid" />
                        </Parameters>

                        <AutoSize Enabled="True" MinHeight="180"/>
                    </px:PXGrid>
                </Template2>
            </px:PXSplitContainer>
        </Template>
    </px:PXTabItem>

2 replies

Forum|alt.badge.img+3
  • Jr Varsity II
  • Answer
  • January 7, 2026

Hi ​@nikola74 ,

Can you try implementing this by making ASPX changes?
You need to pass Grid1 (with ID grid) as a parameter to the second grid with ID gridBidding.
Please verify the highlighted section in this context.

----------------------------------------------------------------------------------------------------------------------------

    <px:PXTabItem Text="Bidding Results" Overflow="Hidden" LoadOnDemand="true">
        <Template>
            <px:PXSplitContainer runat="server" ID="sp1" SplitterPosition="300" SkinID="Horizontal" Height="200px" Panel1MinSize="175" Panel2MinSize="175">
                <AutoSize Enabled="true" />
                <Template1>
                    <px:PXGrid ID="grid" runat="server" DataSourceID="ds" Width="100%" SkinID="DetailsInTab" Caption="Requisition Details" SyncPositionWithGraph="true">
                        <Levels>
                            <px:PXGridLevel DataMember="Lines">
                                <Columns>
                                    <px:PXGridColumn DataField="LineNbr" TextAlign="Right" Visible="False" />
                                    <px:PXGridColumn DataField="InventoryID" DisplayFormat="&gt;AAAAAAAAAA" />
                                    <px:PXGridColumn DataField="SubItemID" DisplayFormat="&gt;A" />                           
                                </Columns>
                            </px:PXGridLevel>
                        </Levels>
                        <Layout FormViewHeight="600px" />
                        <Mode AllowAddNew="false" AllowUpdate="false" AllowDelete="false" />
                        <AutoCallBack Target="gridBidding" Command="Refresh">
                        </AutoCallBack>
                        <AutoSize Enabled="true" MinHeight="180"/>
                    </px:PXGrid>
                </Template1>
                <Template2>
                    <px:PXGrid ID="gridBidding" runat="server" DataSourceID="ds" Style="z-index: 100; height: 167px;" Width="100%" SkinID="DetailsInTab"
                        Caption="Bidding Details">
                        <CallbackCommands>
                            <Save CommitChanges="true" CommitChangesIDs="gridBidding" RepaintControls="None" />
                            <FetchRow RepaintControls="None" />
                        </CallbackCommands>
                        <Levels>
                            <px:PXGridLevel DataMember="Bidding">
                                <RowTemplate>
                                    <px:PXLayoutRule runat="server" StartColumn="True" LabelsWidth="SM" ControlSize="M" />
                                    <px:PXNumberEdit ID="edLineNbr" runat="server" DataField="LineNbr" />                               
                                <Columns>
                                    <px:PXGridColumn AllowNull="False" DataField="Selected" TextAlign="Center" Type="CheckBox" AllowCheckAll="True" AutoCallBack="true" />
                                    <px:PXGridColumn AllowShowHide="False" DataField="LineNbr" TextAlign="Right" Visible="False" />
                                    <px:PXGridColumn DataField="VendorID" DisplayFormat="&gt;AAAAAAAAAA" AutoCallBack="true" />
                                    <px:PXGridColumn DataField="VendorID_Vendor_AcctName" />                             
                                </Columns>
                            </px:PXGridLevel>
                        </Levels>
                        <Mode AllowAddNew="true" AllowUpdate="true" AllowDelete="true" />
                        <Parameters>
                            <px:PXControlParam ControlID="form" Name="reqNbr" PropertyName="NewDataKey[&quot;ReqNbr&quot;]" Type="string" />
                            <px:PXControlParam ControlID="grid" Name="lineNbr" PropertyName="DataValues[&quot;LineNbr&quot;]" Type="Int32" />
                            <px:PXSyncGridParam ControlID="grid" />
                        </Parameters>

                        <AutoSize Enabled="True" MinHeight="180"/>
                    </px:PXGrid>
                </Template2>
            </px:PXSplitContainer>
        </Template>
    </px:PXTabItem>


Forum|alt.badge.img+4

Hi ​@nikola74 

If I understood correctly, you have two grids: the first one displays parent records, and the second one displays child records. You want the second grid to refresh automatically when the selected record in the first grid changes.

If that’s the case, all you need to do is set SyncPosition for the first grid and configure Command and Target for AutoCallBack, where grid2 is the ID of the second grid in the ASPX page.

<px:PXGrid ID="grid1" SyncPosition="True" ... 
...
<AutoCallBack Command="Refresh" Target="grid2"></AutoCallBack>
</px:PXGrid>

 


Since you are using version 25R2, you may also need to implement the same logic in the Modern UI. To do this, for the first grid’s PXView class, add the
autoRepaint: ["SecondGridViewProperty"]
property to the gridConfig decorator.

@graphInfo({
graphType: "MyEntry",
primaryView: "MyPrimaryView"
})
export class AA301000 extends PXScreen {
...
FirstGridViewProperty = createCollection(AALine);
SecondGridViewProperty = createCollection(AALineSplit);
...
}
...

@gridConfig({
preset: GridPreset.ReadOnly,
autoRepaint:["SecondGridViewProperty"],
syncPosition: true
})
export class AALine extends PXView {
...
MyField : PXFieldState;
...
}

 


  • Author
  • Freshman II
  • January 7, 2026

This did the job. What I did was to add the AutoCallBack on the main grid and add the CallbackCommands on the seconds grid

The changes for the main grid

<AutoCallBack Target="gridBidding" Command="Refresh"></AutoCallBack>


The changes for the second grid

<CallbackCommands>
    <Save CommitChanges="true" CommitChangesIDs="the_ID_of_the_2nd_Grid_goes_here" RepaintControls="None" />
    <FetchRow RepaintControls="None" />
</CallbackCommands>