# 表单/单据插件 — C#（AbstractBillPlugIn）

```csharp
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.Bill.PlugIn.Args;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Util;
using Kingdee.BOS.Orm.DataEntity;
using System;
using System.ComponentModel;

namespace Kingdee.MyProject.Plugin.Form
{
    [Description("表单插件说明"), HotUpdate]
    public class MyBillPlugin : AbstractBillPlugIn
    {
        public override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            // 表单加载：初始化变量、缓存、设置默认值
            // 此阶段 UI 控件可能尚未创建完毕
        }

        public override void AfterBindData(EventArgs e)
        {
            base.AfterBindData(e);
            // 数据绑定完成后：设置控件可见性/锁定、过滤
            this.View.GetControl("FDate").Enabled = false;
        }

        public override void BarItemClick(BarItemClickEventArgs e)
        {
            base.BarItemClick(e);
            if (e.BarItemKey.EqualsIgnoreCase("MYBTN"))
            {
                this.View.ShowMessage("自定义按钮点击");
            }
        }

        public override void ButtonClick(ButtonClickEventArgs e)
        {
            base.ButtonClick(e);
            if (e.Key.EqualsIgnoreCase("F_btnSave"))
            {
                var remark = this.View.Model.GetValue("F_TTBO_Remarks") as string;
                if (string.IsNullOrEmpty(remark))
                {
                    this.View.ShowMessage("请输入处理意见");
                    return;
                }
                this.View.ReturnToParentWindow(remark);
                this.View.Close();
            }
        }

        public override void DataChanged(DataChangedEventArgs e)
        {
            base.DataChanged(e);
            if (e.Field == null) return;
            string fieldKey = e.Field.Key;
            if (fieldKey.EqualsIgnoreCase("FQty"))
            {
                // 金额 = 数量 * 单价
                decimal qty = Convert.ToDecimal(this.View.Model.GetValue("FQty") ?? 0);
                decimal price = Convert.ToDecimal(this.View.Model.GetValue("FPrice") ?? 0);
                this.View.Model.SetValue("FAmount", qty * price);
            }
        }

        public override void BeforeF7Select(BeforeF7SelectEventArgs e)
        {
            base.BeforeF7Select(e);
            if (e.FieldKey.EqualsIgnoreCase("FMATERIALID"))
            {
                // F7 选择前过滤
                e.ListFilterParameter.Filter = "FIsEnable = 1";
            }
        }

        public override void BeforeDoOperation(BeforeDoOperationEventArgs e)
        {
            base.BeforeDoOperation(e);
            // 界面保存校验主路径：OperateKey=Save；完整样例见 snippets/SaveValidateSample.cs
            // 禁止在本类使用 BeforeExecuteOperationTransaction
            if (e.OperateKey.EqualsIgnoreCase("Save"))
            {
                string billNo = Convert.ToString(this.Model.DataEntity["BillNo"] /* PropertyName */);
                if (string.IsNullOrEmpty(billNo))
                {
                    e.Cancel = true;
                    this.View.ShowErrMessage("单据编号不能为空");
                }
            }
        }

        public override void AfterDoOperation(AfterDoOperationEventArgs e)
        {
            base.AfterDoOperation(e);
            // 操作完成后处理
        }

        public override void BeforeSave(BeforeSaveEventArgs e)
        {
            base.BeforeSave(e);
            // 保存前校验备选入口（与 BeforeDoOperation(Save) 配合）
            // e.Cancel = true 可取消保存
        }


        public override void EntityRowDoubleClick(EntityRowClickEventArgs e)
        {
            base.EntityRowDoubleClick(e);
            // 分录行双击
        }
    }
}
```

**AbstractBillPlugIn 全部事件（反编译 Kingdee.BOS.Core.dll）：**
OnBillInitialize / OnShowConvertOpForm / OnGetConvertRule / OnShowTrackResult / BeforeCreateModelData / LoadData / AfterLoadData / **BeforeSave** / SaveBillFailed / AfterSave / AfterSaveFailed / BeforeSubmit / AfterSubmit / CopyData / AfterCopyData / BeforeSetStatus / AfterSetStatus / VerifyImportData / BeforeImportGetBaseDataUseOrg / OnTargetBillChanged /

