You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Acumatica中点击Next/Prev导航时数据绑定失效问题

Acumatica INLocation表单切换记录后界面不更新问题

我正在开发一个用于更新INLocation记录的Acumatica基础表单,默认加载第一条记录,支持PREV/NEXT切换、字段修改和删除操作。目前首次运行能正确加载第一条记录,但点击NEXT或PREV按钮时,后台已切换到对应记录(断点验证通过),但界面信息未更新。

ASPX代码

<%@ Page Language="C#" MasterPageFile="~/MasterPages/FormView.master" AutoEventWireup="true" ValidateRequest="false" CodeFile="IN900100.aspx.cs" Inherits="Page_IN900100" Title="Untitled Page" %>
<%@ MasterType VirtualPath="~/MasterPages/FormView.master" %>
<asp:Content ID="cont1" ContentPlaceHolderID="phDS" Runat="Server">
  <px:PXDataSource ID="ds" runat="server" Visible="True" Width="100%"
        TypeName="ASGExecuteSQL.INLocationMaint"
        PrimaryView="Locations"
        >
    <CallbackCommands>
    </CallbackCommands>
  </px:PXDataSource>
</asp:Content>
<asp:Content ID="cont2" ContentPlaceHolderID="phF" Runat="Server">
  <px:PXFormView ID="form" runat="server" DataSourceID="ds" DataMember="Locations" Width="100%" AllowAutoHide="false">
    <Template>
      <px:PXLayoutRule runat="server" StartRow="True" ID="PXLayoutRule1" ></px:PXLayoutRule>
      <px:PXLayoutRule runat="server" ID="CstPXLayoutRule6" StartGroup="True" ></px:PXLayoutRule>
      <px:PXLabel runat="server" ID="CstLabel7" Text="INLocation Information" />
      <px:PXSegmentMask runat="server" ID="CstPXSegmentMask9" DataField="SiteID" />
      <px:PXSegmentMask runat="server" ID="CstPXSegmentMask8" DataField="LocationCD" CommitChanges="True" />
      <px:PXTextEdit runat="server" DataField="Descr" ID="edDescr" ></px:PXTextEdit>
      <px:PXTextEdit CommitChanges="True" runat="server" DataField="LocationID" ID="edLocationID" ></px:PXTextEdit>
    </Template>
    <AutoSize Container="Window" Enabled="True" MinHeight="200" ></AutoSize>
  </px:PXFormView>
</asp:Content>

C#后端代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Data;
using PX.Data.BQL.Fluent;
using PX.Objects.FS;
using PX.Objects.IN;
using static PX.Data.BQL.BqlPlaceholder;

namespace ASGExecuteSQL
{
    public class INLocationMaint : PXGraph<INLocationMaint>
    {
        // Primary view for INLocation DAC
        public PXCancel<INLocation> Cancel;
        public PXSave<INLocation> Save;
        public SelectFrom<INLocation>.View Locations;

        public INLocationMaint()
        {
            // Optionally load the first record into Locations.Current to initialize data
            if (Locations.Current == null)
            {
                Locations.Cache.AllowInsert = false; // don't let them create a blank record
                INLocation firstRecord = SelectFrom<INLocation>.View.Select(this);
                if (firstRecord != null)
                {
                    Locations.Current = firstRecord;
                }
                if (Locations.Current != null)
                {
                    var onCode = Locations.Current.LocationCD;
                    var onID = Locations.Current.LocationID;
                    var StopHere = 0;
                }
            }
        }

        protected void _(Events.RowSelected<INLocation> e)
        {
            var cache = e.Cache;
            // the default display for this is Location ID, which is confusing... so...
            PXUIFieldAttribute.SetDisplayName<INLocation.locationCD>(cache, "Location Code");
        }

