Acumatica物料向导AM300010:单条过滤结果自动全选实现咨询
问题:Acumatica物料向导页面筛选单条记录时自动全选的实现
背景与需求
- 在Acumatica的物料向导1页面(AM300010)新增了两个筛选器(生产单号、仓库)
- 需求:当生产单号筛选后仅返回一条记录时,自动触发「全选」操作
已实现的筛选器代码
[PXDBString(100)] [PXSelector(typeof(Search<AMProdItem.prodOrdID>), typeof(AMProdItem.prodOrdID), typeof(AMProdItem.orderType), typeof(AMProdItem.inventoryID), typeof(AMProdItem.prodDate), SubstituteKey = typeof(AMProdItem.prodOrdID), DescriptionField = typeof(AMProdItem.descr))] [PXUIField(DisplayName="Production Nbr.")] [PXInt] [PXDefault(typeof(Search<UserPreferenceExt.defaultSite, Where<UserPreferences.userID, Equal<Current<AccessInfo.userID>>>>), PersistingCheck = PXPersistingCheck.Nothing)] [PXSelector( typeof(Search<INSite.siteID>), typeof(INSite.siteCD), typeof(INSite.descr), SubstituteKey = typeof(INSite.siteCD))] [PXUIField(DisplayName="Warehouse")]
现有问题
尝试在视图查询方法内调用Base.Actions["ProcessAll"].Press()触发全选时,出现栈溢出错误:
Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space.
现有扩展代码:
using System; using PX.Data; using System.Collections.Generic; using PX.Objects.CS; using System.Collections; using System.Linq; using PX.Objects.IN; using PX.Objects.AM.Attributes; using PX.Objects; using PX.Objects.AM; namespace PX.Objects.AM { public class MatlWizard1_Extension : PXGraphExtension<PX.Objects.AM.MatlWizard1> { #region Event Handlers protected void AMProdItem_Selected_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e, PXFieldUpdated baseHandler) { baseHandler?.Invoke(cache, e); var row = (AMProdItem)e.Row; if (row.Selected == true) // Only if the item is selected { cache.SetValueExt<AMProdItem.qtytoProd>(row, 1.0000m); // Notify Acumatica of the update } } #endregion #region View Extensions protected virtual IEnumerable openOrders() { var baseView = new PXView(Base, true, Base.OpenOrders.View.BqlSelect); var startRow = PXView.StartRow; int totalRows = 0; var filter = Base.filter.Current; if (filter == null) { return baseView.Select(PXView.Currents, PXView.Parameters, PXView.Searches, PXView.SortColumns, PXView.Descendings, PXView.Filters, ref startRow, PXView.MaximumRows, ref totalRows); } var filterExt = filter.GetExtension<WizFilterExt>(); // If neither filter is set, return base view if (filterExt?.UsrWarehouseSelector2 == null && string.IsNullOrWhiteSpace(filterExt?.UsrProdOrderNoFilter)) { return baseView.Select(PXView.Currents, PXView.Parameters, PXView.Searches, PXView.SortColumns, PXView.Descendings, PXView.Filters, ref startRow, PXView.MaximumRows, ref totalRows); } // Build the where clause based on active filters BqlCommand cmd = new Select<AMProdItem>(); // Base conditions cmd = cmd.WhereAnd<Where<AMProdItem.function, NotEqual<OrderTypeFunction.disassemble>, And<Where<AMProdItem.isOpen, Equal<True>, And<AMProdItem.completed, NotEqual<True>>>>>>(); // Add warehouse filter if specified if (filterExt?.UsrWarehouseSelector2 != null) { cmd = cmd.WhereAnd<Where<AMProdItem.siteID, Equal<Required<AMProdItem.siteID>>>>(); } // Add production number filter if specified if (!string.IsNullOrWhiteSpace(filterExt?.UsrProdOrderNoFilter)) { cmd = cmd.WhereAnd<Where<AMProdItem.prodOrdID, Like<Required<AMProdItem.prodOrdID>>>>(); } var view = new PXView(Base, true, cmd); var parameters = new List<object>(); // Add parameter values in the same order as the where conditions if (filterExt?.UsrWarehouseSelector2 != null) { parameters.Add(filterExt.UsrWarehouseSelector2); } if (!string.IsNullOrWhiteSpace(filterExt?.UsrProdOrderNoFilter)) { parameters.Add("%" + filterExt.UsrProdOrderNoFilter + "%"); } return view.Select(PXView.Currents, parameters.ToArray(), PXView.Searches, PXView.SortColumns, PXView.Descendings, PXView.Filters, ref startRow, PXView.MaximumRows, ref totalRows); } #endregion } }
解决方案
栈溢出的根源是在视图的IEnumerable方法内调用全选Action,触发视图重新加载形成无限递归。正确做法是将判断逻辑移到筛选器字段的FieldUpdated事件中执行。
修改后的完整扩展代码
using System; using PX.Data; using System.Collections.Generic; using PX.Objects.CS; using System.Collections; using System.Linq; using PX.Objects.IN; using PX.Objects.AM.Attributes; using PX.Objects; using PX.Objects.AM; namespace PX.Objects.AM { public class MatlWizard1_Extension : PXGraphExtension<PX.Objects.AM.MatlWizard1> { #region Event Handlers protected void AMProdItem_Selected_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e, PXFieldUpdated baseHandler) { baseHandler?.Invoke(cache, e); var row = (AMProdItem)e.Row; if (row.Selected == true) { cache.SetValueExt<AMProdItem.qtytoProd>(row, 1.0000m); } } // 生产单号筛选器字段更新事件 protected void WizFilterExt_UsrProdOrderNoFilter_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e) { var filter = (WizFilter)e.Row; if (filter == null) return; // 刷新视图获取最新筛选结果 Base.OpenOrders.View.RequestRefresh(); Base.OpenOrders.View.Cache.Clear(); // 获取筛选后的记录数量 var recordCount = Base.OpenOrders.Select().Count(); if (recordCount == 1) { // 方式1:调用系统全选按钮(后台执行避免递归) PXLongOperation.StartOperation(Base, () => { var tempGraph = PXGraph.CreateInstance<MatlWizard1>(); tempGraph.filter.Current = filter; tempGraph.Actions["ProcessAll"].Press(); Base.OpenOrders.View.RequestRefresh(); }); // 方式2:手动标记唯一记录为选中(更轻量,无递归风险) // var targetItem = Base.OpenOrders.Select().FirstOrDefault() as AMProdItem; // if (targetItem != null) // { // Base.OpenOrders.Cache.SetValueExt<AMProdItem.selected>(targetItem, true); // Base.OpenOrders.Cache.SetValueExt<AMProdItem.qtytoProd>(targetItem, 1.0000m); // } } } #endregion #region View Extensions protected virtual IEnumerable openOrders() { var baseView = new PXView(Base, true, Base.OpenOrders.View.BqlSelect); var startRow = PXView.StartRow; int totalRows = 0; var filter = Base.filter.Current; if (filter == null) { return baseView.Select(PXView.Currents, PXView.Parameters, PXView.Searches, PXView.SortColumns, PXView.Descendings, PXView.Filters, ref startRow, PXView.MaximumRows, ref totalRows); } var filterExt = filter.GetExtension<WizFilterExt>(); if (filterExt?.UsrWarehouseSelector2 == null && string.IsNullOrWhiteSpace(filterExt?.UsrProdOrderNoFilter)) { return baseView.Select(PXView.Currents, PXView.Parameters, PXView.Searches, PXView.SortColumns, PXView.Descendings, PXView.Filters, ref startRow, PXView.MaximumRows, ref totalRows); } BqlCommand cmd = new Select<AMProdItem>(); cmd = cmd.WhereAnd<Where<AMProdItem.function, NotEqual<OrderTypeFunction.disassemble>, And<Where<AMProdItem.isOpen, Equal<True>, And<AMProdItem.completed, NotEqual<True>>>>>>(); if (filterExt?.UsrWarehouseSelector2 != null) { cmd = cmd.WhereAnd<Where<AMProdItem.siteID, Equal<Required<AMProdItem.siteID>>>>(); } if (!string.IsNullOrWhiteSpace(filterExt?.UsrProdOrderNoFilter)) { cmd = cmd.WhereAnd<Where<AMProdItem.prodOrdID, Like<Required<AMProdItem.prodOrdID>>>>(); } var view = new PXView(Base, true, cmd); var parameters = new List<object>(); if (filterExt?.UsrWarehouseSelector2 != null) { parameters.Add(filterExt.UsrWarehouseSelector2); } if (!string.IsNullOrWhiteSpace(filterExt?.UsrProdOrderNoFilter)) { parameters.Add("%" + filterExt.UsrProdOrderNoFilter + "%"); } return view.Select(PXView.Currents, parameters.ToArray(), PXView.Searches, PXView.SortColumns, PXView.Descendings, PXView.Filters, ref startRow, PXView.MaximumRows, ref totalRows); } #endregion } }
关键说明
- 禁止在视图查询方法内调用视图刷新或Action操作,彻底避免递归栈溢出
- 用
PXLongOperation包裹全选操作,确保在后台线程执行,不阻塞UI - 手动标记选中的方式更轻量,适合单条记录场景,减少系统Action调用的开销
内容的提问来源于stack exchange,提问作者Tharidhi P
相关产品推荐
相关产品推荐

