我有一个动态生成的表,在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。
我做错了什么? 提前致谢
答案 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"]
控件中获取数据。