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

如何获取DataGridView选中复选框行索引并分配计算序列?

DataGridView选中行捕获与计算序列分配解决方案

问题背景

我有一个DataGridView控件,前几列为数据列,最右侧最后一列为复选框列。控件限制仅能同时选中2行作为输入数据,当选中行的数据发生变更时,其余行需根据输入行的数据计算更新。总共有6行,任意两行组合均可被选中,目前需要解决的是如何捕获选中的2行,并为其分配对应的计算序列。

现有代码框架:

private void dgvParameters_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    //Get index of Rows with boxes checked in Column [5] and assign an integer array sequence
    //Ex: if Rows 1 & 3 are selected then int sequence = new int[6] {0,5,2,4,6};
    //Ex: if Rows 1 & 2 are selected then int sequence = new int[2] {0,3,7};

    for (int i = 0; i < sequence.Length; i++)
    {
        switch (sequence[i])
        {
            case 0: 
                //Do calculation for input from row 0 to update other rows
                break;
            case 1:
                //Do calculation for input from row 1 to update other rows
                break;
            ...
            case 7:
                //Do calculation for input from row 7 to update other rows
            default:
                break;
        }
    }
}

公式与计算序列规则:

//Formulas f() for calculation data values:
Row 1 = a = f(c,d)
Row 2 = b = f(a,d)
Row 3 = c = f(a,b)
Row 4 = d = f(b,c)

//EX: if Row 1 & 2 selected then use the values in these cells to solve for Row 3 & 4
//sequences have to be in a particular order to update the formulas correctly.
if Rows Selected = 1 & 2 then sequence = {3 ,4} //Calculate Rows 3 & 4 
if Rows Selected = 3 & 4 then sequence = {1, 2}
if Rows Selected = 1 & 4 then sequence = {2, 3}

实现步骤与代码

1. 捕获选中行并限制选中数量

添加辅助方法获取选中的行索引,同时确保最多选中2行:

private List<int> GetSelectedRowIndices()
{
    List<int> selectedIndices = new List<int>();
    foreach (DataGridViewRow row in dgvParameters.Rows)
    {
        // 检查复选框列(索引5)的选中状态,避免空值异常
        if (row.Cells[5].Value != null && (bool)row.Cells[5].Value)
        {
            selectedIndices.Add(row.Index);
        }
    }

    // 限制仅能选中2行,超出时自动取消多余选中
    if (selectedIndices.Count > 2)
    {
        // 临时禁用事件避免重复触发
        dgvParameters.CellValueChanged -= dgvParameters_CellValueChanged;
        for (int i = 2; i < selectedIndices.Count; i++)
        {
            dgvParameters.Rows[selectedIndices[i]].Cells[5].Value = false;
        }
        dgvParameters.CellValueChanged += dgvParameters_CellValueChanged;
        // 保留前2个选中行
        selectedIndices = selectedIndices.Take(2).ToList();
    }
    return selectedIndices;
}

2. 定义计算序列映射字典

在窗体初始化时创建映射,将选中行组合与对应的计算序列关联,注意对选中行索引排序,避免顺序差异导致匹配失败:

private Dictionary<string, int[]> _calculationSequenceMap;

private void InitializeSequenceMap()
{
    _calculationSequenceMap = new Dictionary<string, int[]>();
    // 按选中行索引升序拼接作为键,确保1&2和2&1匹配同一序列
    _calculationSequenceMap.Add("1,2", new int[] { 3, 4 });
    _calculationSequenceMap.Add("3,4", new int[] { 1, 2 });
    _calculationSequenceMap.Add("1,4", new int[] { 2, 3 });
    // 补充其他所有可能的2行组合对应的序列,例如:
    // _calculationSequenceMap.Add("0,1", new int[] { ... });
    // _calculationSequenceMap.Add("0,2", new int[] { ... });
    // ... 其余组合
}

3. 修改CellValueChanged事件逻辑

更新事件方法,完成选中行捕获、序列匹配与计算执行:

private void dgvParameters_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // 仅处理数据列或复选框列的变更
    if (e.ColumnIndex < 5 || e.ColumnIndex == 5)
    {
        List<int> selectedRows = GetSelectedRowIndices();
        // 选中行数量不为2时不执行计算
        if (selectedRows.Count != 2) return;

        // 排序选中行索引,生成字典匹配键
        selectedRows.Sort();
        string key = string.Join(",", selectedRows);

        // 获取对应计算序列并执行计算
        if (_calculationSequenceMap.TryGetValue(key, out int[] sequence))
        {
            foreach (int rowIndex in sequence)
            {
                switch (rowIndex)
                {
                    case 1:
                        // 执行Row1的计算逻辑:a = f(c,d)
                        break;
                    case 2:
                        // 执行Row2的计算逻辑:b = f(a,d)
                        break;
                    case 3:
                        // 执行Row3的计算逻辑:c = f(a,b)
                        break;
                    case 4:
                        // 执行Row4的计算逻辑:d = f(b,c)
                        break;
                    // 补充其他行的计算逻辑
                }
            }
        }
    }
}

4. 初始化映射字典

在窗体加载事件中调用初始化方法:

private void Form_Load(object sender, EventArgs e)
{
    InitializeSequenceMap();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:40:23