根据DataGridView </t>中的选择删除List <t>中的重复项

时间:2012-01-17 16:42:41

标签: .net visual-studio-2010 c#-4.0

(强制性的初学警报!我不能保证我会理解你告诉我的一切。)

我有一个程序使用List<T>自定义类CheckOrderLine来填充DataGridViewBindingSource。在dataGrid控件内,我提供了将记录“拆分”成多行以进行拼版的功能。我在解决这个过程的过程中遇到了麻烦。

我需要能够在dataGrid中进行选择,从第一个选定的行开始,然后遍历选择中的每个CheckOrderLine并将它们与第一行进行比较。

如果它们全部匹配,我需要将第一个记录中的数量更改为所有选定行的总和,然后删除多余的行。

这是我到目前为止自己制定的一段摘录:

        int index = 1;
        while (index < rowToJoin)
        {
            _bs.RaiseListChangedEvents = false;

            int first = _bs.Position;
            int second = first++;
            CheckOrderLine current = (CheckOrderLine)_bs[first];
            CheckOrderLine next = (CheckOrderLine)_bs[second];

            if (current.OrderNumber == next.OrderNumber)
            {
                _bs.RemoveAt(second);
            }
            else
            {
                MessageBox.Show("You must select at least two matching rows to join.");
                return;
            }

            _bs.RaiseListChangedEvents = true;
            _bs.ResetBindings(false);
            index++;
        }

仅当我从下往上选择并且仅基于OrderNumber时才有效。为了防止意外,我真的需要检查两行之间的所有字段。能够在任何方向选择都是奖励。

编辑:我认为我原本不够清楚。

  1. 我有一个方法可以将一行分成2-5个新行。
  2. 我的原始代码可以加入任意数量的行,但仅限于从下到上选择,并且基于OrderNumber
  3. 是否有更有效的方法来比较current.OrderNumber == next.OrderNumber以外的两行?我知道我可以将所有字段添加到if语句中,但我更愿意让它更具可重用性。
  4. 在任何方向上选择都是在所有领域之间进行比较的第二步。

1 个答案:

答案 0 :(得分:1)

仅当您从下往上选择时它才起作用的原因是BindingSource.Current指向最后选择的项目,因此如果您从上到下选择,则您将与未选择的项目进行比较。

您似乎还有一个错误导致firstsecond被撤销。当您可能不想使用时,您正在使用后缀增量操作。

我们说_bs.Position是5;

int first = _bs.Position;  // first is now 5
int second = first++;  // postfix increment: second is now 5, first is now 6

正如documentation所说,

  

操作的结果是操作数之前的值   已增加

所以你真的这样做了:

second = first;
first = first + 1;

看起来你只是想这样做:

second = first + 1;

它可能在这种情况下没有任何区别,但它使代码相当混乱。


有许多方法可以解决您的问题。这可能是一种更直接,更容易理解的方式:

int count = dgv.SelectedRows.Count;

// DataGridView.SelectedRows is reverse order, so the first selected item is the last item in the list
var firstSelected = dgv.SelectedRows[count - 1].DataBoundItem as CheckOrderLine;
int firstOrderNumber = firstSelected.OrderNumber;

// starting at second-last item (second selected row)
for (int i = count - 2; i >= 0; i--)
{
    var row = dgv.SelectedRows[i];
    var item = row.DataBoundItem as CheckOrderLine;
    if (item.OrderNumber == firstOrderNumber)
        dgv.Rows.Remove(row);
}

为了简单起见,我省略了更新剩余的行以及任何错误检查。

请注意,即使匹配的行不连续,这也会起作用。这取决于你是否允许。

相关问题