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

VSTO Excel插件需求:在用户控件中实现带复选框的下拉组合框

实现带复选框的ComboBox用于Excel VSTO工作表多选筛选

完全可以通过自定义带复选框的ComboBox来实现你的需求,既能支持30+工作表的多选筛选,又能避免FlowLayoutPanel动态调整带来的卡顿问题。以下是具体实现方案:

核心思路

  • 继承标准ComboBox控件,重写绘制逻辑,在下拉项前添加复选框;
  • 维护选中状态字典,记录每个工作表的选中情况;
  • 自定义显示文本,直观反馈选中数量或内容;
  • 直接嵌入VSTO窗体,无需依赖动态布局容器。

自定义CheckedComboBox控件代码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

public class CheckedComboBox : ComboBox
{
    private readonly Dictionary<string, bool> _checkedStates = new Dictionary<string, bool>();

    public CheckedComboBox()
    {
        DrawMode = DrawMode.OwnerDrawFixed;
        DropDownStyle = ComboBoxStyle.DropDownList;
        ItemHeight = 22; // 适配复选框高度
    }

    // 添加工作表项
    public void AddWorksheet(string sheetName)
    {
        if (!_checkedStates.ContainsKey(sheetName))
        {
            _checkedStates.Add(sheetName, false);
            Items.Add(sheetName);
        }
    }

    // 重写绘制逻辑,绘制复选框和文本
    protected override void OnDrawItem(DrawItemEventArgs e)
    {
        e.DrawBackground();
        if (e.Index >= 0)
        {
            string sheetName = Items[e.Index].ToString();
            bool isChecked = _checkedStates[sheetName];

            // 绘制复选框
            CheckBoxRenderer.DrawCheckBox(
                e.Graphics,
                new Point(e.Bounds.X + 3, e.Bounds.Y + 2),
                isChecked ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal);

            // 绘制工作表名称
            e.Graphics.DrawString(
                sheetName,
                e.Font,
                Brushes.Black,
                new Point(e.Bounds.X + 25, e.Bounds.Y + 3));
        }
        e.DrawFocusRectangle();
    }

    // 处理选中事件,切换复选框状态
    protected override void OnSelectedIndexChanged(EventArgs e)
    {
        if (SelectedIndex >= 0)
        {
            string sheetName = Items[SelectedIndex].ToString();
            _checkedStates[sheetName] = !_checkedStates[sheetName];
            
            // 更新控件显示文本
            int checkedCount = _checkedStates.Count(kv => kv.Value);
            Text = checkedCount > 0 ? $"已选中{checkedCount}个工作表" : "选择工作表";
            
            DroppedDown = true; // 保持下拉展开,方便连续选择
        }
        base.OnSelectedIndexChanged(e);
    }

    // 获取所有选中的工作表名称
    public List<string> GetSelectedSheets()
    {
        return _checkedStates.Where(kv => kv.Value).Select(kv => kv.Key).ToList();
    }
}

在VSTO加载项中使用

在你的加载项窗体初始化时,绑定当前工作簿的工作表:

private void AddInForm_Load(object sender, EventArgs e)
{
    // 创建自定义控件并设置样式
    var sheetSelector = new CheckedComboBox();
    sheetSelector.Location = new Point(20, 20);
    sheetSelector.Size = new Size(250, 25);
    Controls.Add(sheetSelector);

    // 绑定当前工作簿的所有工作表
    foreach (Excel.Worksheet sheet in Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets)
    {
        sheetSelector.AddWorksheet(sheet.Name);
    }
}

优化建议

  • 若工作表数量过多,可添加搜索过滤功能:在ComboBox上方添加TextBox,实时筛选下拉项;
  • 调整ItemHeight和绘制位置,适配不同的DPI设置;
  • 监听工作簿的工作表新增/删除事件,同步更新ComboBox的项列表,保证数据一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:18:20