我有两个方法。第一个方法动态创建一个表,然后将该表添加到一个PlaceHolder中。
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。
这一切为什么要发生?
发布于 2012-08-22 23:57:53
这是因为您正在动态地向页面添加一个控件,当您单击按钮页面时,会得到一个回发并删除动态添加的控件。这就是为什么它在按钮单击事件中找不到checkbox控件的原因。
对于动态控件,请查看文章 (代码项目)。
发布于 2012-08-22 23:58:54
FindControl()只查找直接的子项,而不是这些子项的子项。
要执行您想要的操作,您需要向recursively find child controls编写一个例程。
发布于 2012-08-23 00:59:42
正如Pranay解释的那样,这是因为您正在动态添加控件。您需要将页面重新生成为回发前的状态。此外,当需要记住之前显示的信息时,Table控件不是一个好的was控件。你使用中继器、DataList或DataGrid可能会更走运。对比可在微软( )网站上找到。
为了演示,我可以展示一个简短的示例,说明如何实现转发器,因为这是IMO控件中的一个简单控件。因此,不需要在回发中添加表(例如单击按钮),只需在标记中添加中继器,并在需要显示数据时将其设置为可见。这样,你甚至不必为动态控件而烦恼,它在你需要的时候就在那里。
因此,带有复选框的中继器的基本标记如下所示。
<asp:Repeater ID="myTable" runat="server">
<HeaderTemplate>
<table cellpadding="4" cellspacing="0">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Company</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:HiddenField ID="uidfield" Value='<%# Eval("Uid") %>' runat="server" />
<asp:CheckBox ID="valuefield" Checked='<%# Eval("IsChecked") %>' runat="server" />
</td>
<td>
<asp:Label Text='<%# Eval("Name") %>' runat="server" />
</td>
<td>
<asp:Label Text='<%# Eval("Company") %>' runat="server" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody> </table>
</FooterTemplate>
</asp:Repeater>正如您所看到的,该表是手动构建的(如果您不想这样做,可以改用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,它不应该是模型的一部分(如何检查人员?),但它很适合在视图模型类中。
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
}https://stackoverflow.com/questions/12076952
复制相似问题