【问题标题】:C# Logic failure in dynamic Controls Code动态控件代码中的 C# 逻辑故障
【发布时间】:2017-11-14 11:29:21
【问题描述】:

我对编程很陌生,所以请不要因为脏代码而讨厌我。如果你有一些适合我的建议,我很想得到初学者友好的建议。对不起我的英语我希望你能理解我,也许你自己试试我的代码来看看我的问题。

我有一个带有组框的 Windows 窗体,组框中是一个面板。直接在表单中有一个按钮,可以将带有一组控件的行(在我的情况下,1 行有 2 个按钮。一个现在没有意义,一个用于删除该行)到面板中。

一行中的按钮应该有相同的标签(1-X)

所以用我的 2 个按钮组添加一行“很好”。我的下一个计划是当我按下一行中的删除按钮时删除该行。

删除我用控制标签标识的行后,我想减少名称的数值(例如,如果我删除第 1 行,则从函数 2 到函数 1)、每个按钮的标签和文本具有更高标记值比被删除的行号。所以我猜哪里有失败。

添加和删除工作正常。但如果我想再次添加一行,则不是。我必须多次单击才能添加新行。

解释我想做什么:

|添加行按钮| //已经点击了4次 控制板 { |功能一| --- |删除 1| |功能二| --- |删除2| |功能3| --- |删除 3| |功能4| --- |删除4| } // 点击 |删除 2| // 删除第 2 行,将行号较大的行重命名为已删除行,文本、标签和名称的值减小 // 所以第 2 行被删除,函数 3 变为函数 2,函数 4 变为函数 3 控制板 { |功能一| --- |删除 1| |功能二| --- |删除2| |功能3| --- |删除 3| }

但他们大多“从不”重命名,就像我在我的代码/头脑中计划的那样。只有有时在“玩”它时它会重命名一个按钮

我的代码如下所示(从带有名为 pnl 的面板和 Row AddButton 的 Winform 开始):

    public partial class Form1 : Form
{
    int rowCount = 0;
    int lastY;

    public Form1()
    {
        InitializeComponent();
    }

    private void btnAdd_Click(object sender, EventArgs e)
    {
        AddRow();
    }

    public void AddRow()
    {
        rowCount++;
        label1.Text = rowCount.ToString();
        #region Create the Function Button in a row
        Button btnFunction = new Button();
        if (rowCount == 1)
        {
            btnFunction.Location = new Point(10, 5);
        }
        else if (rowCount > 1)
        {
            Control[] letztesY = pnl.Controls.Find($"btnFunction{rowCount - 1}", true);

            foreach (var button in letztesY)
            {
                lastY = button.Location.Y;

            }
            btnFunction.Location = new Point(10, lastY + 25);
        }
        else
        {
            MessageBox.Show("Unerwarteter Fehler");
        }

        btnFunction.Name = "btnFunction" + rowCount;
        btnFunction.Tag = rowCount;
        btnFunction.Text = "Function " + rowCount.ToString();
        pnl.Controls.Add(btnFunction);
        #endregion

        #region Create the Delete Row Button in a row
        Button btnDelete = new Button();
        if (rowCount == 1)
        {
            btnDelete.Location = new Point(85, 5);
        }
        else if (rowCount > 1)
        {
            Control[] letztesY = pnl.Controls.Find($"btnDelete{rowCount - 1}", true);

            foreach (var button in letztesY)
            {
                lastY = button.Location.Y;

            }
            btnDelete.Location = new Point(85, lastY + 25);
        }
        else
        {
            MessageBox.Show("Fail");
        }

        btnDelete.Name = "btnDelete" + rowCount;
        btnDelete.Tag = rowCount;
        btnDelete.Text = "Delete " + rowCount.ToString();
        btnDelete.Click += new EventHandler(deleteCallerRow);
        pnl.Controls.Add(btnDelete);
        #endregion

    }

    private void deleteCallerRow(object sender, EventArgs e)
    {
        rowCount--;
        label1.Text = rowCount.ToString();

        Button delCaller = sender as Button;

        #region DeltePressedRowDelButton
        Control[] toBeRemovedDelButtons = pnl.Controls.Find($"btnDelete{delCaller.Tag}", true);                   
        foreach (var delBtn in toBeRemovedDelButtons)
        {
            pnl.Controls.Remove(delBtn);
            delBtn.Dispose();

        }

        Control[] toBeRemovedFunctionButtons = pnl.Controls.Find($"btnFunction{delCaller.Tag}", true);
        foreach (var funcBtn in toBeRemovedFunctionButtons)
        {
            pnl.Controls.Remove(funcBtn);
            funcBtn.Dispose();

        }
        #endregion

        #region Decrease Numbers in Buttons Texts, Tags and Names
        Control[] toBeRenamedDeleteButtons = pnl.Controls.Find($"btnDelete", true);
        foreach (var db in toBeRenamedDeleteButtons)
        {
            if (Convert.ToInt32(db.Tag) > Convert.ToInt32(delCaller.Tag) )
            {
                db.Name = "btnDelete" + Convert.ToString(Convert.ToInt32(db.Tag) - 1);
                db.Tag = Convert.ToInt32(db.Tag) - 1;
                db.Text = "Delete " + Convert.ToString(Convert.ToInt32(db.Tag) - 1);
            }
        }

        Control[] toBeRenamedFunctionButtons = pnl.Controls.Find($"btnFunction", true);
        foreach (var fb in toBeRenamedFunctionButtons)
        {
            if (Convert.ToInt32(fb.Tag) > Convert.ToInt32(delCaller.Tag))
            {
                fb.Name = "btnFunction" + Convert.ToString(Convert.ToInt32(fb.Tag) - 1);
                fb.Tag = Convert.ToInt32(fb.Tag) - 1;
                fb.Text = "Function " + Convert.ToString(Convert.ToInt32(fb.Tag) - 1);
            }

        }
        #endregion


    }
}

