# 列表插件 — C#（AbstractListPlugIn）

## API 白名单（强制）

写列表插件前必读本文件 + `ListPluginTemplate.cs` + `snippets/ListBatchRemarkSample.cs`。  
**只使用白名单成员；不在表内则禁止出现在生成代码中。**

| 允许 | 说明 |
|------|------|
| `ListView.SelectedRowsInfo` | 勾选行集合 |
| `GetPrimaryKeyValues` / `GetEntryPrimaryKeyValues` | 主键 / 分录主键 |
| `ListModel.GetData(selectedRowsInfo)` | 行数据包 |
| `View.ShowMessage` / `ShowWarnningMessage` / `ShowErrMessage` | 提示 |
| `PrepareFilterParameter` | 过滤 |
| `BarItemClick` / `AfterBarItemClick` | 工具栏（批处理优先 **AfterBarItemClick**） |
| `BeforeDoOperation` / `AfterDoOperation` | 列表操作拦截 |
| `ListRowDoubleClick` / `OnFormatRowConditions` / `EntryButtonCellClick` | 手册内其它事件 |
| `BusinessDataServiceHelper.Save` | 服务侧保存勾选数据 |

| 禁止（常见幻觉） | 替代 |
|------------------|------|
| `GetSelectionData` | `ListView.SelectedRowsInfo` + `ListModel.GetData` |
| `ShowErr` | `ShowErrMessage` / `ShowWarnningMessage` |
| `ShowInputBox` / `ShowProgress` | 设计器交互或 `ShowMessage`；勿编对话框 API |
| `BusinessServiceHelper` | `BusinessDataServiceHelper` |
| 无依据整页 `Refresh` | 非必要不写 |

行字段索引用 **PropertyName**（元数据）；勿把 Key 当数据包键。

```csharp
using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.List.PlugIn;
using Kingdee.BOS.Core.List.PlugIn.Args;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace Kingdee.MyProject.Plugin.List
{
    [Description("列表插件说明"), HotUpdate]
    public class MyListPlugin : AbstractListPlugIn
    {
        public override void PrepareFilterParameter(FilterArgs e)
        {
            base.PrepareFilterParameter(e);
            e.AppendQueryFilter("FDOCUMENTSTATUS = 'C'");
        }

        public override void BarItemClick(BarItemClickEventArgs e)
        {
            base.BarItemClick(e);
            if (e.BarItemKey.EqualsIgnoreCase("MYBTN"))
            {
                // e.Cancel = true;
            }
        }

        public override void AfterBarItemClick(AfterBarItemClickEventArgs e)
        {
            base.AfterBarItemClick(e);
            if (!e.BarItemKey.EqualsIgnoreCase("MYBTN")) return;

            var selectedRowsInfo = this.ListView.SelectedRowsInfo;
            var billIDs = selectedRowsInfo.GetPrimaryKeyValues();
            if (billIDs.Length == 0)
            {
                this.View.ShowWarnningMessage("未选择任何行！");
                return;
            }

            var datas = this.ListModel.GetData(selectedRowsInfo);
            foreach (DynamicObject row in datas)
            {
                // PropertyName，以元数据为准
                string billNo = Convert.ToString(row["BillNo"]);
            }
            this.View.ShowMessage("处理完成，共 " + billIDs.Length + " 条");
        }

        public override void ListRowDoubleClick(ListRowClickEventArgs e)
        {
            base.ListRowDoubleClick(e);
            int row = e.Row;
            string colKey = e.ColKey;
        }

        public override void OnFormatRowConditions(ListFormatConditionArgs args)
        {
            base.OnFormatRowConditions(args);
            var dataRow = ((DynamicObjectDataRow)args.DataRow).DynamicObject;

            if (dataRow.DynamicObjectType.Properties.ContainsKey("FMaterialId"))
            {
                FormatCondition fc = new FormatCondition();
                fc.BackColor = "#0000FF";
                args.FormatConditions.Add(fc);
            }
        }

        public override void EntryButtonCellClick(EntryButtonCellClickEventArgs e)
        {
            base.EntryButtonCellClick(e);
            this.View.ShowMessage("点击了第" + e.Row + "行的[" + e.FieldKey + "]");
        }

        public override void BeforeDoOperation(BeforeDoOperationEventArgs e)
        {
            base.BeforeDoOperation(e);
            if (e.OperateKey.EqualsIgnoreCase("DELETE"))
            {
                e.Cancel = true;
                this.View.ShowWarnningMessage("取消删除！");
            }
        }

        public override void AfterDoOperation(AfterDoOperationEventArgs e)
        {
            base.AfterDoOperation(e);
        }
    }
}
```

批量改字段完整样例：`snippets/ListBatchRemarkSample.cs`。

**AbstractListPlugIn 专有事件（反编译 Kingdee.BOS.Core.dll）：**  
ListInitialize / CellFormat / CellDbClick / BeforeButtonClick / AfterButtonClick / BeforeMenuClick / AfterMenuClick / ListCreateColumns / ListRowDoubleClick / OnShowConvertOpForm / OnGetConvertRule / OnShowTrackResult / **OnFormatRowConditions** / **PrepareFilterParameter** / BeforeGetDataForTempTableAccess / AfterCreateSqlBuilderParameter / PrepareFuncPermissionDataRule / CreateFilterEditorControl / AfterGetData / **FormatCellValue** / BatchCopyData / AfterBatchCopyData / **EntryHyperlinkButtonClick** / AfterCreateFilterField / OnTargetBillChanged / CreateListHeader / ReplaceEntityTable

此外继承 AbstractDynamicFormPlugIn 全部事件（见 FormPlugin.md）。

**源码参考：** `lf-project/Kingdee.LF.Plugin/Plugin/List/` — TestLogListPlugin.cs
