2014-12-06 24 views
0

新手程序員在經過數小時的搜索之後已經讓我難倒了。在一個新的TabPage中引用一個動態創建的控件

我在使用按鈕按下時在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」+ enemyNumber的TextBox,我不知道如何去做。

我所做的是創建「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; 
     } 
    } 

這一次我得到了一個錯誤:無法將類型「System.Windows.Forms.Control的[]」到「System.Windows.Forms.TextBox」

我覺得我在這裏的第二種方法可能更接近正確的方式來做到這一點,但顯然我仍然沒有做到。我通過搜索關於stackoverflow和msdn.microsoft的信息學到了很多東西,但沒有任何東西讓我過去這個問題。

任何幫助,將不勝感激。

回答

0

基本上是與你的第二個學嘗試的問題是,enemyTab.Controls.Find("enemyNameBox" + 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; 
    } 
} 

,但它不是百威這樣做似乎每次用戶添加一個新的標籤頁,將有權同一控制?那麼爲什麼不用你在TabPage上擁有的任何控件創建一個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); 
} 

和代碼從當前選項卡中把文本框可能是如下(你將需要參考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; 
+0

非常感謝!你提出的解決方案的確更容易處理,它的功能就像是一種魅力,正是我所需要的。也許更重要的是,我從中學到了一些新東西。乾杯! :) – 2014-12-07 03:17:59

0

Patrick已經解決了您的根本問題,但我不認爲您需要那裏的循環。在這裏我已經打破了步驟,所以你可以看到需要發生什麼好一點:

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; 
     } 
    } 
相關問題