TableLayoutPanel删除空行

时间:2012-11-03 02:18:59

标签: c# winforms tablelayoutpanel

我正在尝试从TableLayoutPanel中删除所有空行。到目前为止,我已经能够这样做了

private void RemoveEmptyRows()
{
    for (int row = 0; row < tablePanel.RowCount - 1; row++)
    {
        bool hasControl = false;
        for (int col = 0; col < tablePanel.ColumnCount; col++)
        {
            if (tablePanel.GetControlFromPosition(col, row) != null)
            {
                hasControl = true;
                break;
            }
        }
        if (!hasControl)
            tablePanel.RowStyles.RemoveAt(row);
    }
}

有更好的方法吗?我的做法似乎太不堪重负了。

1 个答案:

答案 0 :(得分:5)

我不会说有更好的方法,只是你的代码有一些缺陷。你可以依靠Linq使它更简洁,但可能不够优雅,而且可读性较差,而且根本不可调试,因为你不应该使用太多的Linq来做这种事情(我个人而言)喜欢它!)。您应该对现有代码执行以下操作:

private void RemoveEmptyRows()
{
    for (int row = tablePanel.RowCount -1; row >= 0; row--)
    {
        bool hasControl = false;
        for (int col = 0; col < tablePanel.ColumnCount; col++)
        {
            if (tablePanel.GetControlFromPosition(col, row) != null)
            {
                hasControl = true;
                break;
            }
        }

        if (!hasControl)
        {
            tablePanel.RowStyles.RemoveAt(row);
            tablePanel.RowCount--;
        }
    }
}
  1. 您应该从上到下进行迭代,因为RowCount在您的外部foreach循环中对row进行评估时可能会发生变化。

  2. 您只需在执行RowStyle后删除RowCount--即可删除该行。

  3. 这是Linq版本:

    Enumerable.Range(0, tablePanel.RowCount)
        .Except(tablePanel.Controls.OfType<Control>()
            .Select(c => tablePanel.GetRow(c)))
        .Reverse()
        .ToList()
        .ForEach(rowIndex =>
         {
             tablePanel.RowStyles.RemoveAt(rowIndex);
             tablePanel.RowCount--;
         });
    

    要解决这个问题(如果你不熟悉Linq):

    var listOfAllRowIndices = Enumerable.Range(0, tablePanel.RowCount);
    var listOfControlsInTableLayoutPanel = tablePanel.Controls.OfType<Control>();
    var listOfRowIndicesWithControl = listOfControlsInTableLayoutPanel.Select(c => tablePanel.GetRow(c));
    var listOfRowIndicesWithoutControl = listOfAllRowIndices.Except(listOfRowIndicesWithControl);
    var listOfRowIndicesWithoutControlSortedInDescendingOrder = listOfRowIndicesWithoutControl.Reverse(); //or .OrderByDescending(i => i);
    

    然后:

    listOfRowIndicesWithoutControlSortedInDescendingOrder.ToList().ForEach(rowIndex =>
    {
        tablePanel.RowStyles.RemoveAt(rowIndex);
        tablePanel.RowCount--;
    });
    

    另一个可能更具可读性但效率更低的Linq版本:

    Enumerable.Range(0, tableLayoutPanel1.RowCount)
        .Where(rowIndex => !tableLayoutPanel1.Controls.OfType<Control>()
            .Select(c => tableLayoutPanel1.GetRow(c))
            .Contains(rowIndex))
        .Reverse()
        .ToList()
        .ForEach(rowIndex =>
        {
            tablePanel.RowStyles.RemoveAt(rowIndex);
            tablePanel.RowCount--;
        });