TableLayoutPanel删除空行

nil*_*arp 4 c# tablelayoutpanel winforms

我正在尝试从a中删除所有空行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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

naw*_*fal 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--;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 您应该从上到下进行迭代,因为在外部foreach循环中进行RowCount评估时可能会发生变化row.

  2. 你也应该去掉后删除行RowStyle做简单的RowCount--.

这是一个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--;
     });
Run Code Online (Sandbox Code Playgroud)

要打破它的作用(如果你不熟悉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);
Run Code Online (Sandbox Code Playgroud)

然后:

listOfRowIndicesWithoutControlSortedInDescendingOrder.ToList().ForEach(rowIndex =>
{
    tablePanel.RowStyles.RemoveAt(rowIndex);
    tablePanel.RowCount--;
});
Run Code Online (Sandbox Code Playgroud)

另一个可能更具可读性但效率更低的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--;
    });
Run Code Online (Sandbox Code Playgroud)

  • @corlettk Linq很酷,我喜欢它.对我来说真正的好处是它让我免于为简单的任务编写重复明显的代码.但是我不喜欢Linq的复杂任务.多个linq语句使其难以理解.例如,我喜欢`myList.Where(this and that).Select(so so so).OrderBy(condition)`这样的代码非常简单易读,我讨厌`myList.GroupBy(condition).ToDictionary (选择器,选择器,地狱很多其他选择器).Distinct().Zip(另一个复杂的字典)` (2认同)