在表中动态创建的TextBox会丢失Text值

时间:2017-01-29 14:58:25

标签: c# asp.net textbox

我有一个动态生成的表,在2列内有TextBoxes。在回发期间,即使我填充它们,文本框也始终为空。 该表以这种方式构建:

  protected void ddlScalaTaglie_SelectedIndexChanged(object sender, EventArgs e)
    {
        DataTable dtRighe = oTab.getScaleTaglieRighe(ddlScalaTaglie.SelectedValue);

        //dt is datatable object which holds DB results.
        Table tbl = new Table();
        tbl.CssClass = "table table-striped  table-bordered table-responsive";

        TableRow tr;
        TableCell tcEU, tcUS, tcUK, tcQty, tcEAN;
        Label lbEU, lbUS, lbUK, lbQty, lbEAN;
        TextBox tbEU, tbUS, tbUK, tbQty, tbEAN, tbToFocus = null;

        foreach (DataRow dr in dtRighe.Rows)
        {
            tr = new TableRow();

            //ean
            tcEAN = new TableCell();
            tbEAN = new TextBox();
            tbEAN.ID = "txtEAN" + dr[0].ToString();
            tbEAN.Width = new Unit(100, UnitType.Percentage);
            tbEAN.Columns = 15;
            tcEAN.Controls.Add(tbEAN); 
            tr.Controls.Add(tcEAN);

            //Qty
            tcQty = new TableCell();
            tbQty = new TextBox(); 
            tbQty.ID = "txtQty" + dr[0].ToString(); 
            tbQty.TextMode = TextBoxMode.Number; 
            tcQty.Controls.Add(tbQty);
            tr.Controls.Add(tcQty);            

            tbl.Controls.Add(tr);
        }

        Session["tbl"] = tbl;

        divTaglieRighe.Controls.Add(tbl);
    }

当我单击按钮SAVE时,我必须循环访问我的表并保存所有TextBox.Text ...

这就是我写的:

 ArrayList arrScarpaFigli = new ArrayList();
 Table tbl = (Table)Session["tbl"];
 foreach (TableRow row in tbl.Rows)
 {
     foreach (TableCell cell in row.Cells)
     {
        foreach (Control ctrl in cell.Controls)
        {
           //CONTROL IS TEXBOXT: EXTRACT VALUES//
            if (ctrl is TextBox)
            {
                TextBox txt = (TextBox)ctrl;
                arrScarpaFigli.Add(txt.Text);
             }
         }
      }
  }

问题是,如果我填充文本框,在我的文本中总是有一个空字符串。 我填写表格的唯一时刻是下拉列表的selectionChange。

我做错了什么? 提前致谢

4 个答案:

答案 0 :(得分:2)

Table中存储Session控件的实例是一个可怕的想法,而且是完全错误的。控件属于他们的父页面 - 它们应该在创建后立即添加到它们中,并且它们应该与其父页面一起消失。

在ASP.NET中动态创建控件的事情是,您必须存储它们被创建的事实的指示符(以及再次创建它们所需的相关信息),并在所有后续回发中重新创建它们 - 不迟于在Page_Load。只有这样,这些控件才有可能从Request获取值,您将有机会从控件中获取这些值。

在您的代码中,存储在Table中的Session实例(及其所有行,单元格和文本框)将永远不会反映任何客户端数据更改,也不会属于{{ 1}}将创建以处理后续回发请求。

更新

这里要理解的重要事实是,在处理由Page更改导致的回发并将heh html返回给客户端之后,页面实例就消失了。在下一个请求中,将创建一个新的页面实例 - 并且它不知道前一个实例将表添加到其控制树的事实。您ddlScalaTaglie中的代码必须发现表单必须具有此表,并以与第一次创建表格完全相同的方式创建表格 - 行,单元格和文本框具有完全相同的{{1 }}第

然后,在将新创建的表格添加到Page_Load后,文本框将能够从ID集合中提取其客户端值。

答案 1 :(得分:2)

您必须在每个页面加载上重新创建动态控件,以确保在PostBack之后保留它们的值。因此,您需要创建一个新的方法,以便在每次加载页面时处理表的创建。

protected void Page_Load(object sender, EventArgs e)
{
    //always create the controls on every page load if there is a value selected in ddlScalaTaglie
    if (!string.IsNullOrEmpty(ddlScalaTaglie.SelectedValue))
    {
        createTable(ddlScalaTaglie.SelectedValue);
    }
}

protected void Button1_Click(object sender, EventArgs e)
{
    //use findcontrol to find the Table inside the placeholder
    Table tbl = Page.FindControl("divTaglieRighe").FindControl("Table1") as Table;

    //loop all rows and cells in the Table
    foreach (TableRow row in tbl.Rows)
    {
        foreach (TableCell cell in row.Cells)
        {
            foreach (Control ctrl in cell.Controls)
            {
                //the control is a textbox
                if (ctrl is TextBox)
                {
                    //cast the control back to a textbox
                    TextBox tb = ctrl as TextBox;

                    //does the checkbox have a value, if so append the label
                    if (!string.IsNullOrEmpty(tb.Text))
                    {
                        Label1.Text += tb.Text + "<br>";
                    }
                }
            }
        }
    }

}