        // NEXT button action
        public PXNext<INLocation> Next;
        [PXButton(CommitChanges = true)]
        [PXUIField(DisplayName = "Next", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
        protected IEnumerable next(PXAdapter adapter)
        {
            INLocation current = Locations.Current;
            INLocation next = PXSelect<INLocation,
                Where<INLocation.locationID, Greater<Required<INLocation.locationID>>>,
                OrderBy<Asc<INLocation.locationID>>>
                .Select(this, current.LocationID)
                .FirstOrDefault();
            if (next != null)
            {
                Locations.Current = next;
                Locations.Cache.Update(next);
                Locations.View.RequestRefresh();
            }
            return adapter.Get();
        }

        // PREVIOUS button action
        public PXPrevious<INLocation> Previous;
        [PXButton(CommitChanges = true)]
        [PXUIField(DisplayName = "Previous", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
        protected IEnumerable previous(PXAdapter adapter)
        {
            INLocation current = Locations.Current;
            INLocation prev = PXSelect<INLocation,
                Where<INLocation.locationID, Less<Required<INLocation.locationID>>>,
                OrderBy<Desc<INLocation.locationID>>>
                .Select(this, current.LocationID)
                .FirstOrDefault();
            if (prev != null)
            {
                Locations.Current = prev;
                Locations.Cache.Update(prev);
                Locations.View.RequestRefresh();
            }
            return adapter.Get();
        }

        // DELETE button action
        public PXDelete<INLocation> Delete;
        [PXButton(CommitChanges = true)]
        [PXUIField(DisplayName = "Delete", MapEnableRights = PXCacheRights.Select, MapViewRights = PXCacheRights.Select)]
        protected IEnumerable deleteLocation(PXAdapter adapter)
        {
            INLocation current = Locations.Current;
            if (current != null)
            {
                Locations.Delete(current);
                this.Actions.PressSave();
            }
            return adapter.Get();
        }
    }
}

问题原因及修复方案

核心问题

仅设置Locations.Current = next并调用RequestRefresh()不足以触发Acumatica界面刷新,因为没有让PXAdapter正确同步缓存状态并通知数据源更新界面绑定。

修复步骤

  1. 修改Next/Previous方法逻辑
    移除冗余的Cache.Update()和RequestRefresh()调用,改用SetCurrent()设置缓存当前记录,并通过yield return返回新记录,让PXAdapter自动处理界面同步:

    修改后的Next方法:

    protected IEnumerable next(PXAdapter adapter)
    {
        INLocation current = Locations.Current;
        INLocation nextRecord = PXSelect<INLocation,
            Where<INLocation.locationID, Greater<Required<INLocation.locationID>>>,
            OrderBy<Asc<INLocation.locationID>>>
            .Select(this, current.LocationID)
            .FirstOrDefault();
        
        if (nextRecord != null)
        {
            adapter.View.Cache.SetCurrent(nextRecord);
            yield return nextRecord;
        }
        else
        {
            yield return current;
        }
    }
    

    修改后的Previous方法:

    protected IEnumerable previous(PXAdapter adapter)
    {
        INLocation current = Locations.Current;
        INLocation prevRecord = PXSelect<INLocation,
            Where<INLocation.locationID, Less<Required<INLocation.locationID>>>,
            OrderBy<Desc<INLocation.locationID>>>
            .Select(this, current.LocationID)
            .FirstOrDefault();
        
        if (prevRecord != null)
        {
            adapter.View.Cache.SetCurrent(prevRecord);
            yield return prevRecord;
        }
        else
        {
            yield return current;
        }
    }
    
  2. 验证表单绑定
    当前ASPX中PXFormView的DataMember和DataSourceID配置正确,无需修改。

原理说明

Acumatica的PXAdapter会处理回调中的数据同步逻辑,通过SetCurrent()更新缓存状态,配合yield return返回新记录,能触发数据源通知界面控件重新绑定数据,实现界面刷新。

内容的提问来源于stack exchange,提问作者MarkJoel60

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:55:54