C# 在新选项卡页中引用动态创建的控件

C# 在新选项卡页中引用动态创建的控件,c#,winforms,C#,Winforms,经过数小时的搜索,这里的新手程序员让我感到困惑 在运行时按按钮创建的选项卡中引用控件时遇到问题。基本上,我有一个桌面RPG计算器,使用Windows窗体,它有一个tabControl保存tab页,每个tab页保存用户输入的用于计算的单个敌人的统计数据 问题是,我希望用户能够单击一个按钮来生成一个新的敌人标签页。这是我用文本框生成敌人标签页的代码 int enemyNumber = 0; // Creates a new Enemy Tab private void bu

经过数小时的搜索,这里的新手程序员让我感到困惑

在运行时按按钮创建的选项卡中引用控件时遇到问题。基本上,我有一个桌面RPG计算器,使用Windows窗体,它有一个tabControl保存tab页,每个tab页保存用户输入的用于计算的单个敌人的统计数据

问题是,我希望用户能够单击一个按钮来生成一个新的敌人标签页。这是我用文本框生成敌人标签页的代码

    int enemyNumber = 0;

    // Creates a new Enemy Tab
    private void button2_Click_1(object sender, EventArgs e)
    {

        // Create a new TabPage
        var newTabPage = new TabPage()
        {
            Text = "Enemy " + enemyNumber,
        };

        // Add Enemy Name Box
        var newEnemyNameBox = new TextBox()
        {
            Name = "enemyNameBox" + enemyNumber,
            Text = "",
            Location = new Point(127, 11),
            Size = new Size(133, 20)
        };

        // Add the controls to the new Enemy tab
        newTabPage.Controls.Add(newEnemyNameBox);

         // Add the TabPage to the TabControl
        tabControl1.TabPages.Add(newTabPage);

        // Increases the enemy's "reference number" by 1
        // So that enemy tabs will be generated in order enemyTab0, enemyTab1, etc.
        enemyNumber += 1;
    }
这一切都很好。不幸的是,在这一点之后,事情变得很糟糕。我需要引用名为enemyNameBox+enemyNumber的文本框,但我不知道该怎么做

我所做的是创建archVariables来存储选择的任何敌人选项卡中的值,然后在程序的计算中使用适当的archVariable。艾:阿奇尼玛名字。其思想是,无论用户当前在哪个选项卡上被选中,都将通过SelectedIndex确定该页面的文本框用于程序的输出

以下是我在调查此事后尝试过的两件事:

    // Attempt 1
    private void defendCalcButton_Click(object sender, EventArgs e) 
    {
       for (int i = 0; i < tabControl1.SelectedIndex; i++)
       {
           archEnemyNameBox = ((TextBox)Controls["enemyNameBox" + i]).Text;
       }
    }
当我按下按钮时,这段代码只是抛出一个NullReferenceException。因此,在研究了更多之后,我尝试了以下方法:

    // Attempt 2
    private void defendCalcButton_Click(object sender, EventArgs e) 
    {
       for (int i = 0; i < tabControl1.SelectedIndex; i++)
       {
           TextBox tb2 = new TextBox();
           tb2 = ((TextBox)(enemyTab.Controls.Find("enemyNameBox" + i, true)));
           archEnemyNameBox = tb2.Text;
       }
    }
这次我遇到一个错误:无法将类型“System.Windows.Forms.Control[]”转换为“System.Windows.Forms.TextBox”

我觉得我在这里使用的第二种方法可能更接近于正确的方法,但显然我仍然没有做到这一点。通过搜索stackoverflow和msdn.microsoft上的信息,我学到了很多东西,但没有任何东西让我克服这个问题


任何帮助都将不胜感激。

基本上,第二次尝试的问题是enemyTab.Controls.FindenemyNameBox+i,true返回控件数组Control[],您正试图将其转换为控件,这就是问题所在,您应该获取该数组中的第一个控件,然后将其转换为控件,因此应如下所示:

private void defendCalcButton_Click(object sender, EventArgs e) 
{
   for (int i = 0; i < tabControl1.SelectedIndex; i++)
   {
       TextBox tb2 = new TextBox();
       tb2 = ((TextBox)(enemyTab.Controls.Find("enemyNameBox" + i, true)[0]));
       archEnemyNameBox = tb2.Text;
   }
}
从当前选项卡中获取文本框的代码如下,您需要引用LINQ

using System.Linq;


//First Lets create this property, it should return the selected EnemyTabUserControl inside the tabControl
public EnemyTabUserControl CurrentTab {
    get { 
         return tabControl1.SelectedTab.Controls.OfType<EnemyTabUserControl>().First();
    }
}


// then if we make the textbox you want to reference from outside the code we can do this
CurrentTab.NameOfTheTextBox;

帕特里克已经解决了你的基本问题,但我认为你根本不需要这个循环。在这里,我已将步骤分解,以便您可以看到需要更好地进行的操作:

    private void defendCalcButton_Click(object sender, EventArgs e) 
    {
        Control[] matches = this.Controls.Find("enemyNameBox" + tabControl1.SelectedIndex.ToString(), true);
        if (matches.Length > 0 && matches[0] is TextBox)
        {
            TextBox tb = (TextBox)matches[0];
            archEnemyNameBox = tb.Text;
        }
    }

非常感谢!你建议的解决方案确实更容易处理,而且效果很好,这正是我所需要的。也许更重要的是,我从中学到了一些新东西。干杯
    private void defendCalcButton_Click(object sender, EventArgs e) 
    {
        Control[] matches = this.Controls.Find("enemyNameBox" + tabControl1.SelectedIndex.ToString(), true);
        if (matches.Length > 0 && matches[0] is TextBox)
        {
            TextBox tb = (TextBox)matches[0];
            archEnemyNameBox = tb.Text;
        }
    }