如何在ASP.NET中访问动态创建的服务器控件

4

我创建了一个网页,并动态地向表中添加服务器端控件。

我为它们分配了单独的id,但是我无法访问这些动态创建的服务器控件。

C# 代码:

 protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
        {
            int num_row = (int)Session["No_of_Rows"];
            for (int i = 2; i < num_row; i++)
            {
                TableRow row = new TableRow();
                TableCell cell1 = new TableCell();
                TableCell cell2 = new TableCell();
                TextBox tb = new TextBox();
                CheckBox cb = new CheckBox();

                row.ID = "rw" + i;

                cell1.ID = "c" + i + "1";
                cell2.ID = "c" + i + "2";

                tb.ID = "txt" + i;
                tb.EnableViewState = true;
                cb.ID = "chk" + i;

                cell1.Controls.Add(cb);
                cell2.Controls.Add(tb);

                row.Cells.Add(cell1);
                row.Cells.Add(cell2);

                tbl.Rows.Add(row);
            }
        }
        else
        {
            Session["No_of_Rows"] = 2;
        }




    }
    protected void addRow(object sender, EventArgs e)
    {

        int num_row = (int)Session["No_of_Rows"] + 1;
        TableRow row = new TableRow();
        TableCell cell1 = new TableCell();
        TableCell cell2 = new TableCell();
        TextBox tb = new TextBox();
        CheckBox cb = new CheckBox();

        row.ID = "rw" + num_row;

        cell1.ID = "c" + num_row + "1";
        cell2.ID = "c" + num_row + "2";

        tb.ID = "txt" + num_row;
        //tb.EnableViewState = true;
        cb.ID = "chk" + num_row;

        cell1.Controls.Add(cb);
        cell2.Controls.Add(tb);

        row.Cells.Add(cell1);
        row.Cells.Add(cell2);

        tbl.Rows.Add(row);
        Session["No_of_Rows"] = tbl.Rows.Count;



    }

    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        TextBox tb = new TextBox();

        int num_row = Convert.ToInt16(tbl.Rows.Count);
        for (int i = 1; i < num_row; i++)
        {
            string tstr = "txt" + i;
            tb = (TextBox)this.FindControl(tstr);

        }
        Label1.Text = tb.Text;
    }

ASP 代码:

    <form id="form1" runat="server">
<div>
    <asp:Label ID="Label1" runat="server" Text="textbox value is"></asp:Label>
    <asp:Table ID="tbl" runat="server">
        <asp:TableRow ID="rw0">
            <asp:TableCell ID="c01" Width="100px">
                <asp:CheckBox runat="server" ID="chk0" />
            </asp:TableCell>
            <asp:TableCell ID="c02" Width="100px">
                <asp:TextBox runat="server" ID="txt0" />
            </asp:TableCell></asp:TableRow>
        <asp:TableRow ID="rw1">
            <asp:TableCell ID="c11" Width="100px">
                <asp:CheckBox ID="chk1" runat="server" />
            </asp:TableCell>
            <asp:TableCell ID="c12" Width="100px">
                <asp:TextBox runat="server" ID="txt1" />
            </asp:TableCell></asp:TableRow>
    </asp:Table>
    <asp:Button ID="btn1" runat="server" Text="Add Row" OnClick="addRow" />
</div>
<asp:Button ID="btnSubmit" runat="server" OnClick="btnSubmit_Click" Text="Submit" />
</form>

请帮我解决这个问题。


