我在aspx页面中有一个div Conatining a Panel
<div id="divNameofParticipants" runat="server">
<asp:Panel ID="panelNameofParticipants" runat="server">
</asp:Panel>
</div>
Run Code Online (Sandbox Code Playgroud)
我使用以下代码从代码隐藏动态填充面板:
void btnSubmitCountParticipant_Click(object sender, EventArgs e)
{
StringBuilder sbparticipantName=new StringBuilder();
try
{
int numberofparticipants = Convert.ToInt32(drpNoofparticipants.SelectedValue);
ViewState["numberofparticipants"] = numberofparticipants;
Table tableparticipantName = new Table();
int rowcount = 1;
int columnCount = numberofparticipants;
for (int i = 0; i < rowcount; i++)
{
TableRow row = new TableRow();
for (int j = 0; j < columnCount; j++)
{
TableCell cell = new TableCell();
TextBox txtNameofParticipant = new TextBox();
txtNameofParticipant.ID = "txtNameofParticipant" + Convert.ToString(i);
cell.ID = "cell" + Convert.ToString(i);
cell.Controls.Add(txtNameofParticipant);
row.Cells.Add(cell);
}
tableparticipantName.Rows.Add(row);
panelNameofParticipants.Controls.Add(tableparticipantName);
}
}
catch(Exception ex)
{
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想在codebehind.for中访问这些动态生成的文本框的值,我的代码如下:
public void CreateControls()
{
try
{
//String test1 = test.Value;
List<string> listParticipantName = new List<string>();
if (ViewState["numberofparticipants"] != null)
{
int numberofparticipants = Convert.ToInt32(ViewState["numberofparticipants"]);
for (int i = 0; i < numberofparticipants; i++)
{
string findcontrol = "txtNameofParticipant" + i;
TextBox txtParticipantName = (TextBox)panelNameofParticipants.FindControl(findcontrol);
listParticipantName.Add(txtParticipantName.Text);
}
}
}
catch (Exception ex)
{
}
}
Run Code Online (Sandbox Code Playgroud)
但我无法获得代码隐藏中的值.
TextBox txtParticipantName = (TextBox)panelNameofParticipants.FindControl(findcontrol);
Run Code Online (Sandbox Code Playgroud)
上面的代码无法找到控件,它总是给出null.我做错了.我在页面加载中重新创建了控件,因为回发是无状态但仍然没有成功.
提前致谢
您需要在PreInit中创建不在OnLoad中的动态控件.请参阅此处的文档:https://msdn.microsoft.com/en-us/library/ms178472.aspx
重新/在页面加载时创建控件将导致ViewState不被绑定到控件,因为viewnate绑定在OnLoad之前发生.
正如其他人所说.要创建动态控件,您需要为每个回发和正确的时间执行此操作.要呈现动态控件,请使用Preinit事件.我建议您查看https://msdn.microsoft.com/en-us/library/ms178472(v=vs.80).aspx以了解更多相关信息.
MSDN - PreInit: 使用此事件执行以下操作:检查IsPostBack属性以确定这是否是第一次处理页面. 创建或重新创建动态控件. 动态设置母版页.动态设置Theme属性.读取或设置配置文件属性值.注意注意如果请求是回发,则控件的值尚未从视图状态恢复.如果在此阶段设置控件属性,则其值可能会在下一个事件中被覆盖.
下一个有趣的事件是Preload,它指出:
MSDN - PreLoad 如果需要在Load事件之前对页面或控件执行处理,请使用此事件. 页面引发此事件后,它会为自身和所有控件加载视图状态,然后处理Request实例中包含的所有回发数据.
这意味着在下一个事件Load(Page_Load)中应该加载视图状态,所以在这里你应该能够有效地检查你的值.
您还需要确保启用了视图状态,最简单的可能是在页面级指令中:
<%@Page EnableViewState="True" %>
Run Code Online (Sandbox Code Playgroud)
看看文章https://msdn.microsoft.com/en-us/library/ms972976.aspx 2,它更深入地介绍了这一切
注意
如果您的问题是需要在按钮单击时动态创建控件,并且将创建许多控件,您应该转向jQuery ajax并在代码后面的公共函数上使用属性[WebMethod].创建动态控件和维护ViewState非常昂贵,所以我真的推荐这个,以获得更好的用户体验.
如果您使用DataPresentation控件asp:GridView就会更容易.
标记
<asp:GridView ID="ParticipantsGrid" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="Participants">
<ItemTemplate>
<asp:TextBox ID="txtNameofParticipant" runat="server"
Text='<%# Container.DataItem %>'>
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Run Code Online (Sandbox Code Playgroud)
代码隐藏
protected void btnSubmitCountParticipant_Click(object sender, EventArgs e)
{
try
{
var selectedParticipantCount = Convert.ToInt32(drpNoofparticipants.SelectedValue);
var items = Enumerable.Repeat(string.Empty, selectedParticipantCount).ToList();
ParticipantsGrid.DataSource = items;
ParticipantsGrid.DataBind();
}
catch (Exception ex)
{ }
}
public void CreateControls()
{
try
{
var participants = ParticipantsGrid.Rows
.Cast<GridViewRow>()
.Select(row => ((TextBox)row.FindControl("txtNameofParticipant")).Text)
.ToList();
}
catch (Exception ex)
{ }
}
Run Code Online (Sandbox Code Playgroud)