【问题标题】:Removing a specific Row in TableLayoutPanel删除 TableLayoutPanel 中的特定行
【发布时间】:2013-03-20 21:36:23
【问题描述】:

我有 TableLayoutPanel,我以编程方式将 Rows 添加到其中。用户基本上选择了一个属性,然后将其与一些控件一起显示在表格中。我想我在这里有一个普遍的理解问题,我会尝试解释它。

每一行中的一个控件是一个“删除”按钮。该按钮应该删除它所在的行。我所做的是向按钮添加一个事件处理程序并设置当前行数。

deleteTalent.Click += (sender, e) => buttonClickHandler(numberOfRows);

处理程序代码:

private void buttonClickHandler(int rowCount)
{
    int count = rowCount - 1;
    for (int i = count; i < (count + 5); i++)
    {
        balanceTable.Controls.RemoveAt(count);
    }
    balanceTable.RowStyles.RemoveAt(count);
    balanceTable.RowCount--;

}

我看了好几个小时,然后到处玩。但我找不到有效的清洁解决方案。我对 C# 也很陌生

这是创建新行的完整函数:

private void addBalanceItems(ToolStripMenuItem item)
{
    int numberOfRows = balanceTable.RowCount;
    if (numberOfRows > 1)
    {
        balanceTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.AutoSize));

    }
    balanceTable.Height = numberOfRows * 45;
    Steigerungsrechner rechner = new Steigerungsrechner();
    string tag = item.Tag.ToString();

    //change that asap :(
    if (tag == "A") { rechner.column = 1; }
    if (tag == "B") { rechner.column = 2; }
    if (tag == "C") { rechner.column = 3; }
    if (tag == "D") { rechner.column = 4; }
    if (tag == "E") { rechner.column = 5; }
    if (tag == "F") { rechner.column = 6; }
    if (tag == "G") { rechner.column = 7; }
    if (tag == "H") { rechner.column = 8; }

    Label talentName = new Label();
    talentName.Text = item.Text;
    talentName.Height = standardHeight;
    talentName.TextAlign = ContentAlignment.MiddleLeft;
    talentName.AutoSize = true;
    Label cost = new Label();
    cost.TextChanged += (sender, e) => costChangeHandler(cost);
    cost.Height = standardHeight;
    cost.TextAlign = ContentAlignment.MiddleLeft;
    TextBox startValue = new TextBox();
    startValue.TextChanged += (sender, e) => startValueChangeHandler(rechner, startValue, cost);
    startValue.Height = standardHeight;
    startValue.TextAlign = HorizontalAlignment.Center;
    TextBox endValue = new TextBox();
    endValue.TextChanged += (sender, e) => endValueChangeHandler(rechner, endValue, cost);
    endValue.Height = standardHeight;
    endValue.TextAlign = HorizontalAlignment.Center;
    Button deleteTalent = new Button();
    deleteTalent.Text = "x";
    deleteTalent.Click += (sender, e) => buttonClickHandler(numberOfRows);
    deleteTalent.Height = standardHeight;

    balanceTable.Controls.Add(talentName);
    balanceTable.Controls.Add(startValue);
    balanceTable.Controls.Add(endValue);
    balanceTable.Controls.Add(cost);
    balanceTable.Controls.Add(deleteTalent);
    balanceTable.Visible = true;
    balanceTable.RowCount++;
}

任何帮助将不胜感激! :)

