动态控制代码中的 C# 逻辑故障

C# Logic failure in dynamic Controls Code

我是编程新手,所以请不要因为脏代码而恨我。如果你有一些适合我的建议,我很乐意获得初学者友好的建议。对不起我的英语我希望你能理解我,也许你自己试试我的代码看看我的问题。

我有一个带有分组框的Windows表单,分组框中有一个面板。直接在表单中有一个按钮,用于将带有一组控件的行添加到面板中(在我的例子中,1 行有 2 个按钮。一个现在没有意义,一个用于删除该行)。

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

所以用我的 2 个按钮集添加一行是可行的 "fine"。我的下一个计划是当我从一行中按下删除按钮时删除该行。

删除我用控制标签识别的行后,我想减少名称的数字值(例如,如果我删除第 1 行,则功能 2 到功能 1)、标签和每个按钮的文本具有比被删除的行号更高的标签值。所以我猜是某处失败了。

添加和删除工作正常。但如果我想再次添加一行就不行了。我必须点击多次才能添加新行。

解释一下我想做什么:

|ADD ROW BUTTON| //Clicked 4 Times already

PANEL
{
|Function 1| --- |Delete 1|
|Function 2| --- |Delete 2|
|Function 3| --- |Delete 3|
|Function 4| --- |Delete 4|
}



// Clicking |Delte 2|
// Removed Row 2 and rename those which have bigger Row number as the deleted row with decreased value for the Text, Tag & Name
// So row 2 gets removed, Function 3 becomes Function 2 and Function 4 becomes Function 3

PANEL
{
|Function 1| --- |Delete 1|
|Function 2| --- |Delete 2| 
|Function 3| --- |Delete 3|
}

但他们大多 "never" 重命名就像我在 code/mind 中计划的那样。只是有时候 "playing" 用它会重命名一个按钮

我的代码如下所示(从带有名为 pnl 的面板和行添加按钮的 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


    }
}

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

感谢您的建议。

希望你能理解我的问题。

您的代码中发生的一些事情会导致按钮删除期间出现问题。

第一个在这个块中:

    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 属性 来放置按钮。这将大大简化您的 adding/removing 个。我会执行以下操作之一:

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

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

祝你好运。