嗨,Alwyn,你能告诉我你在哪里放置了上述代码吗?我的意思是在哪个事件或方法中? - Saranya
嗨,Saranya,我已经编辑了代码以获得更好的清晰度。 - Alwyn Miranda
我已经在底部发布了一个答案,请检查。 - Saranya
1
你没有在label1中得到任何值的原因是,你的逻辑是只显示最后一个访问的文本框的值。由于某种原因,动态创建的最后一个文本框的视图状态没有被维护 :( 因此你的标签值为空。 - Saranya
1
发现错误,问题出在逻辑上。int num_row = (int)Session["No_of_Rows"] + 1; 去掉+1就可以了。另外你的逻辑只会在标签中显示最后一个文本框的值。使用 StringBuilder 并在循环内追加它,以获取所有值。 - Saranya
4个回答

2
为了测试您的场景,我添加了2个控件txtOutput和Getvalues button。除了您的控件id从0开始,而for循环从1开始之外,一切都看起来很好。
然而,在FindControl中这不应该返回null。
我怀疑您的表格id是不正确的,因为在另一个您提到的帖子中,表格id是"tbl"。
除此之外,一切似乎都是正确的。无论如何,我已经粘贴了您的代码,并且它可以工作。
另一个可能导致错误的情况是,如果在Page_Load中创建控件之前尝试访问这些控件。但是,由于您的表格中有2行静态内容,所以您的代码应该可以正常工作,无论动态控件的创建如何。请尝试下面的代码并进行更新。
<form id="form1" runat="server">
        <div>
        <div>
        <asp:Table ID="tbl" runat="server">
            <asp:TableRow ID="rw0">
                <asp:TableCell ID="c01" Width="100px">
                    <asp:CheckBox runat="server" ID="chk0" />
                </asp:TableCell>
                <asp:TableCell ID="c02" Width="100px">
                    <asp:TextBox runat="server" ID="txt0" />
                </asp:TableCell></asp:TableRow>
            <asp:TableRow ID="rw1">
                <asp:TableCell ID="c11" Width="100px">
                    <asp:CheckBox ID="chk1" runat="server" />
                </asp:TableCell><asp:TableCell ID="c12" Width="100px">
                    <asp:TextBox runat="server" ID="txt1" />
                </asp:TableCell></asp:TableRow>
        </asp:Table>
        <asp:textbox runat="server" id="checkIn" ClientIDMode="Static" name="checkIn" ></asp:textbox>
        <asp:Button ID="btn1" runat="server" Text="Add Row" OnClick="addRow" />
        <br />
        <asp:Button ID="GetValues" runat="server" Text="GetValues" OnClick="GetValuesfromDynamicControls" />
        <asp:TextBox ID="txtOutput" runat="server" />

//代码在这里开始

 public partial class DynamicControl : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

            if (IsPostBack)
            {
                int num_row = (int)Session["No_of_Rows"];
                for (int i = 2; i < num_row; i++)
                {
                    TableRow row = new TableRow();
                    TableCell cell1 = new TableCell();
                    TableCell cell2 = new TableCell();
                    TextBox tb = new TextBox();
                    CheckBox cb = new CheckBox();

                    row.ID = "rw" + i;

                    cell1.ID = "c" + i + "1";
                    cell2.ID = "c" + i + "2";

                    tb.ID = "txt" + i;
                    tb.EnableViewState = true;
                    cb.ID = "chk" + i;

                    cell1.Controls.Add(cb);
                    cell2.Controls.Add(tb);

                    row.Cells.Add(cell1);
                    row.Cells.Add(cell2);

                    tbl.Rows.Add(row);
                }
            }
            else
            {
                Session["No_of_Rows"] = 2;
            }
        }

        protected void addRow(object sender, EventArgs e)
        {
            int num_row = (int)Session["No_of_Rows"];
            TableRow row = new TableRow();
            TableCell cell1 = new TableCell();
            TableCell cell2 = new TableCell();
            TextBox tb = new TextBox();
            CheckBox cb = new CheckBox();

            row.ID = "rw" + num_row;

            cell1.ID = "c" + num_row + "1";
            cell2.ID = "c" + num_row + "2";

            tb.ID = "txt" + num_row;
            tb.EnableViewState = true;
            cb.ID = "chk" + num_row;

            cell1.Controls.Add(cb);
            cell2.Controls.Add(tb);

            row.Cells.Add(cell1);
            row.Cells.Add(cell2);

            tbl.Rows.Add(row);
            Session["No_of_Rows"] = tbl.Rows.Count;
        }


        protected void GetValuesfromDynamicControls(object sender, EventArgs e)
        {
            //int rows =Convert.ToInt32( Session["No_of_Rows"]);
            int rows = Convert.ToInt32(tbl.Rows.Count);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < rows; i++)
            {               
                    TextBox tb =(TextBox) Page.FindControl("txt" + i);
                    sb.Append(tb.Text + ";");                
            }

            txtOutput.Text = sb.ToString();
        }

    }

