ASP C# Add Row to Table and Survive Postback - c#

I'm looking for a simple way to create a running table of data input by a user in a submit form. The table really just needs to add a row with data that was just input, but more importantly, survive postback.
The table should have a header, then a row per 'set' of data entered the last submit.
For example:
<asp:Table ID="lastRecordTable" runat="server" ViewStateMode="Enabled"
AutoPostBack="true">
<asp:TableHeaderRow>
<asp:TableCell>A</asp:TableCell>
<asp:TableCell>B</asp:TableCell>
<asp:TableCell>C</asp:TableCell>
<asp:TableCell>D</asp:TableCell>
</asp:TableHeaderRow>
<asp:TableRow>
<asp:TableCell>1</asp:TableCell>
<asp:TableCell>2</asp:TableCell>
<asp:TableCell>3</asp:TableCell>
<asp:TableCell>4</asp:TableCell>
</asp:TableRow>
</asp:Table>
Code Behind:
TableRow row = new TableRow();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TableCell cell3 = new TableCell();
TableCell cell4 = new TableCell();
cell1.Text = 1.ToString();
cell1.Text = 2.ToString();
cell1.Text = 3.ToString();
cell1.Text = 4.ToString();
row.Cells.Add(cell1);
row.Cells.Add(cell2);
row.Cells.Add(cell3);
row.Cells.Add(cell4);
lastRecordTable.Rows.Add(row);
Any advice is appreciated.

Because you add the rows dynamically, you need to (re)create them on every page load, and that includes a PostBack. So move the adding of the row outside the IsPostBack check.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//not here
}
//but here
TableRow row = new TableRow();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TableCell cell3 = new TableCell();
TableCell cell4 = new TableCell();
cell1.Text = 1.ToString();
cell1.Text = 2.ToString();
cell1.Text = 3.ToString();
cell1.Text = 4.ToString();
row.Cells.Add(cell1);
row.Cells.Add(cell2);
row.Cells.Add(cell3);
row.Cells.Add(cell4);
lastRecordTable.Rows.Add(row);
}
You don't need ViewStateMode="Enabled" and AutoPostBack="true" for this to work.

