I have tried a lot and have reached a dead end.
I have a to show multiple gridviews on one page and all these are getting populated dynamically.
i have figured a way to populate the gridview dynamically and display them, but i cannot get how to modify these values and display them as i want.
here is the code. for .aspx page
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder2" Runat="Server">
<asp:Panel ID="Panel1" runat="server" ScrollBars ="Auto" Height="500px" BorderColor="#003399" BorderWidth="3px">
</asp:Panel>
</asp:Content>
and here is the code for .aspx.cs
for (int j = 0; j < 5; j++)
{
GridView Grid = new GridView();
ArrayList machID = new ArrayList();
ArrayList machName = new ArrayList();
Grid.ID = machGrps[j].ToString();
Grid.AllowSorting = true;
Grid.CellSpacing = 2;
Grid.GridLines = GridLines.None;
Grid.Width = Unit.Percentage(100);
DataTable dt = new DataTable();
SqlConnection connection = new SqlConnection(Session["ConnectionStringSQL"].ToString());
connection.Open();
SqlCommand sqlCmd = new SqlCommand("select MachineID, MachineName from Machines", connection);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
sqlDa.Fill(dt);
connection.Close();
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
machID.Add(dt.Rows[i]["MachineID"].ToString());
machName.Add(dt.Rows[i]["MachineName"].ToString());
}
DataTable taskTable = new DataTable();
taskTable.Columns.Add("MachineID");
taskTable.Columns.Add("MachineName");
if (machID.Count != 0)
{
for (int i = 0; i < machID.Count; i++)
{
DataRow tableRow = taskTable.NewRow();
tableRow["MachineID"] = machID[i];
tableRow["MachineName"] = machName[i];
taskTable.Rows.Add(tableRow);
}
}
Session["TaskTable"] = taskTable;
Grid.DataSource = Session["TaskTable"];
Grid.DataBind();
Label label = new Label();
label.Text = "Machine Grp" + Grid.ID;
Panel1.Controls.Add(label);
Panel1.Controls.Add(Grid);
}
}
NOTE THIS CODE BELOW CANNOT BE DONE ANYMORE AS I POPULATE THE GRIDVIEW DIRECTLY FROM THE TABLES:
I used to modify like this when the ondatabound="GridView1_DataBound" if is called from the .aspx page
the databound code looks like this:
protected void GridView1_DataBound(object sender, EventArgs e)
{
foreach (GridViewRow myRow in GridView1.Rows)
{
//this is where ID is stored in an label template
Label Label3 = (Label)myRow.FindControl("Label3");
int val = Convert.ToInt32(Label3.Text);
Image Image5 = (Image)myRow.FindControl("Image5");
if (Convert.ToInt32(Label3.Text) < 0)
{
Image5.ImageUrl = "~/NewFolder1/warning_16x16.gif";
}
else
{
Image5.ImageUrl = "~/NewFolder1/1258341827_tick.png";
}
}
}
Two things:
protected void GridView1_DataBound(object sender, EventArgs e) {
foreach (GridViewRow myRow in GridView1.Rows) {
// blah blah blah code goes here
}
}
should be
//now e is a
protected void Grid_RowDataBound(object sender, GridViewRowEventArgs e) {
if (e.Row.RowType == DataControlRowType.DataRow) {
// blah blah blah, this lets you work on one row at a time.
// since the framework does this per row, you don't need to parse the gridview
// yourself, altho you're more than welcome to.
// But you can get more control this way. I promise.
Label Label3 = (Label)e.Row.FindControl("Label3");
int val = Convert.ToInt32(Label3.Text);
Image Image5 = (Image)e.Row.FindControl("Image5");
if (val < 0)
{
Image5.ImageUrl = "~/NewFolder1/warning_16x16.gif";
}
else
{
Image5.ImageUrl = "~/NewFolder1/1258341827_tick.png";
}
// alternately write the code above like this:
Image Image5 = (Image)e.Row.FindControl("Image5");
Image5.ImageUrl = (val < 0) ? "~/NewFolder1/warning_16x16.gif" : "~/NewFolder1/1258341827_tick.png";
// that's called the ternary operator. Takes up less space, does the same thing.
}
}
Please don't ignore this part
Now to the other part, are you aware that you can still bind in the backside like thus:
GridView1.RowDataBound += GridView1_RowDataBound;
Put it here:
for (int j = 0; j < 5; j++)
{
GridView Grid = new GridView();
ArrayList machID = new ArrayList();
ArrayList machName = new ArrayList();
//NEW LINE (doesn't need the comment or the blank space tho)
Grid.RowDataBound += Grid_RowDataBound;
Grid.ID = machGrps[j].ToString();
Grid.AllowSorting = true;
Grid.CellSpacing = 2;
Grid.GridLines = GridLines.None;
Grid.Width = Unit.Percentage(100);
Do your dynamic edits on GridView1_RowDataBound not on GridView1_DataBound
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Label Label3 = (Label)e.Row.FindControl("Label3");
....
}
}
Is it blowing up when you're binding the DataSource to the Session object?
Grid.DataSource = taskTable;
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";
protected void ddlbranchdate_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
DataTable dtgetvalues = new DataTable();
//objRetailPL.date = Convert.ToDateTime(hdndate.Value);
objRetailPL.branchdate = ddlbranchdate.SelectedItem.ToString();
dtgetvalues = objRetailBAL.getbradisdate(objRetailPL);
foreach(GridViewRow row in gvMeatDispatch.Rows)
{
DataTable dtpr = new DataTable();
DropDownList ddl1 = (DropDownList)row.FindControl("ddlpartyname");
objRetailPL.branch = dtgetvalues.Rows[0]["branch"].ToString();
dtpr = objRetailBAL.getbran(objRetailPL);
ddl1.DataSource = dtpr;
ddl1.DataTextField = "partyname";
ddl1.DataValueField = "sno";
ddl1.DataBind();
ddl1.Items.Add(new ListItem("--Select--", "0"));
ddl1.SelectedIndex = ddl1.Items.Count - 1;
}
}
}
why i am getting this exception?..
i am using Dynamic Gridview and adding Rows Dynamically with the help of Button Control..
Outside i am declare another dropdown list ..if user selected some value from this Dropdownlist
then automatically bind the values to Dynamic Gridview ,Dropdown list values..
This is my Setprevious Data in Dynamic control Method..Here i called Dropdownlist selectedindexchanged event ..like..
private void SetPreviousData()
{
try
{
int rowIndex = 0;
if (ViewState["CurrentTable"] != null)
{
DataTable dt = (DataTable)ViewState["CurrentTable"];
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
DropDownList ddlpname = (DropDownList)gvMeatDispatch.Rows[rowIndex].Cells[1].FindControl("ddlpartyname");
DropDownList ddlbt = (DropDownList)gvMeatDispatch.Rows[rowIndex].Cells[2].FindControl("ddlbirdtype");
TextBox txttotwt = (TextBox)gvMeatDispatch.Rows[rowIndex].Cells[3].FindControl("txttotwt");
TextBox txttransbirds1 = (TextBox)gvMeatDispatch.Rows[rowIndex].Cells[4].FindControl("txtrateforkg");
TextBox txtmort1 = (TextBox)gvMeatDispatch.Rows[rowIndex].Cells[5].FindControl("txtdcno");
// Dropdownlist selectedIndex Changed event
ddlbranchdate_SelectedIndexChanged(null, null);
ddlpname.SelectedValue = dt.Rows[i]["Col1"].ToString();
ddlbt.SelectedValue = dt.Rows[i]["Col2"].ToString();
txttotwt.Text = dt.Rows[i]["col3"].ToString();
txttransbirds1.Text = dt.Rows[i]["Col4"].ToString();
txtmort1.Text = dt.Rows[i]["Col5"].ToString();
rowIndex++;
}
}
}
}
I work several time on this functions but also not working at all.
I populate a gridview by code and I add a button that open a detail of row on click.
I try to add button while populate datatable but not work.
After I try to add button on row_databound method; the button it's rendering but not fire event click.
As follow a semplify code.
I hope that you are able to help me to solve this problem.
Thank's in advance and regards.
P
protected void btnSearch_Click(object sender, EventArgs e)
{
string sSearchQuery = "(" + TextBox1.Text + ")";
loadDynamicGrid(sSearchQuery);
}
private void loadDynamicGrid(string sSearchQuery)
{
//search
.....
var oHitColl = searcher.Search(oParser.Parse(sSearchQuery));
//istance of DataTable
gvResult.Columns.Clear();
gvResult.DataSource = null;
DataTable dt = new DataTable();
DataColumn dcol = new DataColumn("Id", typeof(System.String));
dt.Columns.Add(dcol);
dcol = new DataColumn("Table", typeof(System.String));
dt.Columns.Add(dcol);
dcol = new DataColumn("Summary", typeof(System.String));
dt.Columns.Add(dcol);
dcol = new DataColumn("Link", typeof(System.String));
dt.Columns.Add(dcol);
dcol = new DataColumn("Button", typeof(Button));
dt.Columns.Add(dcol);
//Populate la datatable
for (int i = 0; i < oHitColl.Length(); i++)
{
Document oDoc = oHitColl.Doc(i);
DataRow drow = dt.NewRow();
drow["Table"] = oDoc.Get("Table");
drow["Summary"] = oDoc.Get("Summary");
drow["Id"] = oDoc.Get("Id");
string url = ....".aspx";
drow["Link"] = linkText;
//Button btn = CreateButton("dinamicBtn" + i.ToString(), "dinamicBtn" + i.ToString());
//drow["Button"] = btn;
dt.Rows.Add(drow);
}
// add columus in GridView
foreach (DataColumn col in dt.Columns)
{
//Dichiarare i campi bindati e allocare la memoria che serve
BoundField bfield = new BoundField();
bfield.DataField = col.ColumnName;
bfield.HeaderText = col.ColumnName;
gvResult.Columns.Add(bfield);
}
gvResult.DataSource = dt;
gvResult.DataBind();
searcher.Close();
}
protected void gvResult_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Button btn = new Button();
btn = CreateButton("btnOpen_"+ e.Row.RowIndex.ToString(), "Open");
btn.DataBinding +=new EventHandler(btn_DataBinding);
e.Row.Cells[e.Row.Cells.Count - 1].Controls.Add(btn);
}
}
private Button CreateButton(string id, string name)
{
Button b = new Button();
b.Text = name;
b.ID = id;
b.Click += new EventHandler(Dynamic_Method);
b.DataBinding += new EventHandler(btn_DataBinding);
return b;
}
private void btn_DataBinding(object sender, EventArgs e)
{
object bound_value_obj = null;
Control ctrl = (Control)sender;
IDataItemContainer data_item_container = (IDataItemContainer)ctrl.NamingContainer;
bound_value_obj = DataBinder.Eval(data_item_container.DataItem,"gvResult.Rows.Count.ToString()");
}
protected void Dynamic_Method(object sender, EventArgs e)
{
Response.Write("You have clicked at: "+DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"));
}
Any control that you create dynamically need to be re-added at every postback, the events need to be hooked at every postback, etc. In addition to that, you should do this in the OnInit method.
for (int i = 0; i < form2.dataGridView1.Rows.Count; i++)
{
if ( form2.dataGridView2.Rows[i].Cells[0].Value != null &&
(bool) form2.dataGridView2.Rows[i].Cells[0].Value == true )
{
form2.dataGridView2.Rows.Add();
for (int j = 1; j < form2.dataGridView1.Columns.Count; j++)
form2.dataGridView2.Rows[i].Cells[j].Value =
form2.dataGridView1.Rows[i].Cells[j].Value;
}
}
the above code is not giving any result. please tell me how to copy the data of one datagridview to another?
Check Copy from datagridview and paste to second datagridview.
Also, you can do as the following:
//Bind datagridview to linq
var gd1 =
( from a in datagridview.Rows.Cast<DataGridViewRow>()
select new {Column1 = a.Cells["Column1"].Value.ToString() }).tolist();
//loop dg1 and save it to datagridview2
foreach(var b in dg1)
{
datagridview2.Rows.Add(b.Column1);
}
Regards
In form1 copy this code
private void Form1_Load(object sender,EventArgs e)
{
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.Columns.Insert(0, new DataGridViewCheckBoxColumn());
show_chkBox();
SqlConnection con = new SqlConnection("server=(local);DataBase=RIMS;User
d=sa;Password=Rootdb");
SqlCommand com = new SqlCommand("Select * from Master_City", con);
SqlDataAdapter da = new SqlDataAdapter(com);
DataSet ds = new DataSet();
da.Fill(ds, "city");
dataGridView1.DataSource = ds;
dataGridView1.DataMember = "city";
}
private void button1_Click_1(object sender, EventArgs e)
{
DataGridViewRow dr = dataGridView1.SelectedRows[0];
dtItems.Columns.Add("city_ID");
dtItems.Columns.Add("city_Name");
dtItems.Columns.Add("status");
dtItems.Columns.Add("date");
if (dataGridView1.Rows.Count > 1)
{
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
if (dataGridView1.Rows[i].Cells[0].Value != null)
{
DataRow row;
row = dtItems.NewRow();
row["city_ID"] = dataGridView1.Rows[i].Cells[1].Value.ToString();
row["city_Name"] = dataGridView1.Rows[i].Cells[2].Value.ToString();
row["status"] = dataGridView1.Rows[i].Cells[3].Value.ToString();
row["date"] = dataGridView1.Rows[i].Cells[4].Value.ToString();
dtItems.Rows.Add(row);
}
}
}
Form2 frm = new Form2(dtItems);
frm.ShowDialog();
}
in form2 copy this code..
public Form2(DataTable dtIt)
{
dtItems = dtIt;
InitializeComponent();
}
private void AddEmptyRows()
{
for (int i = 1; i <= 5; i++)
{
dataGV.Rows.Add();
}
}
private void Form2_Load(object sender, EventArgs e)
{
AddEmptyRows();
for (int i = 0; i < dtItems.Rows.Count; i++)
{
dataGV.Rows[i].Cells[0].Value = dtItems.Rows[i]["city_ID"];
dataGV.Rows[i].Cells[1].Value = dtItems.Rows[i]["city_Name"];
dataGV.Rows[i].Cells[2].Value = dtItems.Rows[i]["status"];
dataGV.Rows[i].Cells[3].Value = dtItems.Rows[i]["date"];
}
dataGV.Enabled = true;
}
Mirror Data From one Data View into Another Data View
If you just want to mirror the data from one DataGridView in another one. For example: DataGridView1 mirror data in DataGridView2.
DataGridView2.DataSource = DataGridView1.DataSource;
Remember this will only mirror the data from on DataGridView in another one.
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.