I've got a gridview displaying product instance info; I need a hyperlink in my Action column to bring up an view/edit page that displays the row data. How do I make the link bring up the data from that specific row into the edit page?
Note: there are other questions with similar titles, however, they do not cover this specific topic.
Use datakeys in the gridview, using datakey will get you the id of each clicked hyperlink , and then you can use that id to edit or delete the selected items easily. In the code behind just find the hyperlink control , pass the data key and write d update sql for it. Inorder to move your data to other pages you can sessions but if you are developing a commercial website session wont be a good idea due to its security issues, use cookies in that case .
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Request.QueryString["productID"] != null)
{
productID = Convert.ToInt32(Request.QueryString["productID"]);
bindData(productID)
}
...
}
}
protected void bindData(int productID)
{
//to avoid sql injection as mentioned below use parameters
SqlConnection conn = new SqlConnection(ConnectionString); // define connection string globally or in your business logic
conn.Open();
SqlCommand sql = new SqlCommand("Select * From [Table] Where ID = #productID",conn);
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "#ID";
parameter.Value = productID;
sql.Parameters.Add(parameter);
conn.close()
}
You can also use Microsoft.ApplicationBlocks.Data.dll to avoid repeating ado.net , it will reduce your code.
Try something like this?
ViewProducts.aspx:
<columns>
<asp:HyperLinkField DataNavigateUrlFields="ProductID" HeaderText="Edit"
ItemStyle-Width="80"
DataNavigateUrlFormatString="EditProduct.aspx?productID={0}"
Text="Select" ItemStyle-HorizontalAlign="Center" />
...
</columns>
EditProduct.aspx:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Request.QueryString["productID"] != null)
{
productID = Convert.ToInt32(Request.QueryString["productID"]);
...
}
...
}
}
There are n+1 ways to solve this problem. If you are using the sql data source you can accentually have VS generate the sql and edit logic for you if you don't have specific requirements. here is a code project tutorial.
Another oft used tactic is to add a command button to the row and populate the command argument with the ID of the row you want to edit then in the oncommand event handle what ever logic you need.
you can also use a simple html link and and use get parameters. Or you can session like I said there a a ton of ways to solve this problem.
Related
When I choose any option from the dropdown list and then insert it into the database, the first option is chosen automatically, even if I choose the second or third option; only the first option is inserted each time.
Order.aspx.cs
protected void selectList()
{
conn = new SqlConnection(connstr);
conn.Open();
sql = "SELECT * FROM Product";
SqlCommand comm = new SqlCommand(sql, conn);
adap = new SqlDataAdapter(comm);
DataSet ds = new DataSet();
adap.Fill(ds);
ProductID.DataTextField = ds.Tables[0].Columns["Name"].ToString();
ProductID.DataValueField = ds.Tables[0].Columns["Id"].ToString();
ProductID.DataSource = ds.Tables[0];
ProductID.DataBind();
}
protected void Page_Load(object sender, EventArgs e)
{
bindGrid();
selectList();
}
protected void btnAdd_Click(object sender, EventArgs e)
{
selectList();
sql = "INSERT INTO [Order] (CustomerID,ProductID ,EmployeeID,Quantity,Date) VALUES ('" + CustomerID.Text + "','" + ProductID.SelectedValue + "','" + EmployeeID.Text + "','" + Quantity.Text + "','" + Date.Text + "')";
conn = new SqlConnection(connstr);
conn.Open();
comm = new SqlCommand(sql, conn);
comm.ExecuteNonQuery();
conn.Close();
bindGrid();
ScriptManager.RegisterStartupScript(Page, Page.GetType(),
"myPrompt", "alert('Successfully Updated!');", true);
}
Order.aspx
Product ID:
<asp:DropDownList ID="ProductID" runat="server" CssClass="form-control" ></asp:DropDownList>
Actually, the mistake here is the page load. In 99% of ALL pages, you only want to bind and load up on the first page load. And most if not all asp controls will automatic persist for you. So, your big mistake is this:
protected void Page_Load(object sender, EventArgs e)
{
bindGrid();
selectList();
}
The above has to become this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
bindGrid();
selectList();
}
}
In fact, you really can't build a functional web form page unless you follow the above rule. Remember, any button, any post-back, and the page load event will run again.
So yes, page load is the right place, but you in near 99% of cases need to wrap that code in the all important isPostBack = false code stub.
Once you do above, then your whole page will operate quite nice, quite normal, and in near all cases, you find the controls correct persist their values and settings.
So, no, page load is NOT too soon, and page load is VERY much the correct event and place to load up the data bound controls - but, you only want to do this on the really first page load.
In fact, there is probably 1 question near per day on SO, and their woes and problems can be fixed by following the above simple rule. Failure to note the above isPostBack? You can't really even build a working asp.net page.
Page_Load() is too late to bind your list.
Remember, when using web forms, you start from scratch and have to recreate all of your data items on every single request... even simple button click events*. This is why you call bindGrid() in the Page_Load() method. However, part of this process also involves restoring ViewState, so the button click will know what item was selected. The problem is this ViewState data is restored before the Page_Load() method is called. Therefore the grid is still empty, and the SelectedValue information you need to get from ViewState cannot be set correctly.
You can fix this by moving the code that binds your grid data up to the Init or Pre_Init events.
While I'm here, I need to reiterate my comment about SQL Injection. This is a really big deal... the kind of thing that's too important to do wrong even with learning and proof-of-concept projects. I suggest using Google to learn more about using parameterized queries with C#.
Additionally, it's rare to insert selections directly into an Orders table. Often there's a separate "ShoppingCart" table, using a Session Key for the table's primary key, where the user can build up the cart before completing the order and creating the final Order and OrderLines or OrderDetail records.
* For this reason, it's often worthwhile in web forms to do more of this work on the client browser, in javascript.
I have an application that makes the user chose an item from a list, then the components of this item are displayed and when clicking a component, a dataGridView is populated with the stock of that component (size and quantity).
I'd like to make it so that the user can modify the numbers in the dataGridView and UPDATE, INSERT and DELETE inside the database by only using only one "Save" button.
I managed to make these functions work separately but I wonder how it is possible to have them all in one button_click event.
For example here's my update function :
private void buttonSave_Click(object sender, EventArgs e)
{
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
if (con.State == ConnectionState.Open)
{
foreach (DataGridViewRow row in dataGridViewStock.Rows)
{
if (row.Cells[0].Value != null && row.Cells[1].Value != null)
{
SqlCommand update = new SqlCommand("UPDATE stock_test SET quantity=" + row.Cells[1].Value + " WHERE size=" + row.Cells[0].Value+ "AND codeArticleComponent ='" +labelComponentChosen.Text+ "'" , con);
update.ExecuteNonQuery();
update.Parameters.Clear();
}
}
}
}
edit : I know the older version of this application managed this by simply dropping the whole table and inserting all the values again but I don't want to do it like this because it seems totally unsafe and the table will end being of a big size.
Sometimes there is a need to insert, update and delete records in a GridView using a single Stored Procedure instead of creating separate Stored Procedures for each operation.
Suppose I have one .aspx web page in which I need a to insert, view, update and delete records. To do that, instead of creating four Stored Procedures to perform these tasks I will create a single Stored Procedure to satisfy my requirements and I will access it in code behind depending on the action performed by the end user on a button click.
I have written this article specially focusing on newcomers and anyone new wants to insert, update and delete records in a GridView using a Single Stored Procedure, so let us start with a basic introduction.
First create the the table named employee as:
I have set the primary key on the id column and I have set the Identity specification to Yes.
Now we have a table to perform these operations for. Now let us start to create the Stored Procedure.
The Stored Procedure is created using the keyword Create Procedure followed by the procedure name. Let us create the Stored Prcedure named "EmpEntry" as in the following:
create Procedure EmpEntry
(
--variable declareations
#Action Varchar (10), --to perform operation according to string ed to this varible such as Insert,update,delete,select
#id int=null, --id to perform specific task
#FnameVarchar (50)=null, -- for FirstName
#MName Varchar (50)=null, -- for MName
#Lname Varchar (50)=null -- for LastName
)
as
Begin
SET NOCOUNT ON;
If #Action='Insert' --used to insert records
Begin
Insert Into employee (FirstName,MName,LastName)values(#Fname,#MName,#Lname)
End
else if #Action='Select' --used to Select records
Begin
select *from employee
end
else if #Action='Update' --used to update records
Begin
update employeeset FirstName=#Fname,MName=#MName,LastName=#Lname where id=#id
End
Else If #Action='delete' --used to delete records
Begin
delete from employeewhere id=#id
end
End
The comments in the Stored Procedure above clearly explain which block is used for which purpose, so I have briefly explained it again. I have used the #Action variable and assigned the string to them and according to the parameter ed to the Stored Procedure the specific block will be executed because I have kept these blocks or conditions in nested if else if conditional statements.
The most important thing is that I have assigned null to each variable to avoid the effect on the parameter ed to the Stored Procedure because we are ing a different number of parameters but not the same number of parameters to the Stored Procedure to perform these tasks.
Now create the one sample application "Empsys" as:
"Start" - "All Programs" - "Microsoft Visual Studio 2010".
"File" - "New Project" - "C#" - "Empty Web Application" (to avoid adding a master page).
Provide the web site a name such as "Empsys" or another as you wish and specify the location.
Then right-click on Solution Explorer - "Add New Item" - "Default.aspx page".
Drag and drop one button, three textboxes, one GridView and one hidden field to the hidden value to the database and one label on the section of the Default.aspx page.
Then switch to the design view; the section of the Default aspx page source will look as in the following:
<form id="form1"runat="server">
<div>
First Name <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
Middle Name<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
Last Name <asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>
<asp:ButtonID="Button1"runat="server"Text="save"onclick="Button1_Click" />
</div>
<asp:HiddenField ID="HiddenField1" runat="server"/>
<asp:GridViewID="GridView1"runat="server" >
</asp:GridView>
</form>
Now use the following GridView event properties to perform events such as update, delete, edit cancel and so on. Let us see what the properties are:
DataKeyNames: This property I have used to the the row index of GridView
OnRowEditing: This property is used to handle the event when the user clicks on the edit button
OnRowCancelingEdit: This property is used to handle the event when the user clicks on the Cancel button that exists after clicking on the edit button
OnRowDeleting: This property is used to handle the event when the user clicks on the delete button that deletes the row of the GridView
OnRowUpdating: This property is used to handle the event when the user clicks on the update button that updates the Grid Record
Now my grid will look such as the following:
<asp:GridViewID="GridView1" runat="server" DataKeyNames ="id"OnRowEditing ="Edit"
OnRowCancelingEdit ="canceledit" OnRowDeleting ="delete" OnRowUpdating = "Update" >
</asp:GridView>
On the preceding GridView properties I have assigned the method name to be called for particular operations.
Method to Insert Data in Database
Right-click from the design page and view the code and then write the following code in the default.aspx.cs page to save the inserted records in the database:
protected void empsave(object sender, EventArgs e)
{
connection();
query = "studentEntryView"; //Stored Procedure name
SqlCommand com = new SqlCommand(query, con); //creating SqlCommand object
com.CommandType = CommandType.StoredProcedure; //here we declaring command type as stored Procedure
/* adding paramerters to SqlCommand below *\
com.Parameters.AddWithValue("#Action", HiddenField1.Value).ToString();//for ing hidden value to preform insert operation
com.Parameters.AddWithValue("#FName",TextBox1.Text.ToString()); //first Name
com.Parameters.AddWithValue("#Mname ", TextBox2.Text.ToString()); //middle Name
com.Parameters.AddWithValue("#LName ",TextBox3.Text.ToString()); //Last Name
com.ExecuteNonQuery(); //executing the sqlcommand
Label1.Visible = true;
Label1.Text = "Records are Submitted Successfully";
}
Now create the mehtod to view the records in the GridView:
public void viewdata()
{
connection();
query = "studentEntryView";
SqlCommand com = new SqlCommand(query, con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#Action", HiddenField2.Value).ToString();
DataSet ds =new DataSet();
SqlDataAdapter da = new SqlDataAdapter(com);
da.Fill(ds);
GridView1.DataSource = ds;
GridView1.DataBind();
}
The following is method for the "OnRowEditing" Event:
protected void edit(objectsender, GridViewEditEventArgs e)
{
GridView1.EditIndex= e.NewEditIndex;
gedata();
}
The following is method for the "OnRowCancelingEdit" Event:
protected void canceledit(object sender, GridViewCancelEditEventArgs e)
{
GridView1.EditIndex = -1;
gedata();
}
The following is method for the "OnRowDeleting" Event:
protected void delete(object sender, GridViewDeleteEventArgs e)
{
connection();
int id = int.Parse(GridView1.DataKeys[e.RowIndex].Value.ToString());
HiddenField1.Value = "Delete";
query = "EmpEntry";
com = new SqlCommand(query, con);
com.CommandType =CommandType .StoredProcedure;
com.Parameters.AddWithValue("#Action", HiddenField1.Value).ToString();
com.Parameters.AddWithValue("id", SqlDbType.Int).Value = id;
com.ExecuteNonQuery();
con.Close();
gedata();
}
The following is method for the "OnRowUpdating" Event:
protected void update(object sender, GridViewUpdateEventArgs e)
{
connection();
int id=int.Parse(GridView1.DataKeys[e.RowIndex].Value.ToString());
HiddenField1.Value = "update";
query = "EmpEntry";
com = new SqlCommand(query, con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#Action", HiddenField1.Value).ToString();
com.Parameters.AddWithValue("#FName", ((TextBox)GridView1.Rows[e.RowIndex].Cells[3].Controls[0]).Text.ToString());
com.Parameters.AddWithValue("#MName", ((TextBox)GridView1.Rows[e.RowIndex].Cells[4].Controls[0]).Text.ToString());
com.Parameters.AddWithValue("#LName", ((TextBox)GridView1.Rows[e.RowIndex].Cells[5].Controls[0]).Text.ToString());
com.Parameters.AddWithValue("#id", SqlDbType.int ).Value = id;
com.ExecuteNonQuery();
con.Close();
GridView1.EditIndex = -1;
gedata();
}
Brief introduction to the code
In the sample code above I have used the two string queries for giving the Stored Procedure name and the constr for storing the connection from the web.config file and another thing is that I have used a hidden field by which I am ing the action values that are required to our Stored Procedure.
Now our application is ready to use, press F5 or other as you know, then enter the some values to TextBox and press the "Save" button.
Now after clicking on the "Save" button, the hidden field value takes the value "Insert" and es it to the Stored Procedure as the action and because of this the Stored Procedure will execute a particular type of block.
Now at page load I have called the method, so after that the grid will fill as in:
Now click on the Edit button that calls the edit method as shown in the following grid:
If you click on the "Cancel" button then the editcancel method will be called and edit mode will be cancelled. Now enter some values into the grid TextBox and click on an update button that calls the update method and then the records in the GridView will be updated as in:
Now click on the delete button that calls the delete method and deletes the records from the GridView
Note
For detailed code please download the zip file attached above.
Don't forget to update the Web.config file for your server location.
try
{
TblProduct product = new TblProduct();
product.Description = textBox1.Text;
product.Price = decimal.Parse(textBox2.Text);
product.Image = imagedata;
product.ProductType = (int)comboBox1.SelectedValue;
msd.AddToTblProducts(product);
msd.SaveChanges();
Msgbox mg = new Msgbox();
mg.ShowDialog();
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
I want to delete and update data using datagridview. How do I do this?
To help you get started, inside of your Grid you would attach a button. Since I'm not sure if your utilizing Model View Controller, Web Forms, or another aspect I'll default to Web Forms. For instance:
<asp:LinkButton id='btnEdit-<%# Eval("Id") %>' runat="server"
CommandName="Delete"
CommandArgument='<%# Eval("Id")'
OnClick="btnDelete_Click"
Tooltip='<%# String.Format("Delete Record: {0}", Eval("Id")) %>' />
So the following button provides an argument name, when we push to code behind the CommandArgument value will now be accessible based on the Grid Id. That is what the Eval is exposing for us.
On the code behind, you would have the following:
protected void btnDelete_Click(object sender, EventArgs e)
{
var id = ((LinkButton)sender).CommandArgument as int?;
}
Inside the brackets the following occurs:
Instantiation
Retrieve the value in the CommandArgument
Casting as an int?
The instantiation is important to access the control, the CommandArgument has our value, the int? will provide a clean fail safe if it can't cast. It in essence will be null if it fails. Which is easy to work with.
Once you have said Id you can call your database and actually perform desired query.
Hopefully this helps.
So I've got a class, commenter, and two methods within that class, SaveBtn_Click - created primarily not by me, and then also PeerReview, primarily created by me.
Anyway, the code starts off like this (after a variety of using statements):
public partial class commenter : System.Web.UI.Page
{
string employee_reviewed;
PeerReview pr = new PeerReview();
public void SaveBtn_Click(object sender, EventArgs e)
{
//all the information for the SaveBtn_Click method.
}
After that, I have PeerReview:
public void PeerReview(System.Web.UI.WebControls.ListBox listbox)
{
MySqlConnection con = new MySqlConnection("server=localhost;database=hourtracking;uid=username;password=password");
MySqlCommand cmd = new MySqlCommand("select first_name from employee where active_status=1", con);
con.Open();
MySqlDataReader r = cmd.ExecuteReader();
Console.WriteLine("Another test!");
Console.WriteLine(r);
Console.WriteLine("Hi, this is a test!");
while (r.Read())
{
listbox.Items.Add(new ListItem(Convert.ToString(r["first_name"]), Convert.ToString(r["first_name"])));
}
con.Close();
}
I'm connecting this with ASP.NET, and I can get the listbox to show up, but not the individual items in the listbox. I'm testing it with a console.writeline command, to see if that outputs anything - but nothing is being put out on the ASP page.
I'm not certain how I should reference these particular sections (new to C#, asking like 3 dozen questions about this).
ASP code looks like this:
<asp:ListBox ID="listBox1" runat="server">
You have some confused declarations.
You declare a method called PeerReview, but you also have an attempt to create an instance of PeerReview as though it were a type. I think you really just want to call the PeerReview method from your button click event, eg
public void SaveBtn_Click(object sender, EventArgs e)
{
PeerReview();
}
And then eliminate the "PeerReview pr = new PeerReview();" line. Also, as this is on a page, you have an implicit reference within the partial class to the listbox by its ID, so you don't need to pass it as a parameter. And the Console.WriteLines are not useful in a web application - you might try Response.Write if you're wanting to add that to the output for debug purposes.
Edits based on OP response
You should call PeerReview in the Page_Load event handler:
public void Page_Load(object sender, EventArgs e)
{
// You need to determine if you should call PeerReview every time the page
// loads, or only on the initial call of the page, thus determining whether
// you need the IsPostBack() test. My instinct is that you *do* want to constrain
// it to the first pass, but only you can make that determination for
// certain based on your requirements.
if (!Page.IsPostBack) //Do you need this check?
{
PeerReview();
}
}
You're trying to add items to listbox though your listBox has an id of listBox1
Rather than looping through your data and adding items why not bind the datasource to your listbox and then set the DataTextField and DataValueField on your listbox.
So for example (typos may exist..sorry.. been a while since i wrote C#)
MySqlConnection con = new MySqlConnection("server=localhost;database=hourtracking;uid=username;password=password");
MySqlCommand cmd = new MySqlCommand("select first_name from employee where active_status=1", con);
con.Open();
MySqlDataReader r = cmd.ExecuteReader();
listBox1.DataSource = r;
listBox1.DataBind();
con.Close();
If you can't bind to the reader (can't remember..) then dump your results into a datatable first, then bind to the listBox1
DataTable dTable = New DataTable();
dTable.Load(reader);
listBox1.DataSource = dTable;
listBox1.DataBind();
in your asp, set the listBox fields like:
<asp:ListBox ID="listBox1" runat="server" DataTextField="first_name" DataValueField="first_name">
quick view here is you are adding items to listbox instead of listBox1
change:
listbox.Items.Add(new ListItem(Convert.ToString(r["first_name"]), Convert.ToString(r["first_name"])));
to:
listBox1.Items.Add(new ListItem(Convert.ToString(r["first_name"]), Convert.ToString(r["first_name"])));
I'm trying implement a simple Button field in the GridView.
<asp:ButtonField ButtonType="Button" CommandName="Delete" Text="Delete" />
I have a three-tier application that I'll combine into one function for this example:
protected void GV1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Delete")
{
var deletion = (HRA_internalLesion) GV1.SelectedRow.DataItem;
DataContext conn = new DataContext();
conn.HRA_internalLesions.DeleteOnSubmit(deletion);
conn.SubmitChanges();
}
}
I'm sure the var deletion line is not returning the Linq to SQL object I want.
The DataItem property isn't available after the control has been rendered initially. You'll have to re-create the data object from your fields on the page if you want to do this.
Edit:
From MSDN:
The DataItem property is only available during and after the RowDataBound event of a GridView control.
I'm not sure why it says "and after" -- this is confusing language to me -- but nonetheless, there's documented evidence.