GridView.DataSource is null during PostBack

21.2k views Asked by At

i want to implement a print / download csv from each Gridview in my application. Those get their data by Datasources or directly by

gvSample.DataSource = Data;
gvSample.DataBind();

Now my first approach was setting a Download-Button into the Footer-Template and handle the Download there

<asp:GridView ID="gvSample" runat="server">
 <PagerTemplate>
  <asp:ImageButton  ImageUrl="~/download.gif"  OnClick="dl_Click" runat="server" ID="dl"/>
 </PagerTemplate>
</asp:GridView>

and

protected void dl_Click(object sender, ImageClickEventArgs e)
{
    GridView gv = (GridView)this.Parent.Parent.Parent.Parent;
    string csv = ToCSV(gv.DataSource); //gv.DataSource is null, DatasourceID aswell
    Response.ContentType = "application/csv";
    Response.AddHeader("content-disposition", "attachment; filename=file.csv");
    Response.Write(csv);
    Response.End();           
}

but i cant access the data.

3

There are 3 answers

1
giammin On BEST ANSWER

DataSource in GridView is not stored in any persistent way across Postback so you have to save it somewhere (Viewstate or Session) or you have to request it again from your data-store (Es your db).

A quick explanation of the 3 methods:

VievState: is saved in an hidden field in the page so it is not recommended for large data-set because your page could become many MB. It's advantage is that it is saved in the page so it does not expire

ViewState["Data"] = GetData();
gvSample.DataSource = ViewState["Data"];
gvSample.DataBind();

...

protected void dl_Click(object sender, ImageClickEventArgs e)
{
    string csv = ToCSV(ViewState["Data"]);
    ...   
}

Session: is saved in the serve memory so you 'quite' don't have size problems but session does not last forever (usually 30minutes) and if a user display that page and click download after an hour than the session will be null

Session["Data"] = GetData();
gvSample.DataSource = Session["Data"];
gvSample.DataBind();

...

protected void dl_Click(object sender, ImageClickEventArgs e)
{
    string csv = ToCSV(Session["Data"]);
    ...   
}

Request from data-store you request the data from the db so another round trip is done and data could be different respect what the user are seeing

gvSample.DataSource = GetData();
gvSample.DataBind();

...

protected void dl_Click(object sender, ImageClickEventArgs e)
{
    string csv = ToCSV(GetData());
    ...   
}

Just a suggestion:

you can access simpler the grid using directly gvSample in this way it will be not broken if you cange your html...:

protected void dl_Click(object sender, ImageClickEventArgs e)
{
    //GridView gv = (GridView)this.Parent.Parent.Parent.Parent;
    //string csv = ToCSV(gv.DataSource); //gv.DataSource is null, DatasourceID aswell
    string csv = ToCSV(gvSample.DataSource);
    ...   
}
0
Dgan On

You Can't Access it gv.DataSource as You Coded

Try to Use Session or ViewStates and Save DataTable

gvSample.DataSource = Data;
gvSample.DataBind();
Session["MyTable"]=Data;

Convert Session into DataTable and pass to Method

protected void dl_Click(object sender, ImageClickEventArgs e)
{
    if(Session["MyTable"]==null)
{

    string csv = ToCSV(DataTable(Session["MyTable"]) );  
    Response.ContentType = "application/csv";
    Response.AddHeader("content-disposition", "attachment; filename=file.csv");
    Response.Write(csv);
    Response.End();    

}       
}
0
cpacheco On

You could save your data in ViewState (NOT RECCOMENDED FOR LARGE DATASETS!!!), roughly

gvSample.DataSource = Data;
ViewState["Data"] = Data;
gvSample.DataBind();

protected void dl_Click(object sender, ImageClickEventArgs e)
{
    var ds = (ProperDataType)ViewState["Data"]; // TODO: check for nulls
    string csv = ToCSV(ds); //gv.DataSource is null, DatasourceID aswell
    Response.ContentType = "application/csv";
    Response.AddHeader("content-disposition", "attachment; filename=file.csv");
    Response.Write(csv);
    Response.End();           
}

Also, you could rebuild your data based on the gridview, something like

var ds = new ProperDataSource();
foreach(GridViewRow row in gvSample.Rows)
{
    dRow data = new dRow();
    foreach(TableCell cell in row.Cells)
    {
        ds.Add("column1", cell.Text);
    }
    ds.Add(dRow);
}
string csv = ToCSV(ds); //gv.DataSource is null, DatasourceID aswell
        Response.ContentType = "application/csv";
        Response.AddHeader("content-disposition", "attachment; filename=file.csv");
        Response.Write(csv);
        Response.End();  

of course you have to fit this snippet to your specific data structure... but that's the general idea.

GridViews don't save it's original datasource, you have to either save it elsewhere or rebuild it on demand