bertybasset
asked on
ASP.NET Dynamic Column Binding Problem accessing coulmns on Update
Hi,
I'm binding a crosstab query to a datagrid. As a result the columns can vary in name and number, so I am dynamically create the columns at runtime. On update I need to get the column name dynamically as it is used in the sql update.
The markup for the datagrid looks this:
<asp:datagrid id="dgTimes"
OnEditCommand="dgTimes_Edi t" OnUpdateCommand="dgTimes_U pdate" OnCancelCommand="dgTimes_C ancel"
Runat="server" AutoGenerateColumns="False ">
<Columns>
<asp:EditCommandColumn EditText="Edit" HeaderText="Function" CancelText="Cancel" UpdateText="Update"></asp: EditComman dColumn>
</Columns>
</asp:datagrid>
In my Page_Load I call up BindGrid:
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
BindGrid();
}
}
my BindGrid:
- executes a stored proc to return the cross tab (between a range of dates) as a dataset
- dynamically defines BoundColumns using the dataset ColumnNames and adds them to the datagrid
- binds the dataset to the datagrid
It looks like this:
protected void BindGrid()
{
// execute a stored proc to return the cross tab (between a range of dates) as a dataset
SqlParameter[] myParamArray = new SqlParameter[2];
myParamArray[0] = new SqlParameter("@startDate", "2004/01/01");
myParamArray[1] = new SqlParameter("@endDate", "2004/05/12");
DataSet ds= SqlHelper.ExecuteDataset(C onfigurati onSettings .AppSettin gs["dbConn "].ToStrin g(),Comman dType.Stor edProcedur e, "sp_GetHours" ,myParamArray);
//dynamically define BoundColumns using the dataset ColumnNames and adds them to the
int numCols = ds.Tables[0].Columns.Count ;
for (int i=0; i<numCols;i++)
{
DataColumn dc = ds.Tables[0].Columns[i];
BoundColumn col = new BoundColumn();
col.HeaderText=dc.ColumnNa me;
col.DataField=dc.ColumnNam e;
dgTimes.Columns.Add(col);
}
//bind the dataset to the datagrid
dgTimes.DataSource=ds.Tabl es[0].Defa ultView;
dgTimes.DataBind();
ds.Dispose();
}
So far so good!
However when the update handler is fired it cannot see any of the columns in the grid apart from the EditCommandColumn.
protected void dgTimes_Update(Object sender, DataGridCommandEventArgs e)
{
int numCols = e.Item.Cells.Count;
Response.Write ("numCols: " + numCols);
}
numCols comes out as 1.
What I want to do is loop through the cells on the edit row:
for (int i=0; i<numCols; i++)
{
if (e.Item.Cells[i].Controls[ 0] is TextBox)
{
String colname = dgTimes.Columns[i].HeaderT ext.ToStri ng();
String datainput= e.Item.Cells[i].Text;
//sql to insert into database to go here
}
}
but as I'm getting numCols = 1 I can't do this
Can anyone help???
I'm binding a crosstab query to a datagrid. As a result the columns can vary in name and number, so I am dynamically create the columns at runtime. On update I need to get the column name dynamically as it is used in the sql update.
The markup for the datagrid looks this:
<asp:datagrid id="dgTimes"
OnEditCommand="dgTimes_Edi
Runat="server" AutoGenerateColumns="False
<Columns>
<asp:EditCommandColumn EditText="Edit" HeaderText="Function" CancelText="Cancel" UpdateText="Update"></asp:
</Columns>
</asp:datagrid>
In my Page_Load I call up BindGrid:
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
BindGrid();
}
}
my BindGrid:
- executes a stored proc to return the cross tab (between a range of dates) as a dataset
- dynamically defines BoundColumns using the dataset ColumnNames and adds them to the datagrid
- binds the dataset to the datagrid
It looks like this:
protected void BindGrid()
{
// execute a stored proc to return the cross tab (between a range of dates) as a dataset
SqlParameter[] myParamArray = new SqlParameter[2];
myParamArray[0] = new SqlParameter("@startDate",
myParamArray[1] = new SqlParameter("@endDate", "2004/05/12");
DataSet ds= SqlHelper.ExecuteDataset(C
//dynamically define BoundColumns using the dataset ColumnNames and adds them to the
int numCols = ds.Tables[0].Columns.Count
for (int i=0; i<numCols;i++)
{
DataColumn dc = ds.Tables[0].Columns[i];
BoundColumn col = new BoundColumn();
col.HeaderText=dc.ColumnNa
col.DataField=dc.ColumnNam
dgTimes.Columns.Add(col);
}
//bind the dataset to the datagrid
dgTimes.DataSource=ds.Tabl
dgTimes.DataBind();
ds.Dispose();
}
So far so good!
However when the update handler is fired it cannot see any of the columns in the grid apart from the EditCommandColumn.
protected void dgTimes_Update(Object sender, DataGridCommandEventArgs e)
{
int numCols = e.Item.Cells.Count;
Response.Write ("numCols: " + numCols);
}
numCols comes out as 1.
What I want to do is loop through the cells on the edit row:
for (int i=0; i<numCols; i++)
{
if (e.Item.Cells[i].Controls[
{
String colname = dgTimes.Columns[i].HeaderT
String datainput= e.Item.Cells[i].Text;
//sql to insert into database to go here
}
}
but as I'm getting numCols = 1 I can't do this
Can anyone help???
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
tovvenki and rohanpandya,
thanks for you responses.
Tovennki hit the nail on the head - I've added the dynamic column building to the page load. When I did this I could then access the datagrid columns collection. The only problem then was that I couldn't access the Cells collection of the Selected Row. It works now that I bind the grid each time the page loads (ie got rid of the (!PostBack) condition). I'm guessing that as I'm creating the datagrid dynamically, it could in theory vary between page loads, and thus I have to rebind on each load (????).
My full code is:
DataSet ds;
private void Page_Load(object sender, System.EventArgs e)
{
// execute a stored proc to return the cross tab (between a range of dates) as a dataset
SqlParameter[] myParamArray = new SqlParameter[2];
myParamArray[0] = new SqlParameter("@startDate", "2004/01/01");
myParamArray[1] = new SqlParameter("@endDate", "2004/05/12");
ds= SqlHelper.ExecuteDataset(C onfigurati onSettings .AppSettin gs["dbConn "].ToStrin g(),Comman dType.Stor edProcedur e, "sp_GetHours" ,myParamArray);
//dynamically define BoundColumns using the dataset ColumnNames and adds them to the
int numCols = ds.Tables[0].Columns.Count ;
for (int i=0; i<numCols;i++)
{
DataColumn dc = ds.Tables[0].Columns[i];
if (dc.ColumnName.IndexOf("fk ")==-1)
{
BoundColumn col = new BoundColumn();
col.HeaderText=dc.ColumnNa me;
col.DataField=dc.ColumnNam e;
dgTimes.Columns.Add(col);
}
}
BindGrid();
}
protected void BindGrid()
{
//bind the dataset to the datagrid
dgTimes.DataSource=ds.Tabl es[0].Defa ultView;
dgTimes.DataBind();
ds.Dispose();
}
protected void dgTimes_Edit(Object sender, DataGridCommandEventArgs e)
{
dgTimes.EditItemIndex = (int) e.Item.ItemIndex;
BindGrid();
}
protected void dgTimes_Cancel(Object sender, DataGridCommandEventArgs e)
{
dgTimes.EditItemIndex = -1;
BindGrid();
}
protected void dgTimes_Update(Object sender, DataGridCommandEventArgs e)
{
int numCols = e.Item.Cells.Count;
for (int i=0; i<numCols; i++)
{
if (e.Item.Cells[i].Controls[ 0] is TextBox)
{
String colname = dgTimes.Columns[i].HeaderT ext.ToStri ng();
String dataValue = ((TextBox) e.Item.Cells[i].Controls[0 ]).Text;
Response.Write ("colname " + colname + "<BR>");
Response.Write ("dataValue " + dataValue + "<BR>");
}
}
dgTimes.EditItemIndex = -1;
BindGrid();
}
thanks for you responses.
Tovennki hit the nail on the head - I've added the dynamic column building to the page load. When I did this I could then access the datagrid columns collection. The only problem then was that I couldn't access the Cells collection of the Selected Row. It works now that I bind the grid each time the page loads (ie got rid of the (!PostBack) condition). I'm guessing that as I'm creating the datagrid dynamically, it could in theory vary between page loads, and thus I have to rebind on each load (????).
My full code is:
DataSet ds;
private void Page_Load(object sender, System.EventArgs e)
{
// execute a stored proc to return the cross tab (between a range of dates) as a dataset
SqlParameter[] myParamArray = new SqlParameter[2];
myParamArray[0] = new SqlParameter("@startDate",
myParamArray[1] = new SqlParameter("@endDate", "2004/05/12");
ds= SqlHelper.ExecuteDataset(C
//dynamically define BoundColumns using the dataset ColumnNames and adds them to the
int numCols = ds.Tables[0].Columns.Count
for (int i=0; i<numCols;i++)
{
DataColumn dc = ds.Tables[0].Columns[i];
if (dc.ColumnName.IndexOf("fk
{
BoundColumn col = new BoundColumn();
col.HeaderText=dc.ColumnNa
col.DataField=dc.ColumnNam
dgTimes.Columns.Add(col);
}
}
BindGrid();
}
protected void BindGrid()
{
//bind the dataset to the datagrid
dgTimes.DataSource=ds.Tabl
dgTimes.DataBind();
ds.Dispose();
}
protected void dgTimes_Edit(Object sender, DataGridCommandEventArgs e)
{
dgTimes.EditItemIndex = (int) e.Item.ItemIndex;
BindGrid();
}
protected void dgTimes_Cancel(Object sender, DataGridCommandEventArgs e)
{
dgTimes.EditItemIndex = -1;
BindGrid();
}
protected void dgTimes_Update(Object sender, DataGridCommandEventArgs e)
{
int numCols = e.Item.Cells.Count;
for (int i=0; i<numCols; i++)
{
if (e.Item.Cells[i].Controls[
{
String colname = dgTimes.Columns[i].HeaderT
String dataValue = ((TextBox) e.Item.Cells[i].Controls[0
Response.Write ("colname " + colname + "<BR>");
Response.Write ("dataValue " + dataValue + "<BR>");
}
}
dgTimes.EditItemIndex = -1;
BindGrid();
}
ASKER
btw you'll see that I've put a condition in it so that it does not render any of the foreign keys that are in the dataset - these are all identified by "fk":
if (dc.ColumnName.IndexOf("fk ")==-1)
{
//create column
}
if (dc.ColumnName.IndexOf("fk
{
//create column
}
hey if u bind on each page_load...
when u edit some value after clicking "edit" button and hit "update"...it goes to page_load and again over writes the changed values with the old values...so i don't think it updates...did u try that
when u edit some value after clicking "edit" button and hit "update"...it goes to page_load and again over writes the changed values with the old values...so i don't think it updates...did u try that
fill your datagrid into the page load event and do following. And also when update command is fired there is textboes in the datagrid so do following
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim connectionString As String = "Persist Security Info=False;Server=localhos
objConnection = New SqlConnection(connectionSt
objCommand = New SqlCommand
objCommand.CommandText = "Select * from tblUserProfile"
objCommand.Connection = objConnection
objDataAdapter = New SqlDataAdapter
objDataset = New DataSet
objDataAdapter.SelectComma
objConnection.Open()
objDataAdapter.Fill(objDat
objConnection.Close()
dgTest.DataSource = objDataset.Tables(0).Defau
dgTest.DataBind()
End Sub
Private Sub doEdit(ByVal sender As Object, ByVal e As DataGridCommandEventArgs) Handles dgTest.EditCommand
dgTest.EditItemIndex = e.Item.ItemIndex
dgTest.DataBind()
End Sub
Private Sub doInsert(ByVal sender As Object, ByVal e As DataGridCommandEventArgs) Handles dgTest.UpdateCommand
dgTest.SelectedIndex = e.Item.ItemIndex
Dim txtTest As TextBox = e.Item.Cells(1).Controls(0
Dim test As String = txtTest.Text
Response.Write(txtTest.Tex
End Sub