所以我现在在删除行时没有处理行之间的空闲空间,因为我遇到了重命名问题无法按预期工作。

感谢您的建议。

希望你能理解我的问题。

【问题讨论】:

  • 好吧,如果我总是多次删除最后一行,那么 rowCount 在添加和循环此过程时也会起作用。但是如果我删除一些行并添加一些新行,rowCounter 就不再是真的了。

标签: c# winforms dynamic controls panel


【解决方案1】:

在您的代码中发生了几件事,导致您在删除按钮时出现问题。

第一个在这个区块中:

    Button delCaller = sender as Button;

    #region DeltePressedRowDelButton
    Control[] toBeRemovedDelButtons = pnl.Controls.Find($"btnDelete{delCaller.Tag}", true);                   
    foreach (var delBtn in toBeRemovedDelButtons)
    {
        pnl.Controls.Remove(delBtn);
        delBtn.Dispose();

    }

    Control[] toBeRemovedFunctionButtons = pnl.Controls.Find($"btnFunction{delCaller.Tag}", true);
    foreach (var funcBtn in toBeRemovedFunctionButtons)
    {
        pnl.Controls.Remove(funcBtn);
        funcBtn.Dispose();

    }

您将发送者(按钮)存储在 delCaller 中,但是当您在面板中找到它时将其丢弃。然后您继续使用存储的按钮,即使您已经处理了它。您需要将标签存储在另一个变量中,然后再将其丢弃。

第二个在这个区块中:

db.Name = "btnDelete" + Convert.ToString(Convert.ToInt32(db.Tag) - 1);
db.Tag = Convert.ToInt32(db.Tag) - 1;
db.Text = "Delete " + Convert.ToString(Convert.ToInt32(db.Tag) - 1);

您在设置文本之前更改 db.Tag,因此文本将显示一个比您要查找的值低的值。

测试修改删除功能:

    private void deleteCallerRow(object sender, EventArgs e)
    {
        rowCount--;
        label1.Text = rowCount.ToString();

        Button delCaller = sender as Button;
        int callerTagNo = (int)delCaller.Tag;

        #region DeltePressedRowDelButton
        Control[] toBeRemovedDelButtons = pnl.Controls.Find("btnDelete" + callerTagNo, true);
        foreach (var delBtn in toBeRemovedDelButtons)
        {
            pnl.Controls.Remove(delBtn);
            delBtn.Dispose();

        }

        Control[] toBeRemovedFunctionButtons = pnl.Controls.Find("btnFunction" + callerTagNo, true);
        foreach (var funcBtn in toBeRemovedFunctionButtons)
        {
            pnl.Controls.Remove(funcBtn);
            funcBtn.Dispose();

        }
        #endregion

        #region Decrease Numbers in Buttons Texts, Tags and Names
        foreach (Control b in pnl.Controls)
        {
            if(b.Name.Contains("btnDelete"))
            {
                if(callerTagNo < (int)b.Tag)
                {
                    //Rename
                    int newTag = (int)b.Tag - 1;
                    b.Name = "btnDelete" + newTag;
                    b.Tag = newTag;
                    b.Text = "Delete " + newTag;
                }
            }
            else if(b.Name.Contains("btnFunction"))
            {
                if(callerTagNo < (int)b.Tag)
                {
                    //Rename
                    int newTag = (int)b.Tag - 1;
                    b.Name = "btnFunction" + newTag;
                    b.Tag = newTag;
                    b.Text = "Function " + newTag;
                }
            }
        }
        #endregion
    }

注意: 我建议使用控件的 Dock 属性来放置按钮。这将大大简化您添加/删除它们的过程。我会执行以下操作之一:

1) 添加按钮对时,不要将它们添加到主面板 (pnl),而是将它们添加到新面板,然后将该面板添加到主面板,并将 Dock 属性设置为顶部。这将允许它们在添加或删除时自动移动。有很多关于停靠和 WinForms 的资源可以帮助您开始这方面的工作,例如 here

2) 使用具有 2 列且 Dock 设置为 Fill 的 TableLayoutPanel,这也会自动移动内容并且稍微不那么复杂。

祝你好运。

【讨论】:

  • 你帮了我很多忙。感谢您抽出宝贵时间。你确实给了我所希望的帮助。给这家伙一块饼干 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-01
相关资源
最近更新 更多