继承自 **AbstractDynamicFormPlugIn：** BeforeExportDataNew / CreateNewData / AfterCreateNewData / OnChangeConvertRuleEnumList / **AfterCreateModelData** / BeforeControlDataBinder / BeforeEntryRowDataBinder / BeforeEntryBatchFill / AfterEntryBatchFill / BeforeCreateNewEntryRow / AfterCreateNewEntryRow / BeforeDeleteRow / **AfterDeleteRow** / BeforeUpdateValue / **DataChanged** / AfterCopyRow / BeforeDeleteEntry / AfterDeleteEntry / GetTreeViewData / **BeforeSetItemValueByNumber** / GroupSearchMenuPanelAction / ProductsPanelAction / PreOpenForm / **OnInitialize** / OnInitializeService / OnSetBusinessInfo / OnSetLayoutInfo / OnCreateDataBinder / **OnLoad** / BeforeClosed / FormClosed / BeforeFlexClosed / AfterShowFlexForm / ShowFlexFormLoad / Dispose / BeforeBindData / **AfterBindData** / AfterUpdateViewState / OnTimerElapsed / OnQueryProgressValue / **BarItemClick** / ContextMenuItemClick / **EntryBarItemClick** / ToolBarItemClick / **AfterBarItemClick** / AfterEntryBarItemClick / AfterToolBarItemClick / **ButtonClick** / ChangeHTmlTheme / **EntryButtonCellClick** / AfterButtonClick / TreeNodeClick / TreeNodeDoubleClick / TreeLoadData / BeforeDoAction / AfterDoAction / AuthPermissionBeforeF7Select / **BeforeF7Select** / AfterF7Select / AfterQuickGetData / AfterQuickSelect / BeforeFlexSelect / BeforeFilterGridF7Select / AfterShowCustomerPage / AfterShowForm / **BeforeDoOperation** / BeforeOperAfterSelOrg / **AfterDoOperation** / AfterConfirmOperation / ListViewClick / ListViewAddFavorClick / ListViewClearClick / TreeDragDrop / LanguageChanged / **EntityRowClick** / EntryCellFocued / FieldEditorFocued / **EntityRowDoubleClick** / TabItemSelectedChange / BeforeCustomEvents / CustomEvents / RowExpanding / HeaderCellClick / DataUpdateBeginning / DataUpdateEnd / NaviOperAction / FieldLabelClick / FireEntityBlockPasting / AfterEntityBlockPasting / BeforeF1Click / BeforeImportData / BeforeSaveImportData / BeforeShowImportResultMessage / ImportDataCollectFailInfo / ImportDataBeforeBindMatchFields / FireBeforeExportTitle / BeforeExportData / BeforeEntityExport / FireEntryCheck / FireMicroBlogClick / PortDataReceived / MsgInnerControlEvent / GetFormTitle / OnEntrySum / OnInitializeSendMailService / OnBeforeSendMailService / OnQueryFlexFieldState / OnPrepareDevPrintData / OnPrepareNotePrintData / OnPrepareNotePrintQueryParam / OnQueryDynamicColumns / OnAfterPrint / GetValidNoteTemplates / GetValidNoteTemplatesAll / OnBeforePrintValidate / BeforePrintExport / OnAfterPrintExport / BeforeNotePrintCommand / OnBeforePrintFromPreview / OnAfterWebApiOperation / OnBeforeWebApiOperation / UpdateChartData

**源码参考：** `lf-project/Kingdee.LF.Plugin/Plugin/Form/` — TestLogBillPlugin.cs, TickerHanleBillPlugin.cs, MachineDataReaderFormPlugin.cs, SimilarColorFormPlugin.cs