This is what I got to work:
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
}
lastRecordTable();
}
Table Method:
public void lastRecordTable()
{
if (Session["lastRecord"] == null)
{
DataTable dt = new DataTable();
dt.Columns.Add("1");
dt.Columns.Add("2");
dt.Columns.Add("3");
dt.Columns.Add("4");
Session["lastRecord"] = dt;
GridView1.DataSource = dt;
GridView1.DataBind();
}
else
{
DataTable dt = (DataTable)Session["lastRecord"];
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
Modify Table:
protected void buttonSubmit_Click(object sender, EventArgs e)
{
//do stuff here
DataTable dt = Session["lastRecord"] as DataTable;
DataRow row = dt.NewRow();
row["1"] = "A";
row["2"] = "B";
row["3"] = "C";
row["4"] = "D";
dt.Rows.Add(row);
Session["lastRecord"] = dt;
lastRecordTable();
}
ASP:
<asp:GridView ID="GridView1" runat="server" ViewStateMode="Enabled"
AutoPostBack="true"></asp:GridView>
I'm very new to asp c#, so not 100% sure this is 'correct', but it works!

Related

Bug in adding rows to table on the fly

i try adding rows to table on the fly from DataBase but its always the last row that appears only where am i wrong ?
TableCell pNameCell = new TableCell();
TableCell pDescCell = new TableCell();
TableCell pPriceCell = new TableCell();
TableCell pStockCell = new TableCell();
TableCell buyProduct = new TableCell();
HyperLink hl = new HyperLink();
//ds is DataSet
foreach (DataRow dRow in ds.Tables[0].Rows)
{
TableRow row = new TableRow();
pNameCell.Text = dRow["name"].ToString();
row.Cells.Add(pNameCell);
pDescCell.Text = dRow["description"].ToString();
row.Cells.Add(pDescCell);
pPriceCell.Text = dRow["price"].ToString();
row.Cells.Add(pPriceCell);
pStockCell.Text = dRow["Qty"].ToString();
row.Cells.Add(pStockCell);
hl.Text = "Add To Cart";
hl.NavigateUrl = "BuyProduct.aspx?id="+ dRow["pro_id"].ToString();
hl.CssClass = "btn btn-primary";
buyProduct.Controls.Add(hl);
row.Cells.Add(buyProduct);
//TProducts is asp:table ID
TProducts.Rows.Add(row);
}
it should show all the data rows in able
Your table cells are not unique to each iteration of the loop. When you add a cell variable to a row, it maintains a reference to that variable, not a copy. So then in the next iteration of the loop you overwrite the cell variable with the value from the new row, this will also update all the references to that cell.
To fix it, simply move the table cell declarations inside the loop, then their scope will be limited to that iteration, and new variables will be created each time you loop - just like the table row variable already is, in fact:
//ds is DataSet
foreach (DataRow dRow in ds.Tables[0].Rows)
{
TableCell pNameCell = new TableCell();
TableCell pDescCell = new TableCell();
TableCell pPriceCell = new TableCell();
TableCell pStockCell = new TableCell();
TableCell buyProduct = new TableCell();
HyperLink hl = new HyperLink();
TableRow row = new TableRow();
pNameCell.Text = dRow["name"].ToString();
row.Cells.Add(pNameCell);
pDescCell.Text = dRow["description"].ToString();
row.Cells.Add(pDescCell);
pPriceCell.Text = dRow["price"].ToString();
row.Cells.Add(pPriceCell);
pStockCell.Text = dRow["Qty"].ToString();
row.Cells.Add(pStockCell);
hl.Text = "Add To Cart";
hl.NavigateUrl = "BuyProduct.aspx?id="+ dRow["pro_id"].ToString();
hl.CssClass = "btn btn-primary";
buyProduct.Controls.Add(hl);
row.Cells.Add(buyProduct);
//TProducts is table ID
TProducts.Rows.Add(row);
}

How to get value from a cell in table C#

I have table and each row contains a button. If I click the button, I want to retrieve the value from the first column in that particular row. This is my code, how can I do that. Thank you
foreach (var c in list)
{
TableRow row = new TableRow();
TableCell c0 = new TableCell();
c0.Text = string.Format("<img src='"+c.Movie_poster+ "'/>");
TableCell c1 = new TableCell();
c1.Text = c.Name;
TableCell c2 = new TableCell();
c2.Text = c.Date.ToStirng();
TableCell c3 = new TableCell();
c3.Text = c.desc;
TableCell c4 = new TableCell();
c4.Text = c.genre;
TableCell c5 = new TableCell();
//Add each string to cell in row
row.Cells.Add(c0);
row.Cells.Add(c1);
row.Cells.Add(c2);
row.Cells.Add(c3);
row.Cells.Add(c4);
row.Cells.Add(c5);
//Add the row to the table
Table.Rows.Add(row);
Button getname = new Button();
getname.Text = "Reserve";
getname.Click+= new EventHandler(getname_Click);
c5.Controls.Add(getname);
}
}
protected void reserve_Click(object sender,EventArgs e)
{
Button btn = (Button)sender;
TableRow row = (TableRow)btn.
string name = row.Cells[1].Text;
lbl.Text = name;
}
Before create button you should write a new attribute with Row number.
//Add the row to the table
Table.Rows.Add(row);
Button getname = new Button();
getname.Attributes.Add("idRow", idrow);
idrow += 1;
getname.Text = "Reserve";
getname.Click += new EventHandler(getname_Click);
Then in you reserve_Click you should get the row with the ID stored in button attributes
Button btn = (Button)sender;
int idRow = int.Parse(btn.Attributes["id"]);
TableRow row = t.Rows[idRow];
You can bind the value of the Column to the Button as a CommandArgument.
Button getname = new Button();
getname.Text = "Reserve";
getname.CommandName = "Reserve";
getname.CommandArgument = "Column Value";
getname.Command += new CommandEventHandler(Button1_Command);
And then in the Button Command
protected void Button1_Command(object sender, CommandEventArgs e)
{
if (e.CommandName == "Reserve")
{
string columnValue = e.CommandArgument.ToString();
}
}

Show Total Row In Grid Each Time Name Changes

I am attempting to display a grid on my page and each time the name in the grid changes display a Total for that name. However, I keep getting a error of Object not set to instance of an object This is my syntax I am trying, can someone take a look and fill me in on what I am doing wrong?
<asp:GridView ID="gvTest" runat="server" OnDataBound = "gvODB" OnRowCreated = "gvORC" >
<Columns>
<asp:BoundField DataField="" HeaderText="userID"></asp:BoundField>
<asp:BoundField DataField="employeename" HeaderText="Name"></asp:BoundField>
<asp:BoundField DataField="hoursworked" HeaderText="Daily Hours"></asp:BoundField>
</Columns>
</asp:GridView>
private int currentId = 0;
private decimal subTotal = 0;
private decimal total = 0;
private int subTotalRowIndex = 0;
protected void gvORC(object sender, GridViewRowEventArgs e)
{
DataTable dt = new DataTable();
subTotal = 0;
try
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
dt = (e.Row.DataItem as DataRowView).DataView.Table;
int userID = Convert.ToInt32(dt.Rows[e.Row.RowIndex]["userID"]);
total += Convert.ToDecimal(dt.Rows[e.Row.RowIndex]["hoursworked"]);
if (userID != currentId)
{
if (e.Row.RowIndex > 0)
{
for (int i = subTotalRowIndex; i < e.Row.RowIndex; i++)
{
subTotal += Convert.ToDecimal(gvTest.Rows[i].Cells[2].Text);
}
this.AddTotalRow("Total", subTotal.ToString("N2"));
subTotalRowIndex = e.Row.RowIndex;
}
currentId = userID;
}
}
}
catch (Exception exception)
{
throw exception;
}
}
protected void AddTotalRow(string labelText, string value)
{
GridViewRow row = new GridViewRow(0, 0, DataControlRowType.DataRow, DataControlRowState.Normal);
row.BackColor = ColorTranslator.FromHtml("#F9F9F9");
row.Cells.AddRange(new TableCell[3] { new TableCell (), //Empty Cell
new TableCell { Text = labelText, HorizontalAlign = HorizontalAlign.Right},
new TableCell { Text = value, HorizontalAlign = HorizontalAlign.Right } });
gvTest.Controls[0].Controls.Add(row);
}
EDIT --
The grid will return a userid, username and hours worked. And I want a total to be displayed for each individual username returned. Something like so
userid name hours
1646 Red 16
1646 Red 8
Total 24
1812 Blue 6
1812 Blue 8
Total 14
Now a userid, name and hours will ALWAYS be returned, the only time a null value would be returned is when all results have been added to the grid.
The idea is to generate the html that will display your simple "report". There are any number of ways to do this. If the data is read only then using a Grid is less appropriate than just building a table or set of divs, etc. You can look into the Repeater or ListView but here I demonstrate a simple table element:
The aspx markup that has a simple asp:Table with runat server:
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<asp:Table runat="server" ID="usertbl" border="1">
</asp:Table>
</asp:Content>
The Code behind:
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Contrived Data table just because I need some data to demonstrate.
//I assume you are or can acquire a DataTable with your current solution.
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("UserID", typeof(int)));
dt.Columns.Add(new DataColumn("UserName", typeof(string)));
dt.Columns.Add(new DataColumn("Hours", typeof(int)));
DataRow row = dt.NewRow();
row[0] = 1646;
row[1] = "Red";
row[2] = 16;
dt.Rows.Add(row);
row = dt.NewRow();
row[0] = 1646;
row[1] = "Red";
row[2] = 8;
dt.Rows.Add(row);
row = dt.NewRow();
row[0] = 1812;
row[1] = "Blue";
row[2] = 6;
dt.Rows.Add(row);
row = dt.NewRow();
row[0] = 1812;
row[1] = "Blue";
row[2] = 14;
dt.Rows.Add(row);
//Simplify accumualtor logic by grouping on Userid
var users = dt.AsEnumerable().GroupBy(u => u[0]);
//For each group (each user id)
foreach (var item in users)
{
//adds the user hours
int accumulator = 0;
//For each set or rows in group
foreach (var dr in item)
{
accumulator += int.Parse(dr[2].ToString());
//Create a table row
TableRow tr = new TableRow();
//Add the cells to the table row
TableCell userIdCell = new TableCell();
userIdCell.Text = item.Key.ToString();
tr.Cells.Add(userIdCell);
TableCell userNameCell = new TableCell();
userNameCell.Text = dr[1].ToString();
tr.Cells.Add(userNameCell);
TableCell hoursCell = new TableCell();
hoursCell.Text = dr[2].ToString();
tr.Cells.Add(hoursCell);
//Add the row to the table
usertbl.Rows.Add(tr);
}
//create summary row
TableRow totalRow = new TableRow();
//Skip a cells
totalRow.Cells.Add(new TableCell());
totalRow.Cells.Add(new TableCell());
//total cell
TableCell userTotalCell = new TableCell();
userTotalCell.Text = accumulator.ToString();
totalRow.Cells.Add(userTotalCell);
//Finally add the row
usertbl.Rows.Add(totalRow);
}
}
}
}
and finally the result:

