A coworker and I can't figure out why the EventHandlers in the following code aren't getting fired. The function is called twice before the first page loads, and AutoPostBack is set to true. The lnkbtn button and the ddlDose DropDownList are the ones not being fired. It posts back, but it doesn't call the event handler. Here's some code...can anybody see anything inherently wrong?
Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
tblMedOrdering = (Table)Session["tblMedOrdering"];
List<string>medNames = (List<string>)Session["medNamesList"];
populateMeds(medNames);
}
}
PopulateMeds:
protected void populateMeds(List<string> medNames)
{
if (medNames.Count == 0)
{
tblMedOrdering = (Table)Session["tblMedOrdering"];
}
else
{
DataSet ds = new DataSet();
string strConn = Application["dbconn"].ToString();
using (SqlConnection dbconn = new SqlConnection(strConn))
using (SqlCommand medDbcmd = dbconn.CreateCommand())
{
dbconn.Open();
for (int i = 0; i < medNames.Count; i++)
{
DropDownList ddlDose = new DropDownList();
DropDownList ddlSig = new DropDownList();
int flag = 0;
if ((Table)Session["tblMedOrdering"] != null)
{
for (int j = 0; j < tblMedOrdering.Rows.Count; j++)
{
if (tblMedOrdering.Rows[j].Cells[3].Text == medNames[i].ToString())
{
flag = 1;
ddlSig = (DropDownList)tblMedOrdering.Rows[i].Cells[2].FindControl(medNames[i].ToString() + "ddlSig");
if (ddlSig == null)
{
ddlSig.ID = medNames[i].ToString() + "ddlSig";
ListItem liDefaultSig = new ListItem();
liDefaultSig.Value = "0";
liDefaultSig.Text = "Select . . .";
ddlSig.Items.Add(liDefaultSig);
}
break;
}
}
}
if (flag != 1)
{
ListItem liDefault = new ListItem();
liDefault.Value = "0";
liDefault.Text = "Select . . .";
ddlDose.Items.Add(liDefault);
ddlSig.Items.Add(liDefault);
ddlDose.ID = medNames[i].ToString() + "ddlDose";
ddlSig.ID = medNames[i].ToString() + "ddlSig";
ddlDose.AutoPostBack = true;
ddlDose.TextChanged += new EventHandler(ddlDose_SelectedIndexChanged);
medDbcmd.CommandText = "Select distinct medorderid, dose from ordertablemeds where medordername = '" + medNames[i].ToString() + "'";
SqlDataReader dr = medDbcmd.ExecuteReader();
if (dr != null)
{
while (dr.Read())
{
ListItem liDose = new ListItem();
liDose.Value = dr["medorderid"].ToString();
liDose.Text = dr["dose"].ToString();
ddlDose.Items.Add(liDose);
}
dr.Close();
}
TableRow tr = new TableRow();
tr.ID = medNames[i].ToString() + "TableRow";
TableCell tcDose = new TableCell();
TableCell tcSig = new TableCell();
TableCell tcRemove = new TableCell();
TableCell tcMedName = new TableCell();
tcDose.Controls.Add(ddlDose);
tcSig.Controls.Add(ddlSig);
tcMedName.Text = medNames[i].ToString();
tcMedName.ID = medNames[i].ToString() + "medname";
LinkButton lnkbtn = new LinkButton();
lnkbtn.Text = "X";
lnkbtn.ForeColor = System.Drawing.Color.Red;
lnkbtn.ID = medNames[i].ToString() + "_lnkbtn" + tblMedOrdering.Rows.Count;
lnkbtn.Click += new EventHandler(Reset_Click);
tcRemove.Controls.Add(lnkbtn);
tr.Cells.Add(tcRemove);
tr.Cells.Add(tcDose);
tr.Cells.Add(tcSig);
tr.Cells.Add(tcMedName);
tblMedOrdering.Rows.Add(tr);
}
}
tblMedOrdering.DataBind();
dbconn.Close();
}
}
Session["tblMedOrdering"] = tblMedOrdering;
if (medNames.Count == 0)
{
cpeMeds.Collapsed = true;
cpeMeds.ClientState = "True";
}
List<string> medNamesList = new List<string>();
DropDownList ddl = new DropDownList();
for (int k = 0; k < tblMedOrdering.Rows.Count; k++)
{
ddl = (DropDownList)tblMedOrdering.Rows[k].Cells[1].FindControl(tblMedOrdering.Rows[k].Cells[3].Text +"ddlDose");
ddl.SelectedIndexChanged += new EventHandler(ddlDose_SelectedIndexChanged);
medNamesList.Add(tblMedOrdering.Rows[k].Cells[3].Text);
}
Session["medNamesList"] = medNamesList;
}
PopulateMeds is just a function that gets called in the code-behind and is given a list of string names, so it doesn't need args as if it were a control (objects sender, EventArgs e).
Move that logic to OnInit and the event handlers should function properly, assuming that everything else is correct. I would also check to make sure that you don't have validation interfering with the postback.
Related
I am adding columns to gridview from codebehind.
For boundfields, i am able to find control and textbox value while updating the row.
But for template fields, i am not able to get controls to the code behind, so i am unable to get the textbox value.
Can please suggest how to get textbox value in codebehind for template fields
My Code
protected void gvbind()
{
conn.Open();
string Query = "SELECT * FROM testactiondatabase_db.actions";
MySqlCommand MyCommand2 = new MySqlCommand(Query, conn);
MySqlDataAdapter MyAdapter = new MySqlDataAdapter();
MyAdapter.SelectCommand = MyCommand2;
DataTable dt = new DataTable();
MyAdapter.Fill(dt);
TaskGridView.Columns.Clear();
for (int i = 0; i < dt.Columns.Count; i++)
{
if (dt.Columns[i].ColumnName.ToString().ToUpper().Contains("DATE"))
{
TemplateField bfield = new TemplateField();
bfield.HeaderTemplate = new GridViewTemplate(ListItemType.Header, dt.Columns[i].ColumnName.ToString());
bfield.ItemTemplate = new GridViewTemplate(ListItemType.Item, dt.Columns[i].ColumnName.ToString());
bfield.EditItemTemplate = new GridViewTemplate(ListItemType.EditItem, dt.Columns[i].ColumnName.ToString());
TaskGridView.Columns.Add(bfield);
}
else
{
BoundField boundfield = new BoundField();
boundfield.DataField = dt.Columns[i].ColumnName.ToString();
boundfield.HeaderText = dt.Columns[i].ColumnName.ToString();
TaskGridView.Columns.Add(boundfield);
}
}
TaskGridView.DataSource = dt;
TaskGridView.DataBind();
TaskGridView.Width = 600;
TaskGridView.HeaderStyle.CssClass = "header";
TaskGridView.RowStyle.CssClass = "rowstyle";
conn.Close();
}
public class GridViewTemplate : ITemplate
{
ListItemType _templateType;
string _columnName;
public GridViewTemplate(ListItemType type, string colname)
{
_templateType = type;
_columnName = colname;
}
void ITemplate.InstantiateIn(System.Web.UI.Control container)
{
switch (_templateType)
{
case ListItemType.Header:
Label lbl = new Label();
lbl.Text = _columnName;
container.Controls.Add(lbl);
break;
case ListItemType.Item:
Label lb1 = new Label();
lb1.DataBinding += new EventHandler(lb1_DataBinding);
container.Controls.Add(lb1);
break;
case ListItemType.EditItem:
TextBox tb1 = new TextBox();
tb1.ID = _columnName;
tb1.DataBinding += new EventHandler(tb1_DataBinding);
tb1.Attributes.Add("class", "myDatePickerClass");
container.Controls.Add(tb1);
break;
case ListItemType.Footer:
CheckBox chkColumn = new CheckBox();
chkColumn.ID = "Chk" + _columnName;
container.Controls.Add(chkColumn);
break;
}
}
void tb1_DataBinding(object sender, EventArgs e)
{
TextBox txtdata = (TextBox)sender;
GridViewRow container = (GridViewRow)txtdata.NamingContainer;
object dataValue = DataBinder.Eval(container.DataItem, _columnName);
if (dataValue != DBNull.Value)
{
txtdata.Text = Convert.ToDateTime(dataValue.ToString()).ToString("dd/MM/yyyy");
}
}
void lb1_DataBinding(object sender, EventArgs e)
{
Label txtdata = (Label)sender;
GridViewRow container = (GridViewRow)txtdata.NamingContainer;
object dataValue = DataBinder.Eval(container.DataItem, _columnName);
if (dataValue != DBNull.Value)
{
txtdata.Text = Convert.ToDateTime(dataValue.ToString()).ToString("dd/MM/yyyy");
}
}
}
I am using the following code for reading the template field textbox value while updating the row but the controls are 0 for the cell.
GridViewRow row = (GridViewRow)TaskGridView.Rows[e.RowIndex];
TextBox textnew = (TextBox)row.Cells[j].Controls[0];
Try using FindControl.
TextBox textnew = TaskGridView.Rows[e.RowIndex].FindControl(_columnName) as TextBox;
But if I use your snippet like this, with setting an EditIndex manually, it also works... The value of te TextBox is Cell 1 is changed.
TaskGridView.EditIndex = 1;
TaskGridView.DataSource = dt;
TaskGridView.DataBind();
TaskGridView.Width = 600;
TaskGridView.HeaderStyle.CssClass = "header";
TaskGridView.RowStyle.CssClass = "rowstyle";
GridViewRow row = (GridViewRow)TaskGridView.Rows[TaskGridView.EditIndex];
TextBox textnew = (TextBox)row.Cells[1].Controls[0];
textnew.Text = "test";
I have a button which is created from a MySQL query result. It looks like this:
1 Product name |add to basket|
And when I press the "add to basket" button, the product appears in a table on the right side(basket). Like this:
1 Product name |remove|
But for some reason, the remove button click-event removes all items from basket. When I press add to basket again, all items appear in the basket again.
This is whole class. Thank you for your help
public partial class neworder : System.Web.UI.Page
{
Basket basket;
Table BasketTable;
private int countRows = 0;
private string distance;
private string categories;
ArrayList categoryList = new ArrayList();
ArrayList productList = new ArrayList();
private string products = "";
public string Products
{
get { return products; }
set { products = value; }
}
public string Categories
{
get { return categories; }
set { categories = value; }
}
public string Distance
{
get { return distance; }
set { distance = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Page_Init(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
basket = new Basket();
Session["basket"] = basket;
}
populateCategories();
populateProducts();
loadBasket(); // if this is comment then i items are added fine
//to basket but cant be remove, if its not commented then i can add
//only 2 items in basket
}
private void populateCategories()
{
using (MySqlConnection cn = new MySqlConnection(Static.MysqlServer1))
{
cn.Open();
String strSQL = "SELECT category_name FROM categories;";
MySqlCommand cmdPLT = new MySqlCommand(strSQL, cn);
MySqlDataReader myReader;
myReader = cmdPLT.ExecuteReader();
while (myReader.Read())
{
string cat = myReader.GetString(0);
categoryList.Add(cat);
categories += "" + cat + "<br />";
}
}
}
private void populateProducts()
{
Panel1.Controls.Clear();
string tem = "";
foreach (string s in categoryList)
{
Table tableTitle = new Table();
TableRow row1 = new TableRow();
tableTitle.ID = s + "Title";
tableTitle.CssClass = "rest2";
Panel1.Controls.Add(tableTitle);
TableCell cell2 = new TableCell();
Label label2 = new Label();
label2.Text = "<a name="+s+">"+s+"</a>";
label2.ID = "TitleText_" + s;
cell2.Controls.Add(label2);
row1.Cells.Add(cell2);
tableTitle.Controls.Add(row1);
Table table = new Table();
table.ID = s;
table.CssClass = "rest";
Panel1.Controls.Add(table);
using (MySqlConnection cn = new MySqlConnection(Static.MysqlServer1))
{
string name = "";
string size = "";
int id = -1;
double price = 0.0;
cn.Open();
String strSQL = "SELECT product_id, product_name, product_price, product_size FROM products join categories on categories.CATEGORY_ID = products.CATEGORY_ID where category_name ='" + s + "' order by product_order asc;";
MySqlCommand cmdPLT = new MySqlCommand(strSQL, cn);
MySqlDataReader myReader;
myReader = cmdPLT.ExecuteReader();
while (myReader.Read())
{
name = (string)myReader["product_name"];
id = (int)myReader["product_id"];
size = (string)myReader["product_size"];
price = (double)myReader["product_price"];
productList.Add(new Products(id, name, size, price));
GenerateRow(s, name, size, price, table, id);
}
if (!tem.Equals(""))
{
tem += "</table>";
}
}
products += tem;
tem = "";
}
}
private void GenerateRow(string category, string name, string size, double price, Table table,int id )
{
TableRow row1 = new TableRow();
//ROW 1 NAME
TableCell cell1 = new TableCell();
Label label1 = new Label();
label1.Text = name;
cell1.Style.Add("width", "300px !important");
label1.ID = "NameText_" + category+id;
cell1.Controls.Add(label1);
row1.Cells.Add(cell1);
//ROW 2 Size
TableCell cell2 = new TableCell();
Label label2 = new Label();
cell2.Style.Add("width", "100px !important");
label2.Text = size;
label2.ID = "SizeText_" +category+ id;
cell2.Controls.Add(label2);
row1.Cells.Add(cell2);
//ROW 1 PRICE
TableCell cell3 = new TableCell();
Label label3 = new Label();
cell3.Style.Add("width", "60px !important");
label3.Text = "" + price;
label3.ID = "Price_" + category + id;
cell3.Controls.Add(label3);
row1.Cells.Add(cell3);
//ROW 1 BUTTON
TableCell cell4 = new TableCell();
cell4.Style.Add("height", "25px !important");
Button button = new Button();
button.Text = "+";
button.Click += button_Click;
button.ID = ""+id;
cell4.Controls.Add(button);
row1.Cells.Add(cell4);
table.Controls.Add(row1);
}
private void loadBasket()
{
Basket temp = (Basket)Session["basket"];
BasketTable = new Table();
BasketTable.ID = "basket";
BasketTable.CssClass = "rest";
PanelBasket.Controls.Clear();
PanelBasket.Controls.Add(BasketTable);
foreach (Products p in temp.ProductList)
{
TableRow row1 = new TableRow();
//ROW 1 NAME
TableCell cell1 = new TableCell();
Label label1 = new Label();
label1.Text = p.Name;
cell1.Style.Add("width", "100px !important");
label1.ID = p.Name;
cell1.Controls.Add(label1);
row1.Cells.Add(cell1);
//ROW 2 Size
TableCell cell2 = new TableCell();
Label label2 = new Label();
cell2.Style.Add("width", "40px !important");
label2.Text = p.Size;
label2.ID = p.Size;
cell2.Controls.Add(label2);
row1.Cells.Add(cell2);
//ROW 1 PRICE
TableCell cell3 = new TableCell();
Label label3 = new Label();
cell3.Style.Add("width", "60px !important");
label3.Text = p.Price+"";
label3.ID = p.Price + "";
cell3.Controls.Add(label3);
row1.Cells.Add(cell3);
//ROW 1 BUTTON
TableCell cell4 = new TableCell();
cell4.Style.Add("height", "25px !important");
Button remove = new Button();
remove.Text = "-";
remove.Click += new EventHandler(button99_Click);
remove.ID = "remove" + p.Id;
cell4.Controls.Add(remove);
row1.Cells.Add(cell4);
BasketTable.Controls.Add(row1);
}
}
private void button_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
string buttonId = button.ID;
foreach (Products p in productList)
{
if (p.Id == Convert.ToInt32(buttonId))
{
Basket temp = (Basket)Session["basket"];
temp.addPruduct(p);
Session["basket"] = temp;
loadBasket();
Label1.Text = temp.ProductList.Count + "";
}
}
}
protected void remove_Click(object sender, EventArgs e)
{
Label1.Text = "test";
}
}
I have one repeater which displays the list of puja.i have also used one datalist to display the names of temples.whenever i click on search it displays only the last value of the repeater i.e it is taking only the last value of the repeater....my question is how to use loop inside a repeater???
here is my code behind how i used datalist and repeater:
protected void Page_Load(object sender, EventArgs e)
{
//lblnodatafound.Visible = true;
//lbldatafound.Visible = false;
if (Request.QueryString["search"] != null)
{
var dt = new DataTable("Data");
String source = Request.QueryString["search"];
var splitseparator = new string[] { " " };
String[] result = source.Split(splitseparator, StringSplitOptions.RemoveEmptyEntries);
foreach (String s in result)
{
if (IsAlphaNumeric(s) == true)
{
var dttemp = new DataTable();
dttemp = fnsearch(s);
dt.Merge(dttemp, true);
}
}
if (dt.Rows.Count != 0)
{
int count = dt.Rows.Count;
if (dt.Rows.Count > 0)
{
DataList1.DataSource = dt;
DataList1.DataBind();
lblnodatafound.Visible = false;
lbldatafound.Visible = true;
//added the repeater to display the list of puja
for (int i = 0; i < dt.Rows.Count; i++)
{
String id = dt.Rows[i]["id"].ToString();
string query = "select puja.id,puja.name as puja_name, mandir.name as mandir_name from puja,mandir where mandir.id= puja.with_mandir and puja.with_mandir = '" + id + "'";
conn.Open();
MySqlCommand cmd = new MySqlCommand(query, conn);
MySqlDataAdapter adp = new MySqlDataAdapter(cmd);
DataTable dt1 = new DataTable();
adp.Fill(dt1);
conn.Close();
if (dt1.Rows.Count > 0)
{
lblmandirpuja.Text = "Poja in " + dt1.Rows[0]["mandir_name"];
foreach (RepeaterItem repeatItem in Repeater1.Items){
Repeater1.DataSource = dt1;
Repeater1.DataBind();
}
}
}
}
}
else
{
lblnodatafound.Visible = true;
lbldatafound.Visible=false;
}
}
}
Try to change this line:
if (dt1.Rows.Count > 0)
for something like:
for(int i = 0; i < dt1.Rows.Count; i++)
And this one:
lblmandirpuja.Text = "Poja in " + dt1.Rows[0]["mandir_name"];
The 0 for the i:
lblmandirpuja.Text = "Poja in " + dt1.Rows[i]["mandir_name"];
For every row in my 'table' I am manually creating, there must be a LinkButton to delete a database row that matches a column in the table. Because no 2 controls can have the same name, I've had to use a GUID to name them so they're all unique.
Problem is, right now when I click Delete, the page posts back with no changes, but I've been told that I need to recreate the controls - but how do I recreate them in Page_Load when their ID's are randomly generated? Here's my code:
Table table = new Table();
table.GridLines = GridLines.None;
//table.BorderWidth = 1;
//table.BorderColor = (System.Drawing.Color)conv.ConvertFromString("black");
table.Width = Unit.Percentage(100);
table.GridLines = (GridLines)3;
TableHeaderRow header = new TableHeaderRow();
header.BackColor = (System.Drawing.Color)conv.ConvertFromString("#EDEDED");
foreach (string header2 in new string[] {"", "Quantity", "Rate", "Description", "Nominal Code", "Subtotal" })
{
TableCell cell = new TableCell();
cell.Text = header2;
header.Cells.Add(cell);
}
table.Rows.Add(header);
var data = (from s in dc.InvoiceItems where s.invoiceid.ToString() == Request.QueryString["id"].ToString() select s);
foreach (var x in data)
{
TableRow row = new TableRow();
if (x.invoicetext == null)
{
decimal total;
try
{
total = (decimal)x.rate * (decimal)x.quantity;
}
catch
{
total = 0;
}
int i = 0;
foreach (string columnData in new string[] {x.id.ToString(), x.quantity.ToString(), x.rate.ToString(), x.description, x.nominalcode, total.ToString("N2") })
{
TableCell cell = new TableCell();
{
if (i == 0)
{
LinkButton lnkdel = new LinkButton();
lnkdel.Text = "Delete";
lnkdel.ID = "lnkDel" + Guid.NewGuid();
if (alloweditting == false)
{
lnkdel.Enabled = false;
}
lnkdel.Font.Bold = false;
lnkdel.CommandArgument = x.id.ToString();
lnkdel.Command += (s, e2) =>
{
using (SqlConnection conn = new SqlConnection(connection))
{
SqlCommand comm = new SqlCommand("DELETE FROM InvoiceItem WHERE id = #id", conn);
comm.Parameters.AddWithValue("#id", e2.CommandArgument);
conn.Open();
try
{
comm.ExecuteNonQuery();
}
catch (Exception ex)
{
Response.Write(ex);
}
}
};
cell.Controls.Add(lnkdel);
i++;
}
else
{
cell.Text = columnData;
}
}
row.Cells.Add(cell);
}
runningtotal = runningtotal + total;
}
else
{
int i = 0;
foreach (string columnData in new string[] {x.id.ToString(), x.invoicetext })
{
TableCell cell = new TableCell();
if (i == 0)
{
LinkButton lnkdel = new LinkButton();
lnkdel.Text = "Delete";
lnkdel.ID = "lnkDel" + Guid.NewGuid();
if (alloweditting == false)
{
lnkdel.Enabled = false;
}
lnkdel.Font.Bold = false;
lnkdel.CommandArgument = x.id.ToString();
rowid = lnkdel.CommandArgument;
lnkdel.Command += (s, e2) =>
{
using (SqlConnection conn = new SqlConnection(connection))
{
SqlCommand comm = new SqlCommand("DELETE FROM InvoiceItem WHERE id = #id", conn);
comm.Parameters.AddWithValue("#id", rowid);
conn.Open();
try
{
comm.ExecuteNonQuery();
}
catch (Exception ex)
{
Response.Write(ex);
}
}
};
cell.Controls.Add(lnkdel);
i++;
}
else
{
cell.Text = columnData;
cell.ColumnSpan = 5;
}
row.Cells.Add(cell);
}
}
switch (x.formatoptions)
{
case 1:
row.ForeColor = (System.Drawing.Color)conv.ConvertFromString("black");
row.Font.Bold = false;
break;
case 2:
row.ForeColor = (System.Drawing.Color)conv.ConvertFromString("black");
row.Font.Bold = true;
break;
case 3:
row.ForeColor = (System.Drawing.Color)conv.ConvertFromString("red");
row.Font.Bold = false;
break;
case 4:
row.ForeColor = (System.Drawing.Color)conv.ConvertFromString("red");
row.Font.Bold = true;
break;
}
table.Rows.Add(row);
}
TableFooterRow row2 = new TableFooterRow();
TableCell cell2 = new TableCell();
cell2.Text = "<span style\"text-align: right; width: 100%;\">Total = <b>" + runningtotal.ToString("N2") + "</b></span>";
cell2.ColumnSpan = 6;
row2.Cells.Add(cell2);
table.Rows.Add(row2);
var update = (from s in dc.Invoices where s.id.ToString() == Request.QueryString["id"] select s).Single();
update.total = runningtotal;
dc.SubmitChanges();
datatable.Controls.Clear();
datatable.Controls.Add(table);
}
Don't use a GUID. Make the ID value from the rowid, so it's a repeatable value like "row_784".
For example, instead of
lnkdel.ID = "lnkDel" + Guid.NewGuid();
use
lnkdel.ID = "lnkDel" + x.id.ToString();
You need to create them in Page_Init, not Page_Load. You should only need to move the call to the code that creates your table to Page_Init, and everything should work as you expect.
I have a problem that has been bugging me all day.
In my code I have the following:
private int rowCount
{
get { return (int)ViewState["rowCount"]; }
set { ViewState["rowCount"] = value; }
}
and a button event
protected void addRow_Click(object sender, EventArgs e)
{
rowCount = rowCount + 1;
}
Then on Page_Load I read that value and create controls accordingly.
I understand the button event fires AFTER the Page_Load fires so the value isn't updated until the next postback. Real nightmare.
Here's the entire code:
protected void Page_Load(object sender, EventArgs e)
{
string xmlValue = ""; //To read a value from a database
if (xmlValue.Length > 0)
{
if (!Page.IsPostBack)
{
DataSet ds = XMLToDataSet(xmlValue);
Table dimensionsTable = DataSetToTable(ds);
tablePanel.Controls.Add(dimensionsTable);
DataTable dt = ds.Tables["Dimensions"];
rowCount = dt.Rows.Count;
colCount = dt.Columns.Count;
}
else
{
tablePanel.Controls.Add(DataSetToTable(DefaultDataSet(rowCount, colCount)));
}
}
else
{
if (!Page.IsPostBack)
{
rowCount = 2;
colCount = 4;
}
tablePanel.Controls.Add(DataSetToTable(DefaultDataSet(rowCount, colCount)));
}
}
protected void submit_Click(object sender, EventArgs e)
{
resultsLabel.Text = Server.HtmlEncode(DataSetToStringXML(TableToDataSet((Table)tablePanel.Controls[0])));
}
protected void addColumn_Click(object sender, EventArgs e)
{
colCount = colCount + 1;
}
protected void addRow_Click(object sender, EventArgs e)
{
rowCount = rowCount + 1;
}
public DataSet TableToDataSet(Table table)
{
DataSet ds = new DataSet();
DataTable dt = new DataTable("Dimensions");
ds.Tables.Add(dt);
//Add headers
for (int i = 0; i < table.Rows[0].Cells.Count; i++)
{
DataColumn col = new DataColumn();
TextBox headerTxtBox = (TextBox)table.Rows[0].Cells[i].Controls[0];
col.ColumnName = headerTxtBox.Text;
col.Caption = headerTxtBox.Text;
dt.Columns.Add(col);
}
for (int i = 0; i < table.Rows.Count; i++)
{
DataRow valueRow = dt.NewRow();
for (int x = 0; x < table.Rows[i].Cells.Count; x++)
{
TextBox valueTextBox = (TextBox)table.Rows[i].Cells[x].Controls[0];
valueRow[x] = valueTextBox.Text;
}
dt.Rows.Add(valueRow);
}
return ds;
}
public Table DataSetToTable(DataSet ds)
{
DataTable dt = ds.Tables["Dimensions"];
Table newTable = new Table();
//Add headers
TableRow headerRow = new TableRow();
for (int i = 0; i < dt.Columns.Count; i++)
{
TableCell headerCell = new TableCell();
TextBox headerTxtBox = new TextBox();
headerTxtBox.ID = "HeadersTxtBox" + i.ToString();
headerTxtBox.Font.Bold = true;
headerTxtBox.Text = dt.Columns[i].ColumnName;
headerCell.Controls.Add(headerTxtBox);
headerRow.Cells.Add(headerCell);
}
newTable.Rows.Add(headerRow);
//Add value rows
for (int i = 0; i < dt.Rows.Count; i++)
{
TableRow valueRow = new TableRow();
for (int x = 0; x < dt.Columns.Count; x++)
{
TableCell valueCell = new TableCell();
TextBox valueTxtBox = new TextBox();
valueTxtBox.ID = "ValueTxtBox" + i.ToString() + i + x + x.ToString();
valueTxtBox.Text = dt.Rows[i][x].ToString();
valueCell.Controls.Add(valueTxtBox);
valueRow.Cells.Add(valueCell);
}
newTable.Rows.Add(valueRow);
}
return newTable;
}
public DataSet DefaultDataSet(int rows, int cols)
{
DataSet ds = new DataSet();
DataTable dt = new DataTable("Dimensions");
ds.Tables.Add(dt);
DataColumn nameCol = new DataColumn();
nameCol.Caption = "Name";
nameCol.ColumnName = "Name";
nameCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(nameCol);
DataColumn widthCol = new DataColumn();
widthCol.Caption = "Width";
widthCol.ColumnName = "Width";
widthCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(widthCol);
if (cols > 2)
{
DataColumn heightCol = new DataColumn();
heightCol.Caption = "Height";
heightCol.ColumnName = "Height";
heightCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(heightCol);
}
if (cols > 3)
{
DataColumn depthCol = new DataColumn();
depthCol.Caption = "Depth";
depthCol.ColumnName = "Depth";
depthCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(depthCol);
}
if (cols > 4)
{
int newColCount = cols - 4;
for (int i = 0; i < newColCount; i++)
{
DataColumn newCol = new DataColumn();
newCol.Caption = "New " + i.ToString();
newCol.ColumnName = "New " + i.ToString();
newCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(newCol);
}
}
for (int i = 0; i < rows; i++)
{
DataRow newRow = dt.NewRow();
newRow["Name"] = "Name " + i.ToString();
newRow["Width"] = "Width " + i.ToString();
if (cols > 2)
{
newRow["Height"] = "Height " + i.ToString();
}
if (cols > 3)
{
newRow["Depth"] = "Depth " + i.ToString();
}
dt.Rows.Add(newRow);
}
return ds;
}
public DataSet XMLToDataSet(string xml)
{
StringReader sr = new StringReader(xml);
DataSet ds = new DataSet();
ds.ReadXml(sr);
return ds;
}
public string DataSetToStringXML(DataSet ds)
{
XmlDocument _XMLDoc = new XmlDocument();
_XMLDoc.LoadXml(ds.GetXml());
StringWriter sw = new StringWriter();
XmlTextWriter xw = new XmlTextWriter(sw);
XmlDocument xml = _XMLDoc;
xml.WriteTo(xw);
return sw.ToString();
}
private int rowCount
{
get { return (int)ViewState["rowCount"]; }
set { ViewState["rowCount"] = value; }
}
private int colCount
{
get { return (int)ViewState["colCount"]; }
set { ViewState["colCount"] = value; }
}
EDIT: Here's my .aspx as well in case you want to try it out in VS.
<asp:Panel ID="tablePanel" runat="server" CssClass="table-panel" />
<asp:Label ID="resultsLabel" runat="server" />
<asp:LinkButton ID="submit" Text="submit" runat="server" onclick="submit_Click" />
<asp:LinkButton ID="addColumn" Text="Add Column" runat="server"
onclick="addColumn_Click" />
<asp:LinkButton ID="addRow" Text="Add Row" runat="server" onclick="addRow_Click" />
Thanks in advance,
Marko
Just as I recommended in this other question, if you'd like some page logic to execute AFTER the buttons' Click event, put that code into the Page_PreRender instead.
You can read more about it here: ASP.NET page life cycle.
EDIT:
After examining your code more closely, I see that you add stuff and create new controls, which is not a good idea in the PreRender event.
Instead, put the code into a separate method. In the Page_Load, check if it is a postback and handle the case when it isn't.
In the buttons' click evnt, also add a call to that new method. (thus handling the IsPostback == true case)
OK I've solved the problem by following instructions in this post.
Here's my final code - feel free to use it if you ever need to create dynamic controls based on a counter.
Also I wouldn't mind feedback on the overall coding style, I always appreciate others' input.
protected void Page_Load(object sender, EventArgs e)
{
string xmlValue = ""; //To read a value from a database
if (xmlValue.Length > 0)
{
if (!Page.IsPostBack)
{
DataSet ds = XMLToDataSet(xmlValue);
Table dimensionsTable = DataSetToTable(ds);
tablePanel.Controls.Add(dimensionsTable);
DataTable dt = ds.Tables["Dimensions"];
rowCount = dt.Rows.Count;
colCount = dt.Columns.Count;
}
else
{
tablePanel.Controls.Add(DataSetToTable(DefaultDataSet(rowCount, colCount)));
}
}
else
{
if (!Page.IsPostBack)
{
rowCount = 2;
colCount = 4;
}
else
{
if (GetPostBackControl(this.Page).ID == "addRow")
{
rowCount = rowCount + 1;
}
else if (GetPostBackControl(this.Page).ID == "addColumn")
{
colCount = colCount + 1;
}
}
tablePanel.Controls.Add(DataSetToTable(DefaultDataSet(rowCount, colCount)));
}
}
protected void submit_Click(object sender, EventArgs e)
{
resultsLabel.Text = Server.HtmlEncode(DataSetToStringXML(TableToDataSet((Table)tablePanel.Controls[0])));
}
protected void addColumn_Click(object sender, EventArgs e)
{
}
protected void addRow_Click(object sender, EventArgs e)
{
}
public DataSet TableToDataSet(Table table)
{
DataSet ds = new DataSet();
DataTable dt = new DataTable("Dimensions");
ds.Tables.Add(dt);
//Add headers
for (int i = 0; i < table.Rows[0].Cells.Count; i++)
{
DataColumn col = new DataColumn();
TextBox headerTxtBox = (TextBox)table.Rows[0].Cells[i].Controls[0];
col.ColumnName = headerTxtBox.Text;
col.Caption = headerTxtBox.Text;
dt.Columns.Add(col);
}
for (int i = 0; i < table.Rows.Count; i++)
{
DataRow valueRow = dt.NewRow();
for (int x = 0; x < table.Rows[i].Cells.Count; x++)
{
TextBox valueTextBox = (TextBox)table.Rows[i].Cells[x].Controls[0];
valueRow[x] = valueTextBox.Text;
}
dt.Rows.Add(valueRow);
}
return ds;
}
public Table DataSetToTable(DataSet ds)
{
DataTable dt = ds.Tables["Dimensions"];
Table newTable = new Table();
//Add headers
TableRow headerRow = new TableRow();
for (int i = 0; i < dt.Columns.Count; i++)
{
TableCell headerCell = new TableCell();
TextBox headerTxtBox = new TextBox();
headerTxtBox.ID = "HeadersTxtBox" + i.ToString();
headerTxtBox.Font.Bold = true;
headerTxtBox.Text = dt.Columns[i].ColumnName;
headerCell.Controls.Add(headerTxtBox);
headerRow.Cells.Add(headerCell);
}
newTable.Rows.Add(headerRow);
//Add value rows
for (int i = 0; i < dt.Rows.Count; i++)
{
TableRow valueRow = new TableRow();
for (int x = 0; x < dt.Columns.Count; x++)
{
TableCell valueCell = new TableCell();
TextBox valueTxtBox = new TextBox();
valueTxtBox.ID = "ValueTxtBox" + i.ToString() + i + x + x.ToString();
valueTxtBox.Text = dt.Rows[i][x].ToString();
valueCell.Controls.Add(valueTxtBox);
valueRow.Cells.Add(valueCell);
}
newTable.Rows.Add(valueRow);
}
return newTable;
}
public DataSet DefaultDataSet(int rows, int cols)
{
DataSet ds = new DataSet();
DataTable dt = new DataTable("Dimensions");
ds.Tables.Add(dt);
DataColumn nameCol = new DataColumn();
nameCol.Caption = "Name";
nameCol.ColumnName = "Name";
nameCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(nameCol);
DataColumn widthCol = new DataColumn();
widthCol.Caption = "Width";
widthCol.ColumnName = "Width";
widthCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(widthCol);
if (cols > 2)
{
DataColumn heightCol = new DataColumn();
heightCol.Caption = "Height";
heightCol.ColumnName = "Height";
heightCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(heightCol);
}
if (cols > 3)
{
DataColumn depthCol = new DataColumn();
depthCol.Caption = "Depth";
depthCol.ColumnName = "Depth";
depthCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(depthCol);
}
if (cols > 4)
{
int newColCount = cols - 4;
for (int i = 0; i < newColCount; i++)
{
DataColumn newCol = new DataColumn();
newCol.Caption = "New " + i.ToString();
newCol.ColumnName = "New " + i.ToString();
newCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(newCol);
}
}
for (int i = 0; i < rows; i++)
{
DataRow newRow = dt.NewRow();
newRow["Name"] = "Name " + i.ToString();
newRow["Width"] = "Width " + i.ToString();
if (cols > 2)
{
newRow["Height"] = "Height " + i.ToString();
}
if (cols > 3)
{
newRow["Depth"] = "Depth " + i.ToString();
}
dt.Rows.Add(newRow);
}
return ds;
}
public DataSet XMLToDataSet(string xml)
{
StringReader sr = new StringReader(xml);
DataSet ds = new DataSet();
ds.ReadXml(sr);
return ds;
}
public string DataSetToStringXML(DataSet ds)
{
XmlDocument _XMLDoc = new XmlDocument();
_XMLDoc.LoadXml(ds.GetXml());
StringWriter sw = new StringWriter();
XmlTextWriter xw = new XmlTextWriter(sw);
XmlDocument xml = _XMLDoc;
xml.WriteTo(xw);
return sw.ToString();
}
private int rowCount
{
get { return (int)ViewState["rowCount"]; }
set { ViewState["rowCount"] = value; }
}
private int colCount
{
get { return (int)ViewState["colCount"]; }
set { ViewState["colCount"] = value; }
}
public static Control GetPostBackControl(Page page)
{
Control control = null;
string ctrlname = page.Request.Params.Get("__EVENTTARGET");
if (ctrlname != null && ctrlname != string.Empty)
{
control = page.FindControl(ctrlname);
}
else
{
foreach (string ctl in page.Request.Form)
{
Control c = page.FindControl(ctl);
if (c is System.Web.UI.WebControls.Button)
{
control = c;
break;
}
}
}
return control;
}
move this code:
tablePanel.Controls.Add(DataSetToTable(DefaultDataSet(rowCount, colC....
To the prerender event to make the table bind to its data after the button click fired.