Caius Jard Caius Jard - 1 year ago 111
ASP.NET (C#) Question

ASP.NET GridView - dynamic columns blank on postback, how to identify them for removal?

I've a GridView with a set of fixed (written into the ASPX markup) columns. Onto the end of this column collection, during the page load, I add another few columns (the number of columns varies according to how many key-value pairs I have stored in relation to the grid entities) and I set the IDs of the controls I dynamically add, to relate to the key:

//Dictionary<string, string> myDictionary ...
foreach (string in myDictionary.Keys)
{
var tf = new TemplateField();
tf.HeaderText = k;
tf.ItemTemplate = new Label("key_" + k);
gridview.Columns.Add(tf);
}


During the RowDataBound event I look through the key value pairs, call a
e.Row.FindControl
to find the label that should have this value, and populate the value:

foreach (var k in myDictionary.Keys)
{
Label lb = (Label)e.Row.FindControl("key_" + k);
lb.Text = myDictionary[k];
}


This works fine for the initial display, but on postback the page load code runs again. At this time, the gridview seems to have re-instated all the dynamic columns I made, but it hasn't put any data into them. If I wrap my column adding code in an
if(!IsPostback)
to prevent them being added again on postback.. then I'll see the columns I originally added, but they're blank. If I don't use an
IsPostback
check, then I'll see a duplicate set of columns in the rendered page: one blank, the other containing values. The controls within the blank columns don't seem to have the same IDs any more, so when my RowDataBound fires,
e.Row.FindControl("key_" + k)
returns null. Of course, if I don't check for postback, and just add the columns again, the newly added set of columns will have controls with correctly named IDs and they'll get populated..

To counter the ever growing set of blank columns, I plan to remove (in page load) any columns I dynamically added, that have been re-instated with the wrong cell-control IDs, and add them again. I can do this by looping backwards through the column collection until I hit a column that is certain to be the last column that is present in the ASPX markup, but the only thing I can see to identify that column by is the header text assigned in the markup (as it doesn't have an ID of its own). Here's the markup, for example:














This feels like an awful way to do things:

for(int i = gv.Columns.Count-1; gv.Columns[i].HeaderText != "Edit Profile"; i--)
gv.Columns.RemoveAt(i); //remove all columns after the 'Edit Profile' one


..not least because there's a bug waiting to happen if the header text changes, or if the key value pairs list ever contains "Edit Profile" as a key..

But how can I better determine which column in a gridview is there because it was added in the markup, versus one that was added dynamically?




Alternatively, is there a better way to re-use the dynamically added columns without deleting them and re-adding them (with corrected IDs)? As noted they're there, but the cells have no data and the Label IDs within the cells are all changed when I get the grid back during a postback, so I can't find them to restore their values..

Answer Source

You can try to use a datatable instead of adding columns in gridview, it used to work very well with me you just need to initialise the datatable and add as much columns and rows as you want, and at the end of the if(!IsPostback) on pageload bind the gridview to the datatable without the need to define the gridview_rowdatabound. For example:

if (!Page.IsPostBack) {

foreach (string s in mydictionary.Keys) {
    dt1.Columns.Add(s);

}

DataRow dr = dt.NewRow();
foreach (column col in dt1.Columns) {
    dr[i].value = mydictionary(col.columnname);
    i = i + 1;
}
    dt1.Rows.Add(dr);
gridview1.datasource = dt1;
gridview1.databind();
}

Note:

I converted from vb.net to C# please notice me in case of error. Let Autogenerate columns in gridview=true

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download