你已经解决了我两个大问题。所以我想送给你 Dairy Milk Silk 巧克力 B-) .. 如果你想报销,请告诉我 :) - Alwyn Miranda
仅供参考:您提供的代码可以独立运行。但是,如果我将其合并到应用程序代码中,它就无法正常工作。后来我意识到这是由于主页面引起的。这就是为什么我得到了空值。为此,我们需要使用tb =(TextBox)sometable.FindControl(“txt”+ i); - Alwyn Miranda

2

在每次页面回发时,动态创建的控件可能不可见。因此,您需要在每次页面回发时重新创建动态控件。然后才能访问这些控件。


我已经完成了这一步,Priya。但是我无法访问它。这是我所做的方式:http://stackoverflow.com/questions/19562117/unable-to-add-more-than-one-server-control-dynamically-in-asp-net - Alwyn Miranda
如果您遇到问题,那么您可能在某个地方做错了。动态控件是这样工作的:每次回传时,在页面加载事件中,您需要使用与创建时相同的ID重新创建动态控件。例如,第一次创建一个文本框(ID为txt1)和一个下拉列表控件(ID为drp1),然后如果您单击下拉列表,即发生POSTBACK,则在页面加载事件中,您需要使用相同的ID(txt1和drp1)重新创建文本框和下拉列表控件,只有这样才能进一步访问这些控件。 - Priya Gund
我已经执行了相同的操作。在页面加载事件下,我使用for循环重新创建了所有控件。在添加行按钮事件中,我添加了新行。是的,我错过了某个地方。等一下,我会发布整个代码,这样你就可以在有空的时候找出问题。非常感谢。 - Alwyn Miranda

2

尝试:

            tb = (TextBox)sometable.FindControl("txt" + i);

哇,PJM。如果我们有主页面,这真的很有用。非常感谢你,伙计。但是如果我们没有主页面,那么我们可以直接使用Saranya上面提到的this.control或page.control。 - Alwyn Miranda
1
FindControl() 只会在指定的容器直接包含控件时才能找到该控件;也就是说,该方法不会在控件内部的控件层次结构中搜索,因此您需要指定命名容器 table。 - PJM
这个问题的答案应该像这个一样简单明了。 - precise

1
你可以这样做:

你可以像这样做:

TextBox txt= (TextBox)FindControl("txt"+i.Tostring());
string txtValue=txt.Text;

要在for循环中访问所有文本框:

int num_row = Convert.ToInt16(sometable.Rows.Count);
for (int i = 1; i < num_row; i++)
{
    string txtID="txt" + i.Tostring();
    TextBox txt= (TextBox)FindControl(txtID);
    string txtValue=txt.Text;
}

1
@ChrisFarmer虽然他没有将i转换为字符串,但当他执行FindControl("txt" + i)时,他没有得到正确的TextBox Id。 - gwt
2
我不认为那是正确的。转换是通过 + 自动进行的。https://dev59.com/b3RB5IYBdhLWcg3wAjNH - Chris Farmer
Karam: 其实我得到了正确的ID。我设置了断点并进行了检查。然而,我按照你说的做了,结果仍然是一样的。 - Alwyn Miranda
tb在块之前声明为:TextBox tb = new TextBox(); - Alwyn Miranda
这没什么用。但是正如你所说,我在循环内声明并分配了文本。 for (int i = 1; i < num_row; i++) { string tstr = "txt" + i; tb = (TextBox)this.FindControl(tstr); string abl = tb.Text; } 但是我得到的错误与循环外得到的相同。我的意思是我根本无法读取它:(..我不知道我错过了什么 - Alwyn Miranda
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接