protected void ddlScalaTaglie_SelectedIndexChanged(object sender, EventArgs e)
{
    //no need to create the Table dynamically, that will be handled in Page_Load
    //this method is just a dummy to trigger a PostBack

    //you could remove this method and the OnSelectedIndexChanged from the DropDown
    //and just keep the AutoPostBack="true", that will also work
}

private void createTable(string value)
{
    DataTable dtRighe = Common.LoadFromDB();

    //create a new table WITH id, that is needed for findcontrol
    Table tbl = new Table();
    tbl.ID = "Table1";

    //loop all rows in the datatable
    foreach (DataRow dr in dtRighe.Rows)
    {
        TableRow tr = new TableRow();

        //ean
        TableCell tcEAN = new TableCell();
        TextBox tbEAN = new TextBox();
        tbEAN.ID = "txtEAN" + dr[0].ToString();
        tbEAN.Width = new Unit(100, UnitType.Percentage);
        tbEAN.Columns = 15;
        tcEAN.Controls.Add(tbEAN);
        tr.Controls.Add(tcEAN);

        //Qty
        TableCell tcQty = new TableCell();
        TextBox tbQty = new TextBox();
        tbQty.ID = "txtQty" + dr[0].ToString();
        tbQty.TextMode = TextBoxMode.Number;
        tcQty.Controls.Add(tbQty);
        tr.Controls.Add(tcQty);

        tbl.Controls.Add(tr);
    }

    //add the table to the placeholder
    divTaglieRighe.Controls.Add(tbl);
}

使示例完整的aspx

<asp:DropDownList ID="ddlScalaTaglie" runat="server" OnSelectedIndexChanged="ddlScalaTaglie_SelectedIndexChanged" AutoPostBack="true">
    <asp:ListItem Text="Select..." Value=""></asp:ListItem>
    <asp:ListItem Text="Option 1" Value="1"></asp:ListItem>
    <asp:ListItem Text="Option 2" Value="2"></asp:ListItem>
</asp:DropDownList>
<br />
<br />
<asp:PlaceHolder ID="divTaglieRighe" runat="server"></asp:PlaceHolder>
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Save" OnClick="Button1_Click" />
<br />
<br />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>

答案 2 :(得分:1)

确保文本框中有一个“名称”,用于回发到控制器的帖子。 如果不是,则为参数抓取null。

检查Request.Form以获取返回控制器的数据。

答案 3 :(得分:0)

您创建了一个名为#include "opencv2\opencv.hpp" using namespace cv; using namespace std; int main() { VideoCapture cap(0); Mat src, gray, background, binary, diff; cap >> background; cvtColor(background, background, CV_BGR2GRAY); vector<vector<Point>> contours; vector < vector<int>> hullI = vector<vector<int>>(1); vector < vector<Point>> hullP = vector<vector<Point>>(1); vector<Vec4i> defects; while (waitKey(30)!='q') { cap >> src; cvtColor(src, gray, CV_BGR2GRAY); blur(gray, gray, Size(3, 3)); absdiff(gray, background, diff); threshold(diff, binary, 15, 255, THRESH_BINARY); erode(binary, binary, Mat(Size(5, 5), CV_8U)); imshow("binary", binary); findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); if (!contours.empty()) { sort(contours.begin(), contours.end(), [](vector<Point> a, vector<Point> b) { return a.size() > b.size(); }); drawContours(src, contours, 0, Scalar(255, 255, 0)); convexHull(contours[0], hullI[0]); convexHull(contours[0], hullP[0]); drawContours(src, hullP, 0, Scalar(0, 255, 255)); if (hullI[0].size() > 2) { convexityDefects(contours[0], hullI[0], defects); for (Vec4i defect : defects) { line(src, contours[0][defect[0]], contours[0][defect[2]], Scalar(0, 0, 255)); line(src, contours[0][defect[1]], contours[0][defect[2]], Scalar(0, 0, 255)); } } } imshow("src", src); char key = waitKey(30); if (key == 'q')break; else if (key == 'p') waitKey(); else if (key == 'b') { cap >> background; cvtColor(background, background, CV_BGR2GRAY); } } } 的表,并添加了两个<div class='main-element'> <input> <label></label> <ul> <li>Example</li> </ul> </div> <div class='main-element'> <input> <label></label> </div> ,然后将Table控件存储在会话var env = new nunjucks.Environment(new nunjucks.WebLoader('../views')); $.ajax({ url: '/products', contentType: 'application/json', type: 'GET', success: function(response) { var $tableBody = $('#products-table-body'); var template = env.getTemplate('_item-row.html'); response.products.forEach(function(product) { $tableBody.append( nunjucks.render( template, { id: product.id, name: product.name } ) ); }); } }); 中并添加到tbl控件中。最后,您尝试从会话TextBox表中获取TextBox数据,而不是在Session["tbl"]控件中添加的ViewState控件。您必须从divTaglieRighe控件中添加的表Session["tbl"]控件中获取数据。