I would not say that there is a better way, except that your code has some disadvantages. You can rely on Linq to make it a little more concise, but it can be inelegant as well as less readable and not debugable at all, since you shouldn't use too much Linq to do this kind of thing (I personally like it at least!). Here is what you should do with existing code:
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--; } } }
You have to iterate over from top to bottom, as the RowCount may change when evaluating it against row in your outer foreach loop.
You should also delete the row after removing RowStyle by simply doing RowCount-- .
Here is the Linq version:
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--; });
Break it down into what it does (if you are not familiar with 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();
And then:
listOfRowIndicesWithoutControlSortedInDescendingOrder.ToList().ForEach(rowIndex => { tablePanel.RowStyles.RemoveAt(rowIndex); tablePanel.RowCount--; });
Another version of Linq, which may be more readable, but less effective:
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--; });
source share