Dynamically Created Form from Controls and Submit Click

Why btnSave_Click doesn't fire? It does postback when I click it but not jump in to handler.
if (Session["mytable"] != null)
pnlContent.Controls.Add((Table)Session["mytable"]);
else
{
Table table = new Table();
foreach (var item in Items)
{
TableRow row = new TableRow();
table.Rows.Add(row);
if (item.ColumnTypeName == "String")
{
TableCell cell = new TableCell();
row.Cells.Add(cell);
cell.Controls.Add(new LiteralControl(item.ColumnName));
TextBox textbox = new TextBox();
textbox.ID = item.ColumnName;
TableCell cell2 = new TableCell();
row.Cells.Add(cell2);
cell2.Controls.Add(textbox);
}
}
LinkButton btnSave = new LinkButton();
btnSave.ID = "btnSave";
btnSave.Click += new EventHandler(btnSave_Click);
btnSave.Text = "Submit";
TableRow row1 = new TableRow();
table.Rows.Add(row1);
TableCell cell3 = new TableCell();
row1.Cells.Add(cell3);
cell3.Controls.Add(btnSave);
pnlContent.Controls.Add(table);
Session["mytable"] = table;
}
protected void btnSave_Click(object sender, EventArgs e)
{
//TADAA
}

How to put controls in the footer of the gridview(not belongs to specific column)