【问题讨论】:

    标签: c# .net tablelayoutpanel


    【解决方案1】:

    是的,从 TableLayoutPanel 中删除任意行一点也不直观。他们真的把这个设计搞砸了。

    删除行的唯一方法是设置RowCount 属性。仅这一点就够奇怪了。该属性确实看起来应该是只读的,并且每次看到它时,执行此操作的代码对我来说都是错误的。

    但除此之外,这种设计的结果是您无法从中间删除行。重置RowCount 属性只会导致行被从底部截断。

    解决方法有点笨拙,需要多个步骤才能出错:

    1. 从要删除的行中删除控件
    2. 如果适用,请将这些控件移到另一行。
    3. 将要删除的行之后的其他行中的所有控件上移一行。
    4. 最后,通过减小RowCount 属性的值来删除最后一行。

    快速的 Google 搜索显示有人有 written and shared code 声称要这样做。它在 VB.NET 中,但在您的母语中应该是 easily translated

    我承认,众所周知,我只是将要“删除”的行的 RowHeight 设置为 0。这样,自动调整大小就可以为您工作。不过,您可能仍想删除其中包含的控件。

    【讨论】:

    • 只是在这里明确说明,只有当您(至少)隐藏它们包含的所有控件时,最后一行才会被删除。否则RowCount 的更改无效,行仍然可见。
    【解决方案2】:

    这是一个静态类,可以帮助您通过索引删除任何行:

    using System.Windows.Forms;
    
    public static class TableLayoutHelper
    {
        public static void RemoveArbitraryRow(TableLayoutPanel panel, int rowIndex)
        {
            if (rowIndex >= panel.RowCount)
            {
                return;
            }
    
            // delete all controls of row that we want to delete
            for (int i = 0; i < panel.ColumnCount; i++)
            {
                var control = panel.GetControlFromPosition(i, rowIndex);
                panel.Controls.Remove(control);
            }
    
            // move up row controls that comes after row we want to remove
            for (int i = rowIndex + 1; i < panel.RowCount; i++)
            {
                for (int j = 0; j < panel.ColumnCount; j++)
                {
                    var control = panel.GetControlFromPosition(j, i);
                    if (control != null)
                    {
                        panel.SetRow(control, i - 1);
                    }
                }
            }
    
            var removeStyle = panel.RowCount - 1;
    
            if (panel.RowStyles.Count > removeStyle)
                panel.RowStyles.RemoveAt(removeStyle);
    
            panel.RowCount--;
        }
    }
    

    需要提一下:我们通过panel.GetControlFromPosition(...) 获得的控件必须是可见的,否则它将返回null 而不是不可见的控件。

    【讨论】:

    • 如果您想抑制一些可以使用此代码获得的奇怪动画,请使用这两行将代码包装在 RemoveArbitraryRow 中。 panel.SuspendLayout() 和 panel.ResumeLayout().
    • 上述方法调用前使用tableLayoutPanel.SuspendLayout();,方法调用后使用tableLayoutPanel.ResumeLayout(false);tableLayoutPanel.PerformLayout();
    • 非常感谢!我什至把它变成了一个扩展方法(而不是静态类中的方法),并且可以无缝地工作
    【解决方案3】:

    首先移除rowCount的现有控件

    for(int i = 0; i < panel.ColumnCount; i++){
         Control Control = panel.GetControlFromPosition(i, rowCount);
         panel.Controls.Remove(Control);
      }
    

    然后删除行

    panel.RowStyles.RemoveAt(rowCount-1);
    

    【讨论】:

      【解决方案4】:

      删除完整的表格 -

      tableLayoutPanel1.Controls.Clear();
      tableLayoutPanel1.RowStyles.Clear();
      

      再次设置表格的标题 -

                  tableLayoutPanel.RowCount = 1;
                  tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
                  tableLayoutPanel.Controls.Add(new Label() { Text = "MONTH", Font = new Font("Century Gothic", 12, FontStyle.Bold), ForeColor = Color.LightGray }, 0, tableLayoutPanel.RowCount - 1);
                  tableLayoutPanel.Controls.Add(new Label() { Text = "YEAR", Font = new Font("Century Gothic", 12, FontStyle.Bold), ForeColor = Color.LightGray }, 1, tableLayoutPanel.RowCount - 1);
                  tableLayoutPanel.Controls.Add(new Label() { Text = "MEASURED WAFERS", Font = new Font("Century Gothic", 12, FontStyle.Bold), ForeColor = Color.LightGray }, 2, tableLayoutPanel.RowCount - 1);
      

      3 列 - 1 行

      也许有人可以使用我的代码片段,效果很好......

      【讨论】:

      • 您可以通过在设计视图中手动设计表格布局并复制VS生成的代码来获得上面的代码。在你的表名后面查看YourForm.Designer.cs
      【解决方案5】:

      您无法完全删除 tablelayoutpanel 上的一行,但有一个解决方法:

      1. 删除行中的所有控件,如果您知道控件的名称会更容易,因为您可以调用 dispose 方法。
      2. 使用行样式方法将行的高度设置为2px (例如tablelayoutpanel1.Rowstyle(index).height=2

      对我来说,这很有效,无论行索引如何,行都完全折叠了行。

      【讨论】:

      • 为什么将高度设置为2px?为什么不归零以避免边距和最终边界问题?使用 2px 行并不是“完全折叠”。
      猜你喜欢
      • 2013-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-11
      • 2014-09-16
      • 2019-02-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多