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

RowSelecting事件未触发,SOInvoice表单中基于BQL实现字段禁用的最佳方案?

在SOInvoice表单中实现字段禁用的最佳实践

首先直接给你结论:你完全可以使用RowSelected事件——虽然文档不建议在里面加BQL,但只要你的查询是轻量的(比如针对当前发票关联的单条记录),完全是可接受的。而且RowSelected正好能解决你遇到的RowSelecting初始化不触发的问题,因为表单首次加载记录时就会触发RowSelected。

先解释下你遇到的RowSelecting的问题:这个事件的触发时机是用户手动在网格中选择行的时候,表单初始化加载默认发票记录时并不会触发它,这就是为什么你调试时只有点取消才触发(取消操作可能触发了行选择状态变化),而且Acumatica的官方API文档里确实很少提及这个事件,因为它的适用场景非常窄。

回到你的需求:给非数据库绑定的布尔字段赋值,再用这个值控制其他字段的启用/禁用,针对SOInvoice表单,我推荐以下步骤:

1. 定义非DB绑定字段

首先在SOInvoice的DAC扩展里添加你的布尔字段:

public class SOInvoiceExtension : PXCacheExtension<SOInvoice>
{
    #region UsrDisableTargetField
    [PXBool]
    [PXUIField(DisplayName = "Disable Target Field")]
    public virtual bool? UsrDisableTargetField { get; set; }
    public abstract class usrDisableTargetField : PX.Data.BQL.BqlBool.Field<usrDisableTargetField> { }
    #endregion
}

2. 在RowSelected事件中实现逻辑

在SOInvoiceEntry的图扩展里,重写RowSelected事件,这里完成两个核心事情:

  • 执行BQL查询给非DB字段赋值
  • 根据这个值控制目标字段的启用状态

示例代码(假设你要根据关联的SOOrder状态来判断是否禁用字段):

public class SOInvoiceEntry_Extension : PXGraphExtension<SOInvoiceEntry>
{
    protected void SOInvoice_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
    {
        SOInvoice invoice = e.Row as SOInvoice;
        if (invoice == null) return;

        // 获取DAC扩展实例
        SOInvoiceExtension invoiceExt = cache.GetExtension<SOInvoiceExtension>(invoice);

        // 执行BQL查询(这里是查询关联的SOOrder,示例逻辑)
        SOOrder linkedOrder = PXSelect<SOOrder, 
            Where<SOOrder.orderType, Equal<Current<SOInvoice.orderType>>,
            And<SOOrder.orderNbr, Equal<Current<SOInvoice.orderNbr>>>>>.Select(Base);

        // 给非DB字段赋值:如果关联订单是冻结状态,就标记为禁用目标字段
        invoiceExt.UsrDisableTargetField = linkedOrder != null && linkedOrder.Hold == true;

        // 控制目标字段的启用/禁用,比如禁用CuryDocTotal字段
        PXUIFieldAttribute.SetEnabled<SOInvoice.curyDocTotal>(cache, invoice, !(invoiceExt.UsrDisableTargetField ?? false));
    }
}

3. 关键注意事项

  • BQL查询要轻量:尽量只查询和当前发票直接关联的单条记录,避免批量查询或复杂JOIN,否则会影响表单加载性能。如果查询结果可以复用,也可以考虑用缓存来优化。
  • 简化逻辑的替代方案:如果你的非DB字段不需要依赖外部数据,只是基于SOInvoice自身的字段计算,那可以直接在RowSelected里做计算,不需要BQL,比如:
    invoiceExt.UsrDisableTargetField = invoice.DocType == SOInvoiceType.CreditMemo;
    
  • 彻底放弃RowSelecting:正如你发现的,它在初始化时不触发,只适合网格行手动选择的场景,完全不匹配你的需求。

这样实现后,表单首次加载时RowSelected会自动触发,给非DB字段赋值并控制目标字段状态,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:02:03