Q:
How to put a table from two columns and one row in the footer of the gridview. the footer doesn't belong to any column .
You could generate the footer manually from codebehind in RowCreated of the GridView.
For example:
protected void GridView1_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Footer) {
var grid = (GridView)sender;
Label lbl1 = new Label();
Label lbl2 = new Label();
TableCell footerCell = new TableCell();
TableCell cell1 = new TableCell();
TableCell cell2 = new TableCell();
TableRow footerRow = new TableRow();
Table footerTable = new Table();
e.Row.Cells.Clear();
footerCell.Controls.Add(footerTable);
footerTable.Rows.Add(footerRow);
lbl1.ID = "lbl1";
lbl2.ID = "lbl2";
cell1.Controls.Add(lbl1);
cell2.Controls.Add(lbl2);
footerRow.Cells.Add(cell1);
footerRow.Cells.Add(cell2);
e.Row.Cells.Add(footerCell);
}
}
protected void GridView1_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Footer) {
DataRow row = getFooterSource().Rows[0];
var lbl1 = (Label)e.Row.FindControl("lbl1");
var lbl2 = (Label)e.Row.FindControl("lbl2");
lbl1.Text = row["Col1"];
lbl2.Text = row["Col2"];
e.Row.Cells[0].ColumnSpan = ((DataTable)((GridView)sender).DataSource).Columns.Count;
}
}
//get some mock-data
private DataTable getFooterSource()
{
DataTable tblFooter = new DataTable("Footer");
tblFooter.Columns.Add(new DataColumn("Col1", typeof(string)));
tblFooter.Columns.Add(new DataColumn("Col2", typeof(string)));
var footerRow = tblFooter.NewRow();
footerRow(0) = "first column's value";
footerRow(1) = "second column's value";
tblFooter.Rows.Add(footerRow);
return tblFooter;
}

Categories

Resources