I have populated a list box using a Data-table.
In another method, I have to retrieve the data table from the list box.
Datatable dt = (DataTable)lstExample.DataSource;
Throws an error, that the Datatable dt is null
I am working on c# ASP.Net
If you are trying to do this on a Postback then the DataTable will no longer be there. You will need to save it in ViewState or Session if you want access to it on a Postback, or just hit the database again.
For example:
protected override Page_Load(object sender, EventArgs e)
{
if( !IsPostBack)
{
DataTable tbl = GetData();
lstData.DataSource = tbl;
lstData.DataBind();
// store in viewstate
ViewState["data"] = tbl;
}
}
protected void btnSave_Click(object sender, EventArgs e)
{
DataTable tbl = (DataTable)ViewState["data"];
}
Related
How can I display the first selected row values to text boxes after I filter the data in the datagridview?
private void btnsearch_Click(object sender, EventArgs e)
{
dgpay.DataSource = p.SearchInPaymentVouchers("PaymentVouchers.VendorID", comven.SelectedValue.ToString());
}
private void btnsearch_Click(object sender, EventArgs e)
{
DataTable dt = p.SearchInPaymentVouchers("PaymentVouchers.VendorID", comven.SelectedValue.ToString());
dgpay.DataSource = dt;
//Code to bind first row in textbox.
//check if the datatable has rows
if(dt.Rows.Count > 0)
{
textbox.text = Convert.ToInt32(dt.Rows[0]["id"]);
//Row[line index you want to get]["Header of datatable column ex VendorID"]
}
}
Hope this is what you actually want. Please feel free to ask if you face any problem.
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;
}
}
When trying to update GridView data, it successfully runs, but it gets the old data instead of the data you type in the textboxes.
This is what I have:
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
string name = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[1].Controls[0])).Text;
string phone = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[2].Controls[0])).Text;
string email = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[3].Controls[0])).Text;
int contactId = Convert.ToInt32(((TextBox)(GridView1.Rows[e.RowIndex].Cells[4].Controls[0])).Text);
objLogic.UpdateContact(name, phone, email, contactId); //passes values to SQL to update database
GridView1.EditIndex = -1;
GridView1.DataBind();
}
and
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
GridView1.DataBind();
}
and
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DropDownList1.DataSource = objLogic.LoadClient();
DropDownList1.DataTextField = "name";
DropDownList1.DataValueField = "clientId";
DropDownList1.DataBind();
}
GridView1.DataSource = objLogic.LoadContacts(Convert.ToInt16(DropDownList1.SelectedValue));
GridView1.DataBind();
For example, the current data is:
name: Blake, phone: 123-234-3456, email: test#test.com, contactId: 22
I type in new data:
name: John, phone: 555-555-5555, email: test2#test2.com, contactId: 22
Data that ends up in the database:
name: Blake, phone: 123-234-3456, email: test#test.com, contactId: 22
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DropDownList1.DataSource = objLogic.LoadClient();
DropDownList1.DataTextField = "name";
DropDownList1.DataValueField = "clientId";
DropDownList1.DataBind();
BindGrid();
}
}
protected void BindGrid()
{
GridView1.DataSource = objLogic.LoadContacts(Convert.ToInt16(DropDownList1.SelectedValue));
GridView1.DataBind();
}
Every time the page posts back you are rebinding the grid. Move the binding of the grid into a separate function. After you do the row updating, rebind the grid.
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
string name = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[1].Controls[0])).Text;
string phone = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[2].Controls[0])).Text;
string email = ((TextBox)(GridView1.Rows[e.RowIndex].Cells[3].Controls[0])).Text;
int contactId = Convert.ToInt32(((TextBox)(GridView1.Rows[e.RowIndex].Cells[4].Controls[0])).Text);
objLogic.UpdateContact(name, phone, email, contactId); //passes values to SQL to update database
GridView1.EditIndex = -1;
BindGrid();
}
When you edit you must call BindGrid too.
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
//GridView1.DataBind(); this is meaningless, you have not set a DataSource
BindGrid();
}
When you raise the RowUpdating event your basically getting the values BEFORE the GridView updates the row. This is basically so you can cancel the update operation. To get what you've type in I think you need to get the new values (the Dictionary e.NewValues() in your case).
In your case you can use it something like this (assuming name, phone and email are what they're called in your gridview):
foreach(DictionaryEntry de in e.NewValues())
{
string name = de.FirstOrDefault(x => x.Key == "name").Value;
string phone = de.FirstOrDefault(x => x.Key == "phone").Value;
string email = de.FirstOrDefault(x => x.Key == "email").Value;
}
NOTE: If you're simply using this to get the values typed in to update your database then you're better of binding the datagrid and use the value after that to ensure you definitely have the same values in the datagrid as to what you put into the database. Alternatively, use the RowUpdated event instead of the RowUpdating event.
The most prevalent reason is that we usually forgot to check the postbacks in the Page Load event.
check the post-back, then the problem will be removed.
if (! IsPostBack)
{
readData();
...
}
Prokzy I have just your example on my side and doing something like this worked fine for me. notice the DataSource portion. I have a DataSet instantiated as aDataSet btw
protected void GridView1_GridViewPageEventArgs e(object sender, GridViewPageEventArgs e)
{
GridView1.EditIndex = e.NewPageIndex;
GridView1.DataSource = null;
GridView1.DataSource = aDataset;
GridView1.DataBind();
}
You need to call LoadContacts again and reassign GridView1.DataSource after the database is updated. Currently, the DataSource is not being updated - and is just using the collection that was retrieved prior to the row update.
The following code gives me to take one row value from textbox to datagridview ......
private void button1_Click(object sender, EventArgs e)
{
DataTable table = new DataTable();
table.Columns.Add("Course Name", typeof(string));
table.Columns.Add("Credit", typeof(string));
table.Rows.Add(txtName.Text.Trim(), txtCredit.Text.Trim());
addcrsView.DataSource = table;
}
When I give another value to textbox it just replaces the previous one. But I need to take both in datagrid view.
As I am very beginner please put your answer details.
You have to make table as class level object.
DataTable table = new DataTable();
And, set the DataGridView datasource in the Form_Load event
private void Form1_Load(object sender, EventArgs e)
{
table.Columns.Add("Course Name", typeof(string));
table.Columns.Add("Credit", typeof(string));
addcrsView.DataSource = table;
}
Your button1_Click just need to add row
private void button1_Click(object sender, EventArgs e)
{
table.Rows.Add(txtName.Text.Trim(), txtCredit.Text.Trim());
}
When button_click event is fired. I get DataTable from method and assign it to DataTable defined in class, but this DataTable setting in nothing. If I bind DataTable to GridView it show data.
public partial class Default : System.Web.UI.Page
{
TestClass test = new TestClass();
DataTable _table = new DataTable();
protected void Button1_Click(object sender, EventArgs e)
{
_table = test.getTable();
//displaying table
GridView1.DataSource= _table;
GridView1.DataBind();
}
protected void Button2_Click(object sender, EventArgs e)
{
//does not displaying table
GridView2.DataSource= _table;
GridView2.DataBind();
}
}
When I want get some data from _table, it have nothing. What's wrong?
Update:
Thanks all, and especially Darren Davies, problem been in Postback. When Button2_Click event happens _table assign _table = new DataTable(), and therefore _table no more reference to table returned by method getTable().
It will only bind correctly if Button1 is clicked before Button2. Otherwise _table will not be populated.
You should check that _table has data or call the getTable method inside the Button2_Click event handler:
protected void Button2_Click(object sender, EventArgs e)
{
_table = test.getTable();
GridView2.DataSource= _table;
GridView2.DataBind();
}
What you could try is this:
protected void Button1_Click(object sender, EventArgs e)
{
_table = test.getTable();
//displaying table
GridVieuw1.Datasource = null;
GridView1.DataSource= _table;
GridView1.DataBind();
}
Also you must do this at buuton 2
protected void Button2_Click(object sender, EventArgs e)
{
_table = test.getTable();
//displaying table
GridVieuw2.Datasource = null;
GridView2.DataSource= _table;
GridView2.DataBind();
}
Otheriwse the table is empty at button 2, so you have to press button 1 to fill it
Maybe that can do the trick
You are initializing your DataTable like
DataTable _table = new DataTable();
Then, when you click your button 1:
protected void Button1_Click(object sender, EventArgs e)
{
_table = test.getTable(); // <- here
//displaying table
GridView1.DataSource= _table;
GridView1.DataBind();
}
you are assigning your DataTable to a different instance.
You have to debug and check that your method getTable is returning a valid DataTable (and if you want to see your data, make sure that it contains data.
Your problem arises when you do not press button 1 before button 2. You should generalized your data binding like this:
public partial class Default : System.Web.UI.Page
{
TestClass test = new TestClass();
DataTable _table = new DataTable();
protected void Button1_Click(object sender, EventArgs e)
{
FillDataTable (); // <----------- See this function call
//displaying table
GridView1.DataSource= _table;
GridView1.DataBind();
}
protected void Button2_Click(object sender, EventArgs e)
{
FillDataTable (); // <----------- See this function call
//does not displaying table
GridView2.DataSource= _table;
GridView2.DataBind();
}
private void FillDataTable()
{
if(_table.Rows.Count == 0)
_table = test.getTable();
}
}
It would a wise way to fill table once, instead of filling on every button click and write it down in every button click event.