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.
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);
...
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With