I'm using GridView in ASP.NET, after editing the columns and pressing a button I want to get the whole GridView back to a DataTable or a List, how can I do it?
<asp:GridView ID="FireFighters" runat="server" AutoGenerateColumns="false"
OnRowDataBound="FireFighters_RowDataBound">
After rendering the page the DataSource is null.
You can't get a data source back out of a web control once it's been bound and rendered. Unlike applications that you may be accustomed to programming the web is stateless and it will not persist data unless you implement that by using Session or ViewState.
In a typical example you would have an underlying data set that you are binding to the GridView, at the same time you can store it in ViewState. Any changes to the grid by the user need to trigger something to make changes to the underlying data set and then you rebind the control to that data set. There are other ways of doing this, but the point is that you have to track the changes.
Here's a rudimentary example of the above using ViewState:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
InitialDataLoad();
}
private void InitialDataLoad()
{
var dt = new DataTable();
dt.Columns.Add("SomeData");
var dr = dt.NewRow();
dr[0] = "some initial data here";
dt.Rows.Add(dr);
GridView1.DataSource = dt;
GridView1.DataBind();
ViewState["dt"] = dt;
}
protected void Button1_Click(object sender, EventArgs e)
{
// adds a row
var dt = ViewState["dt"] as DataTable;
if (dt != null)
{
var dr = dt.NewRow();
dr[0] = "some more data here";
dt.Rows.Add(dr);
GridView1.DataSource = dt;
GridView1.DataBind();
ViewState["dt"] = dt;
}
}
Related
I want to bind gridview column from textbox value for example: I have two textbox and a button what i exactly want that i will give input in the two textboxes and when i clicked the button the textbox values will show in gridviw and want to do this for multiple times without replacing the previous values.
I found so many relevant answer but all are done with hard code inside button click event
protected void Button1_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[2] { new DataColumn("Name",
typeof(string)),
new DataColumn("Age", typeof(decimal)) });
dt.Rows.Add(TextBox1.Text, TextBox2.Text);
GridView1.DataSource = dt;
GridView1.DataBind()
}
which replace the previous values when i insert new values, but i want to keep all the previous values in which I stuck .thanks
this code will help you to get current data from gridview to datatable
and then you can append new rows accordingly .
protected void Button1_Click(object sender, EventArgs e)
{
DataTable dt =GetGridData();
dr = dt.NewRow();
dt.Rows.Add(TextBox1.Text, TextBox2.Text);
GridView1.DataSource = dt;
GridView1.DataBind();
}
private DataTable GetGridData ()
{
DataTable _datatable = new DataTable();
for (int i = 0; i < grdReport.Columns.Count; i++)
{
_datatable.Columns.Add(grdReport.Columns[i].ToString());
}
foreach (GridViewRow row in grdReport.Rows)
{
DataRow dr = _datatable.NewRow();
for (int j = 0; j < grdReport.Columns.Count; j++)
{
if (!row.Cells[j].Text.Equals(" "))
dr[grdReport.Columns[j].ToString()] = row.Cells[j].Text;
}
_datatable.Rows.Add(dr);
}
return _dataTable;
}
You can store the values from each PostBack into a Session or ViewState, otherwise you'll lose all the data when the button is clicked again.
protected void Button1_Click(object sender, EventArgs e)
{
DataTable dt;
//check if the datatable already exists in the viewstate, if not create a new datatable
if (ViewState["myTable"] == null)
{
dt = new DataTable();
dt.Columns.AddRange(new DataColumn[2] { new DataColumn("Name", typeof(string)), new DataColumn("Age", typeof(decimal)) });
}
else
{
//correct viewstate exists, cast back to a datatable
dt = ViewState["myTable"] as DataTable;
}
//add the new values
dt.Rows.Add(TextBox1.Text, Convert.ToDecimal(TextBox2.Text));
//bind the datatable to the gridview
GridView1.DataSource = dt;
GridView1.DataBind();
//save the datatable into the viewstate
ViewState["myTable"] = dt;
//clear the textboxes
TextBox1.Text = "";
TextBox2.Text = "";
}
I have a two control, which are a Search button and Export button. The user will 'Search' the data and the data will be inserted into DataTable and bound to the GridView or Repeater, and then when user click Export, the DataTable will be passed into the class that will generate an Excel file using the data inside DataTable.
In my current code, the Search button and Export button both will query to fetch data from database. But what I need is only Search button that will query, and store the data into a DataTable or something, and when Export button is clicked it will use the earlier data to generate the Excel file.
Here is my current code:
Report.aspx
<asp:GridView ID="GridView1" runat="server">
<Columns>
</Columns>
</asp:GridView>
</body>
Report.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
/* Page load */
}
protected void btn_search_Click(object sender, EventArgs e)
{
DataTable dt = GetData();
GridView1.DataSource = dt;
GridView1.DataBind();
}
protected DataTable GetData()
{
DataTable dataTable = new DataTable();
/* Query operation */
adapter.Fill(dataTable);
return dataTable;
}
protected void btn_export_Click(object sender, EventArgs e)
{
var excelClass = new ExcelClass();
excelClass.ExcelData = GetData();
}
I attempt to create a DataTable as a property in 'Report.aspx.cs' and fill it with the data when Search is clicked. But when I Export , the DataTable is empty again.
DataTable dataTable = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
/* Page load */
}
protected void btn_search_Click(object sender, EventArgs e)
{
GetData();
GridView1.DataSource = dataTable ;
GridView1.DataBind();
}
protected void GetData()
{
/* Query operation */
adapter.Fill(dataTable);
}
protected void btn_export_Click(object sender, EventArgs e)
{
var excelClass = new ExcelClass();
excelClass.ExcelData = dataTable;
}
But, I need to fetch the data just once, when Search is clicked, and use the data again when I Export it, so it wont query to the database twice.
There are three ways you can achieve this as mentioned below.
Using Session
You can use session for this but this will affect the performance of the application/page if, for example, the dataTable contains 10,000 records.
Add a dataTable into session:
DataTable dataTable= new DataTable();
dataTable= GetData();
Session.Add("dataTable", dataTable);
Retrive that datatable from session:
DataTable dataTable = Session["dataTable"] as DataTable
or
DataTable dataTable= (DataTable)Session["dataTable"];
Export a GridView1.DataSource to a dataTable
DataTable dataTable= Gridview1.DataSource as DataTable;
Iterate each Row from GridView to DataTable
//Create a new DataTable.
DataTable dataTable = new DataTable();
//Add columns to DataTable.
foreach (TableCell cell in GridView1.HeaderRow.Cells)
{
dataTable.Columns.Add(cell.Text);
}
//Loop through the GridView and copy rows.
foreach (GridViewRow row in GridView1.Rows)
{
dataTable.Rows.Add();
for (int i = 0; i < row.Cells.Count; i++)
{
dataTable.Rows[row.RowIndex][i] = row.Cells[i].Text;
}
}
I have a GridView and want to make headers dynamically based on the some SQL query like...
select question from quiz where quizid is 123.
This query will return * number of questions based on the quizid.
How to create headers with the data that's been selected from database?
You can use DataTable to help with this.
I don't know which technologies you used for database management, but I used LinQ to SQL. And the following is my sample:
DataClassesDataContext db = new DataClassesDataContext();
protected DataTable GetDataSource()
{
DataTable dt = new DataTable();
var questions = db.ExecuteQuery<string>("select question from quiz where quizid is 123").ToList();
// Header implementation
int count = 0;
foreach (var question in questions)
{
DataColumn dc = new DataColumn(question);
dt.Columns.Add(dc);
count++;
}
// Rows implementation here
DataRow row = dt.NewRow();
...
dt.Rows.Add(row);
return dt;
}
protected void Page_Load(object sender, EventArgs e)
{
GridView1.DataSource = GetDataSource();
GridView1.DataBind();
}
And here is my aspx code:
<asp:GridView ID="GridView1" runat="server"></asp:GridView>
I will suggest you to Add HeaderText Dynamically on RowDataBound event.
You could try something like
protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
GridView.Columns[0].HeaderText = "New Header text for First Column";
}
}
You could find RowDataBound on properties >> Events of GridView control. and RowDataBound fires on binding of every row of GridView.
I have cached a select * query in a dataset in c#.
On my page I have 3 dropdownlists.
Depending on the dropdownlist selected I filter the datatable and bind it to the gridview.
whenever the data in the dropdownlist gets changed,I display the data accordingly.
My problem is, I have added pagination to this gridview since I have more than 500 results for each query.
When I try to paginate,the gridview disappears.The value in the dropdownlist does not change.
what should I do?
the code for page Index changing of gridview is:
protected void gridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
GridView1.DataBind();
}
thank you for you help in advance.
You need to bind your grid again in the function
protected void gridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
//provide data source here
GridView1.DataBind();
}
Following are the steps that may help you out...
Add dynamic gridview control to page or in any other control where u want to show it on page.
Set its pager settings along with PageIndexChanging Event Handler
Call it in OnInit Event instead of Page_Load
Following is sample code:
private void AddGridDynamically()
{
try
{
HtmlTableRow tr = new HtmlTableRow();
HtmlTableCell td = new HtmlTableCell();
GridView gv = new GridView();
gv.AllowPaging = true;
gv.PageSize = 20;
gv.PagerSettings.Visible = true;
gv.PagerSettings.Mode = PagerButtons.NumericFirstLast;
gv.PageIndexChanging += new GridViewPageEventHandler(gv_PageIndexChanging);
FillGrid(gv);
td.Controls.Add(gv);
tr.Cells.Add(td);
tbl1.Rows.Add(tr);
gv.EmptyDataText="No Data Found";
gv.DataBind();
}
catch (Exception ex)
{
throw ex;
}
}
private void FillGrid(GridView gv)
{
try
{
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Id");
DataRow dr;
for (int i = 0; i < 100; i++)
{
dr = dt.NewRow();
dr[0] = "AnyThing" + i;
dr[1] = i;
dt.Rows.Add(dr);
}
gv.DataSource = dt;
}
catch (Exception ex)
{
}
}
protected override void OnInit(EventArgs e)
{
AddGridDynamically();
}
I set GridView's source to be result from stored procedure, which is basically datatable.
ASPxGridView1.DataSource = dt1;
ASPxGridView1.DataBind();
This is happening on button click. On first step it is OK, but when I try to sort, filter or go to next page of results, gridview is empty, and I must click button (to call DataBind obviously) to see results.
So, my question is, how to somehow cache datatable from stored procedure, so I don't need to bind data on every sort or page change.
Thanks.
Generally, when you updating the ASPxGridView or WebChartControl data at runtime, this information isn't cached automatically.
So, you must provide it to the control at every request to the server, using the Page_Init event handler.
To improve performance, you can save data into a Session/Cache
variable.
For reference check following DevExpress KB regarding your question and KB:
rebinding gridview at each postback
Bind a grid to a DataTable via code.
Why might paging (sorting, grouping, filtering) not work in the ASPxGridView?
//Cache DataTable in Session to avoid multiple database hit on every postback
DataTable GetTable() {
//You can store a DataTable in the session state
DataTable table = Session["Table"] as DataTable;
if (table == null) {
table = new DataTable();
table.Columns.Add("id", typeof(int));
table.Columns.Add("data", typeof(String));
for (int n = 0; n < 100; n++) {
table.Rows.Add(n, "row" + n.ToString());
}
Session["Table"] = table;
}
//Otherwise you have to create a DataTable instance on every request:
//DataTable table = new DataTable();
//table.Columns.Add("id", typeof(int));
//table.Columns.Add("data", typeof(String));
//for(int n = 0; n < 100; n++) {
// table.Rows.Add(n, "row" + n.ToString());
//}
return table;
}
Reference links to improve the performance of DevExpress GridView controls:
Default grid data binding behavior is unworkable for large data sets
ASPxGridView.DataSourceForceStandardPaging Property
ASPxGridView - How to implement caching using the SqlCacheDependency or SqlDependency classes
Best Solution for ASPxGridView with Custom DataTable objects
Data caching on the client side
How To Cache Rows In DevExpress ASP.NET GridView
Performance issue in GridView when using paging & master detail view
Speed up your page loads with a lighter ViewState
Data Loading times and custom record loading
You can use AfterPerformCallback:
protected void gridSchedule_AfterPerformCallback(object sender,
DevExpress.Web.ASPxGridView.ASPxGridViewAfterPerformCallbackEventArgs e)
{
LoadGrid(gridSchedule);
}
Use ViewState
Step 1:
GridView1.DataSource = ds;
ViewState["itemsetPending"] = ds;
GridView1.DataBind();
Step 2:
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
DataSet m_DataTable = (DataSet)ViewState["itemsetPending"];
if (m_DataTable != null)
{
DataView m_dataview = new DataView(m_DataTable.Tables[0]);
if (Convert.ToInt32(ViewState["m_sort"]) == 0)
{
m_dataview.Sort = e.SortExpression + " " + ConvertSortDirectionToSql(SortDirection.Descending);
ViewState["m_sort"] = 1;
}
else
{
m_dataview.Sort = e.SortExpression + " " + ConvertSortDirectionToSql(e.SortDirection);
ViewState["m_sort"] = 0;
}
GridView1.DataSource = m_dataview;
GridView1.DataBind();
}
}
Here I m Fill the data from Store Procedure into Dataset and assigning into ViewState.Just try it.
private string ConvertSortDirectionToSql(SortDirection sortDirection)
{
string newSortDirection = String.Empty;
switch (sortDirection)
{
case SortDirection.Ascending:
newSortDirection = "ASC";
break;
case SortDirection.Descending:
newSortDirection = "DESC";
break;
}
return newSortDirection;
}