在新TabPage中引用动态创建的控件

时间:2014-12-06 19:28:20

标签: c# winforms

经过几个小时的搜索,这里的新手程序员让我感到难过。

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

问题在于我希望用户能够单击按钮以生成新的敌人标签页。这是我使用TextBox生成敌人标签页的代码。

    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"的TextBox。 + enemyNumber,我不知道怎么做。

我所做的是创造" archVariables"存储选择的任何敌人选项卡中的值,然后在程序的计算中使用适当的archVariable。 IE:archEnemyName。我们的想法是,无论当前选择用户的任何标签(通过SelectedIndex确定),该页面上的TextBox都将用于该程序的输出。

以下是我在研究此事后尝试过的两件事:

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

这次我得到一个错误:无法转换类型&#39; System.Windows.Forms.Control []&#39;到&#39; System.Windows.Forms.TextBox&#39;

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

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:0)

基本上你的第二次尝试的问题是enemyTab.Controls.Find("enemyNameBox" + i, true)返回一个控件数组Control[]而你试图将它转换为控件这里是问题,你应该得到第一个控件该数组然后将其转换为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;
   }
}

但这并不是BestWay这样做似乎每次用户添加新的tabPage它会有相同的控件吗?那么为什么不用TabPage上的任何Control创建一个userControl呢?所以当你按下用户按下以添加一个新标签时,你的代码应该是这样的:

private void CreateNewEnemyTab()
{
    var newTabPage = new TabPage()
    {
        Text = "Enemy " + enemyNumber,
    };
    EnemyTabUserControl enemyTab = new EnemyTabUserControl(enemyNumber);
    here the EnemyTabUserControl should have all the components you need;
    newTabPage.Controls.Add(enemyTab);
    tabControl1.TabPages.Add(newTabPage);
}

以及从当前选项卡中引入TextBox的代码可能如下(您将需要引用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;

答案 1 :(得分:0)

帕特里克解决了你的根本问题,但我认为你根本不需要循环。在这里,我已经打破了步骤,以便您可以更好地了解需要发生的事情:

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