2012-08-22 51 views
4

我有兩種方法。第一個動態地創建一個表,然後將該表添加到PlaceHolder中。.FindControl總是返回null

private void generateData(){ 
    Table tbl = new Table(); 
    tbl.ID = "table1"; 
    holder_info.Controls.Add(tbl); 
    // ...adding tr's and td's.... 
    // ...adding CheckBox in tds.... 
} 

如果我做.FindControl( 「...」)這個方法裏面,我可以找到使用控制:

CheckBox check = (CheckBox)holder_info.FindControl("checkbox1"); 

這是確定的,但不是我假裝。

在第二種方法中,我想檢查用戶是否選中了checkBox並執行了某些操作,但找不到控件(它始終返回null)。

protected void saveInfo_Click(object sender, ImageClickEventArgs e) 
{ 
    CheckBox check = (CheckBox)holder_info.FindControl("checkbox1"); 
    if(check.checked){ ... } 
} 

另外,如果我試圖找到控件「table1」,我會得到null。

爲什麼會發生這種情況?

+1

@Shyju - 肯定。這裏是:[真正理解動態控制](http://tinyurl.com/yfc66o) – Oded

回答

3

FindControl()只發現直接的孩子,而不是那些孩子的孩子。

要做你想做的事,你需要寫一個例程到recursively find child controls

+0

我試過了,但我有一個巨大的問題。當我通過我的holder_info時,他是空的!如果我做holder_info.Controls.Count它返回0! – oteal

+0

然後,您需要更具體地說明您在哪裏調用FindControl()。它不是在你添加這些項目的方法中,而是在你的問題中隱含的,而是在回發期間,那麼它將是空的。 –

+0

yap。這就是我在帖子中說的!如果我用同樣的方法做,我可以得到控制權,但是如果它不是我有空... – oteal

1

正如Pranay解釋的,這是因爲您正在動態添加控件。您需要重建頁面,因爲它在回發之前。此外,當涉及到記住之前顯示的信息時,表格控件不是一個好的網頁控件。使用Repeater,DataList或DataGrid可能會更好。比較可在Deciding When to Use the DataGrid, DataList or Repeater(MSDN)中獲得。

爲了演示,我可以展示一個關於如何實現Repeater的簡短示例,因爲這是簡單的IMO控件之一。因此,不要在回發中添加表格(如點擊按鈕),只需在標記中添加中繼器,並在您想要顯示數據時將其設置爲可見。這樣,您甚至不必擔心動態控件,它在您需要時就在那裏。

因此,帶複選框的中繼器的基本標記如下。您可以看到,該表是手動構建的(如果您不想這樣做,可以使用DataGrid)。現在,你可以有一個類,這是你的模型,是這樣的:

public class Person { 
    public Person() { } 

    public Person(Guid id, string name, string company) { 
    this.Uid = id; 
    this.Name = name; 
    this.Company = company; 
    } 

    public Guid Uid { get; set; } 

    public string Name { get; set; } 

    public string Company { get; set; } 
} 

而一個視圖模型類,「適應需求」的觀點(如在你的網頁控制)。注意額外的屬性IsChecked,它不應該是模型的一部分(如何檢查一個人?),但它適合viewmodel類。

public class PersonViewModel { 
    private Person model; 
    public PersonViewModel(Person model) { 
     this.model = model; 
    } 

    public Guid Uid { get { return model.Uid; } } 

    public string Name { get { return model.Name; } } 

    public string Company { get { return model.Company; } } 

    public bool IsChecked { get; set; } 
} 

好的,等到後面的代碼。當使用中繼器控制時,您需要將其綁定到列表。從IEnumerable繼承的東西的實例將會很好,所以你需要把它連接起來。

在您的代碼頁面後面添加這些方法。

protected override void OnInit(EventArgs e) { 
    base.OnInit(e); 
    mailinglists.DataBinding += bindMyTable; 
} 

protected override void OnLoad(EventArgs e) { 
    base.OnLoad(e); 
    if (!Page.IsPostBack) { 
     DataBind(); 
    } 
} 

private void bindMyTable(object sender, EventArgs e) { 
    // Are the conditions set for adding data to the table? 
    if (conditionsMet()) { 
     myTable.DataSource = getDataSource(); 
    } 
} 

private IEnumerable<PersonViewModel> getDataSource() { 
    List<PersonViewModel> view = new List<PersonViewModel>(); 
    view.Add(new PersonViewModel(new Person() { Uid = Guid.NewGuid(), Name = "Example", Company = "Co" })); 
    return view; 
} 

現在,你只需要調用myTable.DataBind()只要條件滿足,說,當你點擊一個按鈕。當你點擊一個按鈕,需要檢查哪些複選框被選中,則可以使用repeater.Items屬性迭代他們,這樣的事:

private void onValidatePage() { 
    List<Guid> checks = new List<Guid>(); 
    foreach (RepeaterItem repeatitem in myTable.Items) { 
     string uid = ((HiddenField)repeatitem.FindControl("uidfield")).Value; 
     bool value = ((CheckBox)repeatitem.FindControl("valuefield")).Checked; 
     if (value) { 
      checks.Add(new Guid(uid)); 
     } 
    } 
    // Now "checks" hold all the id's of the checked items 
}