2012-11-03 6 views
4

J'essaie de supprimer toutes les lignes vides d'un TableLayoutPanel. Jusqu'à présent, j'ai été capable de le faire de cette façonTableLayoutPanel supprimer des lignes vides

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); 
    } 
} 

Y a-t-il une meilleure façon de faire? Mon approche semble trop dépassée.

Répondre

5

Je ne dirais pas qu'il existe un meilleur moyen, sauf que votre code a quelques failles. Vous pouvez compter sur Linq pour le rendre un peu plus concis mais cela peut être inélégant et moins lisible et pas débogable du tout puisque vous ne devriez pas utiliser trop de Linq pour faire ce genre de chose (Personnellement, je l'aime bien!). Voici ce que vous devez faire pour votre code existant:

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. Vous devez itérer de haut en bas depuis RowCount peut changer lors de l'évaluation contre row dans votre boucle foreach externe. Vous devez également supprimer la ligne après avoir supprimé le RowStyle simplement en faisant RowCount--.

Voici une version 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--; 
    }); 

Pour décomposer à ce qu'il fait (si vous n'êtes pas familier avec 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); 

Et puis:

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

Un autre la version LINQ qui peut être plus facile à lire, mais moins efficace:

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--; 
    }); 
+0

+1 pour itérer-de bas en haut .... Personnellement je déteste LINQ, pour aucune autre raison que la syntaxe est si dense que je trouve c'est imprenable, et donc mes solutions LINQ ont tendance à prendre plus de temps à se développer et à être buggées pour démarrer! Typiquement, je trouve que la version non-linq est plus rapide à écrire et plus facile à maintenir de toute façon ... mais peut-être que j'ai juste besoin de plus de practive avec LINQ, ce que j'évite en ne le préférant pas. Soupir. – corlettk

+2

@corlettk Linq est cool, et j'adore ça. Le vrai avantage pour moi est que cela me libère de l'écriture de code répétitif-évident pour des tâches simples. Mais toi je n'aime pas Linq pour les tâches complexes. Plusieurs instructions linq le rendent difficile à comprendre. Par exemple j'aime le code comme 'myList.Where (ceci et cela) .Sélectionnez (untel) .OrderBy (condition)' qui est si simple et lisible, où je déteste le code comme 'myList.GroupBy (condition) .ToDictionary (sélecteur, sélecteur, beaucoup d'autres sélecteurs) .Distinguable() .Zip (un autre dictionnaire complexe) ' – nawfal

+0

Merci pour l'approche ascendante. Je connaissais aussi un comportement bizarre. Je vais essayer ça. – nilobarp

Questions connexes