In my simple starter asp page I create a DataTable and populate it with two rows. The web site allows users to add new rows. My problem is the DataTable doesn't save the information. I've stepped through the code and the row gets added but the next time a row is added it's not there, only the original two and the newest one to get entered.
I have gotten around this, in an inelegant way, but am really curious why the new rows are being saved.
My code:
protected void Page_Load(object sender, EventArgs e)
{
_Default.NameList = new DataTable();
DataColumn col = new DataColumn("FirstName", typeof(string));
_Default.NameList.Columns.Add(col);
col = new DataColumn("LastName", typeof(string));
_Default.NameList.Columns.Add(col);
DataRow row = _Default.NameList.NewRow();
row["FirstName"] = "Jane";
row["LastName"] = "Smith";
_Default.NameList.Rows.Add(row);
row = _Default.NameList.NewRow();
row["FirstName"] = "John";
row["LastName"] = "Doe";
_Default.NameList.Rows.Add(row);
}
protected void AddButton_Click(object sender, EventArgs e)
{
DataRow row = _Default.NameList.NewRow();
row["FirstName"] = this.TextBox1.Text;
row["LastName"] = this.TextBox2.Text;
_Default.NameList.Rows.Add(row);
_Default.NameList.AcceptChanges(); // I've tried with and without this.
}
I've tried saving them to GridView control but that seems like quite a bit of work.
I'm new to ASP.Net but have done windows programming in C# for the last two years.
You're creating a new DataTable object each time the page loads.
You need to persist the DataTable object to session state or a static variable, or save the data to a database.
Remember that handling events like your button click requires a full postback. You don't run just the click code, you run your entire page lifecycle on a new instance of your page class. The new instance of your page class means a new instance of the datatable as well.
The issue here is that your DataTable is being created every time your page loads and it goes out of scope when your page has finished loading and been displayed to the user. To get your desired effect, you will need to store the DataTable in either Session, ViewState, cache, use a control like GridView that will automatically store the underlying data in its state, or something else.
Since you're new to ASP.NET, check out your options for state management.
Related
I have a web forms project that has one filter. When the user filters the data and clicks on the next page, the filter seems to get taken off and the default data is displayed. How can I fix this? Is it the OnPageIndexChanging attribute method that needs updating? I've shown the code behind below for the ONPageIndexChanging method and the method used to bind the data (had to cut some out to get rid of the "too much code" error but if I'm missing anything that would be helpful, please let me know.)
protected void dashboard_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
dashboard.PageIndex = e.NewPageIndex;
BindDataToGridView();
}
void BindDataToGridView(SqlCommand cmdSQL = null)
{
// default sql
if (cmdSQL is null)
{
cmdSQL = new
SqlCommand("SELECT TabID, TabName, Title, CreatedOnDate, TabPath From [tableName].[dbo].[Tabs] Order By TabName");
}
var connectionFromConfig = WebConfigurationManager.ConnectionStrings["connstring"].ConnectionString;
using (cmdSQL)
{
cmdSQL.Connection = new SqlConnection(connectionFromConfig);
cmdSQL.Connection.Open();
DataTable rst = new DataTable();
rst.Load(cmdSQL.ExecuteReader());
dashboard.DataSource = rst;
dashboard.DataBind();
}
}
}
In place of your BindDataToGridView() for the paging event?
Call the SAME routine you have for the button click to filter the dates.
(you could even pull out the code for the button click into a separate routine. That routine filters by date, so have both your button click to filter, and the page index change event call that same routine.
So, for paging, you have to call the routine with the filter. This kind of suggests that you want one routine to load the grid, and it has to figure out if you have a filter or not. So, you might check for start/end date being blank. this would allow both page load event, the filter button, and the data page change event ALL to call ONE common routine.
So, a few things:
If you going to bind a grid/list view? and page? And filter?
(3 issues)?
Then make ONE common routine for all to call.
Say like this:
void BindDataToGridView()
{
SqlCommand cmdSQL = new SqlCommand("");
cmdSQL.CommandText = "SELECT TabID, TabName, Title, CreatedOnDate, TabPath From TableName Order By TabName";
if (startDate.Text != "")
{
// filter
cmdSQL.CommandText =
"SELECT TabID, TabName, Title, CreatedOnDate, TabPath From TableName " +
"WERE CreatedOnDate >= #Start AND <= #End ORDER By TabName";
cmdSQL.Parameters.Add("#Start", SqlDbType.Date).Value = startDate.Text;
cmdSQL.Parameters.Add("#End", SqlDbType.Date).Value = endDate.Text;
}
using (cmdSQL)
{
cmdSQL.Connection = new SqlConnection(conString);
cmdSQL.Connection.Open();
DataTable rst = new DataTable();
rst.Load(cmdSQL.ExecuteReader());
dashboard.DataSource = rst;
dashboard.DataBind();
}
}
So now we are NOT passing the filter. You could I suppose also put the sql or the status of the filter into view state, and have the filter routine check this, but you better off to do the above.
In fact, I often suggest that we filter the reocrdset against its built in "view", as that can save database hits, but it don't matter.
So, when introducing filters? AND paging? You have to keep the above in mind.
So, now we have one routine for page load, the button click and the pager changing index code.
We've got an ASP.Net application that contains a GridView Control that contains row edit functionality.
This allows a user to Edit, Delete, Or Cancel editing on a particular row.
For Example Read Only Mode Looks Like This:
And Edit Mode Looks Like this:
The mechanism that allows the user to enter Edit mode is based on an Edit Button in a template column that changes the selected row from a read only row to an editable row using a RowEditing event something like this:
protected void grdOfMine_RowEditing(object sender, GridViewEditEventArgs e)
{
grdOfMine.EditIndex = e.NewEditIndex;
ReBindDataGrid();
}
Canceling is pretty much the opposite where we have a button click event that changes the row back to ready only mode:
protected void grdOfMine_RowEditing(object sender, GridViewEditEventArgs e)
{
grdOfMine.EditIndex = -1;
ReBindDataGrid();
}
(Apologies to those who are already familiar with this aspect of ASP.Net forms development.)
We've also created a footer row that allows a user to add a new row:
We're looking for a way to extend the ASP.Net GridView control do this without using the buttons to fire the events.
For example:
Allow a user to enter edit mode for a row, by clicking in a cell of any given row and update the selected record say, on an Enter keyboard input event (Instead of the Edit Button).
Delete a record say, on a delete keyboard input event (Instead of the Delete Button).
Add a record in a similar fashion (Instead of the Add Button).
We were attempting this functionality using Infragistics controls, however we had a very tough time getting these to work, so we decided not to use them.
Thanks in advance
I am working on asp.net gridview on webforms and using Gridview RowCommand method of GridView OnRowCommand event for the Buttons View, Edit & Update inside TemplateField.
if (e.CommandName == "EditContract") {
GridViewRow row = (GridViewRow)(((Button)e.CommandSource).NamingContainer);
int SerialNo = (int)gvContract.DataKeys[row.RowIndex].Value;
int rowIndex = ((GridViewRow)((Button)e.CommandSource).NamingContainer).RowIndex;
gvContract.SelectRow(rowIndex);
using (SqlCommand cmd = new SqlCommand("spContractEdit", myObj.DbConnect()))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#RoleName", SqlDbType.Char).Value = Session["RoleName"];
cmd.Parameters.Add("#UnitName", SqlDbType.Char).Value = Session["UnitName"];
cmd.Parameters.Add("#ContrSerialNo", SqlDbType.Int).Value = SerialNo;
dAdapter = new SqlDataAdapter(cmd);
DataTable DtContract = new DataTable();
dAdapter.Fill(DtContract);
}
if (e.CommandName == "UpdateContract") {
lblMessage.Text = "";
lblFile.Text = "";
GridViewRow row = (GridViewRow)(((Button)e.CommandSource).NamingContainer);
int SerialNo = (int)gvContract.DataKeys[row.RowIndex].Value;
using (SqlCommand cmd = new SqlCommand("spContractUpdate", myObj.DbConnect()))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ContrNewRev", SqlDbType.VarChar).Value = ddNewOrRevised.SelectedValue;
cmd.Parameters.Add("#ContractTitle", SqlDbType.VarChar).Value = txtContractTitle.Text;
cmd.Parameters.Add("#FinancerID", SqlDbType.Int).Value = ddFinancer.SelectedValue;
}
This code is working fine when the page loads first time but has 2 problems after that. i.e. 1. It is editing and updating data when the page gets load for the first time but when I try to edit the same row or any other then it doesn't. I know it is because I have defined the !Page.IsPostback method on the Page_Load event but I do not know how to tackle this situation. 2. Problem is How to restrict the gridview row to update only that data whose row is selected?
Please suggest me a solution.
GridView Sample
freshly boarded the asp.net boat.
I have an asp.net page that initially displays some data in a gridview with pagination(with a dataset as its datasource). And, there are few textboxes to perform insertions or updations ( don't ask about the edit/insert options in the gridview itself!!).
I need few guidances regarding the right place to store datasets.
Im posting the simplified codebehind file, that uses viewstate to store the dataset, which I dont like.
enter code here
class xyx : Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridBind();
}
}
protected void InsertUpdateButton_Click(object sender, EventArgs e)
{
1.perform insert or update data in the database
2.GridBind();
}
protected void GridView1_PageIndexChanged(object sender, EventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
GridView1.SelectedIndex = -1;
GridView1.DataSource = (DataSet)ViewState["DataSet"];
GridView1.DataBind();
}
private void GridBind()
{
DataSet ds = getDataFromDataBase();
GridwView1.DataSource = ds;
GridView1.DataBind();
ViewState["DataSet"] = ds;
}
}
Now apart from viewstate, what is the best choice to store the datasets??...
get the data from database everytime
Use a common Session variable Session["DataSet"] for all the datasets across all the pages(I have a few other pages with the same scenario )
Use Cache
I included session or cache because it is likely that the user might just be viewing the data rather than inserting or updating.
Also, In the Button click event instead of calling GridBind(), is it OK if I just updated the dataset in the viewstate rather than fetching data again from the database?
like -
DataSet ds = ViewSate["DataSet"] (or) Session["DataSet"] (or) Cache["DataSet"];
(perform updations or insertions upon the dataset)
Session(or)Cache(or)ViewState["DataSet"] = ds;
Generally:
If the data must be up to date, fetch it every time
If stale data is OK (or doesn't change often):
If the data is different per user, store in Session
If the data is the same for all users, use Cache or Application
If you wish to store large amounts of data per user do not use Session - you could run out of memory.
Depends upon many condition you should take care of these things first
Number of records in dataset.
Number of users.
If there are thousand of record then fetch only those record required. User some pager control.
here is an expample
For better use of paging.
In my ASP.NET page, I'm using a GridView to view data (Items & their prices). Currently users can edit the data (prices) in the grid row by row. (Click --> "Edit" link, change the values then "Update"). This is ROW by ROW. Is it possible to open all rows in Edit mode & use a single button (eg. Submit) to update all data once?
If you don't need to read only mode, in that case you can put input boxes ( textbox, dropdownlist, etc.) in ItemTEmplate section and bind them with existing data.
Next, put a submit button at above/below of the GridView and handle button Click event and loop through the GridView item data and save all database.
I'll post code block if you need. Thanks for your time.
And you will have better control on that you doing by using listview instead of gridview.
My best practise is using listview and custom web user control for this kind of problems.
If you fill your listview with your user control, you will easy to manage your saving method, just have to iterate on the listview items, find control and call your Save() method for each item.
I know that this question has already been answered but here is the code for loop through the GridView getting data and store it in the Data Base:
Using libraries:
using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;
using System.Data.Odbc;
Code Behind:
// this is a variable that have the Query or SQL Commands.
string DataBaseQuery = "UPDATE [table] SET [variable2] = #variable2, [variable3] = #variable3) WHERE [variable1] = #variable1";
//Click Event from a LinkButton.
protected void LinkButton1_Click(object sender, EventArgs e)
{
//"ConnectionString" its the string connection for your DataBase (often get from the WebConfig File or a DataSource element.
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
//this is for open the database using the string connection.
connection.Open();
//this is the algorithm for going through the entire GridView.
for (int i = 0; i < GridView1.Rows.Count; i++)
{
//"DataBaseQuery" it's a string variable that have the Query or SQL Commands.
SqlCommand cmd = new SqlCommand(DataBaseQuery, conexion);
//this case it's for obtain the text variable of the first column of the gridview (in my case it was the ID of the register).
cmd.Parameters.AddWithValue("#variable1", ((Label)GridView1.Rows[i].Cells[0].FindControl("Label1")).Text.ToString());
//this case it's for obtain the selected value of a DropDownList that were in the 14 th column)
cmd.Parameters.AddWithValue("#variable2", ((DropDownList)GridView1.Rows[i].Cells[15].FindControl("DropDownlist2")).SelectedValue.ToString());
//this command it's for obtain the text of a textbox that is in the 15 th column of the gridview.
cmd.Parameters.AddWithValue("#variable3", ((TextBox)GridView1.Rows[i].Cells[16].FindControl("TextBox17")).Text.ToString());
cmd.ExecuteNonQuery();
}
//after going through all the gridview you have to close the connection to the DataBase.
connection.Close();
}
}
Of course you have to adjust the code to your particular case but it's very easy. In this code you have the example to obtain values for other object like labes, textbox and dropdownlist in the gridview.
I suffered a lot to make run this code (I'm not good programming) but I'm happy to help.
NOTE: For count the columns of the gridview you have to start at zero.
NOTE2: Sorry for my bad English by the way... It's not my nature language.
I am trying to make a gridview sortable which uses a stored procedure as a datasource, I would not want it to rerun the query each time to achieve this. How would I get it to work my current code is:
protected override void OnPreRender(EventArgs e)
{
if (!IsPostBack)
{
SqlCommand cmd2 = new SqlCommand("SR_Student_Course_List", new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["RDCV2ConnectionString"].ConnectionString));
try
{
cmd2.CommandType = CommandType.StoredProcedure;
cmd2.CommandTimeout = 120;
cmd2.Parameters.Add("student_id", SqlDbType.Char, 11).Value = student;
cmd2.Connection.Open();
grdCourses.DataSource = cmd2.ExecuteReader();
grdCourses.DataSourceID = string.Empty;
grdCourses.DataBind();
} finally
{
cmd2.Connection.Close();
cmd2.Connection.Dispose();
cmd2.Dispose();
}}}
This code just binds the data when it isn't a postback, the gridview has viewstate enabled. On pressing the column headers a postback happens but no sorting occurs. If anyone has a simple fix for this please let me know or even better an ajax sort which would avoid the postback would be even better. The dataset is relatively small however takes a long time to query which is why I would not like to requery on each sort.
If you are not paging the results, and just doing a read, then something like the jquery tablesorter plugin would be a quick and easy fix. I have used this on tables of up to 1400 rows and works great, although ~> few hundred probably better on slow putas.
If the gridview is editable, then aspnet event/input validation might spit a dummy if you don't go through the proper registration of client scripts etc.
You could try storing the data in view state (or cache).
In your case, I would use a SqlDataAdapter and fill a DataTable. Then, put the DataTable into a Session variable. When the GridView is sorting, check if the Session variable still exists. If it does not, then fill the DataTable again. Finally sort the DataTable using a DataView and rebind the GridView with the DataView.