.FindControl总是返回null
我有两种方法。第一个动态地创建一个表,然后将该表添加到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。
为什么会发生这种情况?
这是因为您正在动态添加控件到页面,并且当您单击按钮页时获取回发并删除动态添加的控件。这就是为什么它无法在按钮单击事件中找到复选框控件。
对于动态控制,请检查文章Retaining State for Dynamically Created Controls in ASP.NET applications(代码项目)。
正如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
}
@Shyju - 肯定。这里是:[真正理解动态控制](http://tinyurl.com/yfc66o) – Oded