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;
}
Related
I have little problem , I shared images and code below.
I have two datagridview in my code block. First(left side in form) datagridview's name searchDataGridView. This grid shows data from my database by some filters. Second(right side in form) datagridview's name dataGridView1. This grid shows when I click next button if I select some rows from first grid then this rows will add to dataGridView1. This code block working very well but this that my problem when I click next button and selected rows and added to dataGridView1 then searchDataGridVÄ°ew will show new items and selected rows will add to datagridView1, but when I add new items to dataGridView older rows will clear and new selected rows will add but I need that news selected rows must add to under older rows. Thank you for helping.
private void buttonNext_Click(object sender, EventArgs e)
{
Search searchObj = new Search();
DataTable dt = new DataTable();
dt.Columns.Add("Item");
dt.Columns.Add("Company");
dt.Columns.Add("Category");
dt.Columns.Add("Price");
foreach (DataGridViewRow drv in searchDataGridView.Rows)
{
bool chkboxselect = Convert.ToBoolean(drv.Cells["CheckBox"].Value);
if (chkboxselect)
{
dt.Rows.Add(drv.Cells[2].Value, drv.Cells[3].Value, drv.Cells[4].Value, drv.Cells[8].Value);
drv.DefaultCellStyle.BackColor = Color.Gray;
drv.DefaultCellStyle.ForeColor = Color.Aqua;
}
dataGridView1.DataSource = dt;
}
counter +=1;
if (counter == maxIndex)
{
counter =0;
}
try
{
searchCategoryComboBox.SelectedIndex = counter;
}
catch (System.ArgumentOutOfRangeException) // CS0168
{
MessageBox.Show("hata yakalandı");
return;
}
//catch for error outofrange
searchCategoryComboBox.SelectedIndex =counter;
searchObj.Company = searchCompanyComboBox.Text;
searchObj.Category = searchCategoryComboBox.Text;
SearchManager searchMangObj = new SearchManager();
DataTable dt2 = searchMangObj.SearchInfo(searchObj);
searchDataGridView.DataSource = dt2;
textBox1.Text = String.Empty;
}
The problem is the way you get data from the db:
DataTable dt2 = searchMangObj.SearchInfo(searchObj);
searchDataGridView.DataSource = dt2;
Your SearchInfo method returns a new datatable and you bind that so the rows from the previous table are lost. Modify this method so it takes a datatable as a parameter (ie the existing datatable) and add rows to it.
You didn't say how your SearchInfo works to get rows from the db, but I suspect it will use a dataadapter or tableadapter, in which case you should set its ClearBeforeFill property to false to stop it from clearing the search datatable (the table that is databind'd to the searchdatagridview.DataSource)
You would then use it like:
searchMangObj.SearchInfo(searchDataGridView.DataSource as DataTable);
And it would be coded like:
void SearchInfo(DataTable dt){
var dataadapter = blah blah blah;
dataadapater.ClearBeforeFill = false;
dataadapter.Fill(dt);
}
I have a page that allows both sorting columns as well as a search option that filters the GridView data. The problem I am running into is the GridView's ViewState SortExpression gets lost when filtering the datatable through the Search option.
My question is how do I retain the ViewState after a DataBind to ensure the SortExpression is kept on the newly binded dataTable?
protected void Page_Load(object sender, EventArgs e)
{
try{
if (IsPostBack)
{
Control control = null;
string controlName = Request.Params["__EVENTTARGET"];
if (!String.IsNullOrEmpty(controlName))
{
control = FindControl(controlName);
GridViewRow gvRow1 = (GridViewRow)control.Parent.Parent;
string controlID = control.ID.ToString();
}
}
if(!IsPostBack)
{
DataGrid_Load(DAL.reg(HeadText.Text, OrgText.Text), "reg");
}
}
catch{}
}
private void DataGrid_Load(DataTable command, string type)
{
DataTable dataTable = new DataTable();
dataTable = command;
string sortDir = ViewState["SortDirection"] as string;
string sortExp = ViewState["SortExpression"] as string;
if(ViewState["SortExpression"] != null)
{
dataTable = resort(dataTable, sortExp, sortDir);
}
string myStatus = HeadText.Text;
DataRow[] dr = dataTable.Select("status = '" + myStatus + "'");
DataTable filteredDataTable = dataTable.Clone();
foreach (DataRow sourceRow in dr)
{
filteredDataTable.ImportRow(sourceRow);
}
GridView1.DataSource = filteredDataTable;
GridView1.DataBind();
}
public class dal
{
public DataTable reg(string head, string org = null)
{
if (head == "all")
return Data_Load(String.Format("SELECT * from reg"), "reg");
}
}
I resolved this and it was simply a problem with my Load Data procedure which did not take into account if there was something already filtered in the GridView and the filter was being lost on the new Load.
To fix this I made a static searchFilter variable and added a check for this in each of the methods that called for loading data into the GridView:
after column sorting
after the "Rows Per Page" is changed
Any other functions within that page that require Loading Data on that page.
The code looked this this in each of the functions that load data:
if(searchFilter != "")
loadDataWithFilter();
else
loadDataWithoutFilter();
I did not have to do anything with the Page_Load PostBack.
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;
}
}
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.
How can I export GridView.DataSource to datatable or dataset?
Assuming your DataSource is of type DataTable, you can just do this:
myGridView.DataSource as DataTable
You should convert first DataSource in BindingSource, look example
BindingSource bs = (BindingSource)dgrid.DataSource; // Se convierte el DataSource
DataTable tCxC = (DataTable) bs.DataSource;
With the data of tCxC you can do anything.
Personally I would go with:
DataTable tbl = Gridview1.DataSource as DataTable;
This would allow you to test for null as this results in either DataTable object or null. Casting it as a DataTable using (DataTable)Gridview1.DataSource would cause a crashing error in case the DataSource is actually a DataSet or even some kind of collection.
Supporting Documentation: MSDN Documentation on "as"
Ambu,
I was having the same issue as you, and this is the code I used to figure it out. Although, I don't use the footer row section for my purposes, I did include it in this code.
DataTable dt = new DataTable();
// add the columns to the datatable
if (GridView1.HeaderRow != null)
{
for (int i = 0; i < GridView1.HeaderRow.Cells.Count; i++)
{
dt.Columns.Add(GridView1.HeaderRow.Cells[i].Text);
}
}
// add each of the data rows to the table
foreach (GridViewRow row in GridView1.Rows)
{
DataRow dr;
dr = dt.NewRow();
for (int i = 0; i < row.Cells.Count; i++)
{
dr[i] = row.Cells[i].Text.Replace(" ","");
}
dt.Rows.Add(dr);
}
// add the footer row to the table
if (GridView1.FooterRow != null)
{
DataRow dr;
dr = dt.NewRow();
for (int i = 0; i < GridView1.FooterRow.Cells.Count; i++)
{
dr[i] = GridView1.FooterRow.Cells[i].Text.Replace(" ","");
}
dt.Rows.Add(dr);
}
If you do gridview.bind() at:
if(!IsPostBack)
{
//your gridview bind code here...
}
Then you can use DataTable dt = Gridview1.DataSource as DataTable; in function to retrieve datatable.
But I bind the datatable to gridview when i click button, and recording to Microsoft document:
HTTP is a stateless protocol. This means that a Web server treats each
HTTP request for a page as an independent request. The server retains
no knowledge of variable values that were used during previous
requests.
If you have same condition, then i will recommend you to use Session to persist the value.
Session["oldData"]=Gridview1.DataSource;
After that you can recall the value when the page postback again.
DataTable dt=(DataTable)Session["oldData"];
References:
https://msdn.microsoft.com/en-us/library/ms178581(v=vs.110).aspx#Anchor_0
https://www.c-sharpcorner.com/UploadFile/225740/introduction-of-session-in-Asp-Net/
I have used below line of code and it works, Try this
DataTable dt = dataSource.Tables[0];
This comes in late but was quite helpful. I am Just posting for future reference
DataTable dt = new DataTable();
Data.DataView dv = default(Data.DataView);
dv = (Data.DataView)ds.Select(DataSourceSelectArguments.Empty);
dt = dv.ToTable();