I have a C# winforms app form with a TreeView on it. Populating the TreeView is done using a stored proc and view (not table) from database.
This works fine as it puts the information into the TreeView as all root nodes. I have drag and drop available to the users for the TreeView so they can move nodes and have a parent/child/grandchild/etc. However, many are needed. This also works fine.
What I am struggling with (more like getting frustrated with) is saving the users' TreeView changes back to the database table. I considered making the change with each move but decided to use a button click event when all is done being moved.
I am providing what code I have so far. Just remember that this is not final look of the click event since button is not named plus a few other cleanups needed as well and the sqlUpdate will actually become a stored proc.
In the sqlUpdate there are 2 parameters listed; #parentid and #industryid. If I was to hard code those with a number (ex: 1 and 4) the update works and makes the changes in the table to the correct industry id. When the TreeView is populated it uses three (3) fields from the table; IndustryID, ParentID, IndustryItem. These go into a datatable and to the TreeView.
What I am getting frustrated over is getting the #parentid and #industryid which is why I am posting here for help. I've done updates, deletes, inserts many times but for some reason this is making draw a blank.
I do realize I need to specify the parameters in the code but I'm thinking that is where the issue is. Here are the 2 lines;
command.Parameters.AddWithValue("#parentid", ?????);
command.Parameters.AddWithValue("#industryid", ?????);
And here is the click handler:
private void button6_Click(object sender, EventArgs e)
{
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlCommand command = new SqlCommand();
{
string sqlUpdate = "UPDATE tblIndustry SET IndustryItemParentID = #parentid WHERE IndustryID = #industryid";
try
{
conn.Open();
command.Connection = conn;
command.CommandType = CommandType.Text;
command.CommandText = sqlUpdate;
command.ExecuteNonQuery();
MessageBox.Show("Done");
}
catch (Exception ex)
{
MessageBox.Show("There is an error." + '\r' + '\n' + '\r' + '\n' + ex.ToString(), "NOTICE", MessageBoxButtons.OK);
}
finally
{
conn.Close();
}
}
}
}
Here's one way to do it:
For #industryid, use an auto-incremented id column in the database. Assign that value to the treeview node tags when you populate the treeview. Then use the value of treeview.parent.tag for #parentid.
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 two user controls. One is to input data and another one has a combobox that displays data from my MySQL table.
The use types in data in the first user control and presses a button. This adds the data to a MySQL table. I want to add the data immediately / automatically into the combobox (the other user control).
I would prefer not doing it using an event. If it is not possible and I have to use an event, what event should I use? Can it be an event not associated to the button?
Here is the method that reads data from MySQL and adds it to the combobox :
private void LoadFromDatabase()
{
string query = "select name from country";
MySqlConnection conn = new MySqlConnection(connection);
MySqlCommand command = new MySqlCommand(query,conn);
MySqlDataReader Read;
conn.Open();
Read = command.ExecuteReader();
while(Read.Read())
{
metroComboBox1.Items.Add(Read.GetString("name"));
}
conn.Close();
}
The current result is that I must reload the windows form to load the new data into thecombobox. Without the reload, the combobox only displays the old data. I have put that method under InitializeComponent(); of the combobox user control.
You can use the event click on the comboBox itself, so whenever you click it to open the dropdown it will update the combobox. Make sure to clear the items at the top of the click event to prevent duplicates.
If you truly insist on having no events, you can use a background worker, however for what you're doing it seems like overkill to spawn a thread just for that.
This is an idea of what the final result should look like.
private void comboBox1_Click(object sender, EventArgs e)
{
if (comboBox1.Items.Count > 0)
comboBox1.Items.Clear();
LoadFromDatabase();
comboBox1.SelectedItem = 0;
comboBox1.Text = "Select Item";
}
So I'm making a seat reservation system for a school project and I'm stuck. I'll explain exactly what I'm trying to do. I created this form:
Seat Reservation Layout
As you can see, I created a seat layout. All the seats are buttons. I also created a local SQL database with SeatID (which matches the names of the buttons exactly) and Availability (either True or False).
What I wanted to do is let the user choose seat(s) (which becomes green after clicking on it) and whenever the user clicks on the "OK" button, the seats get reserved, meaning that I want the Availability in my database corresponding with the buttonname and thus, the SeatID, to become False (meaning the seat got reserved). After running the program again, the reserved seats need to be red, on the start, meaning they can not get reserved.
So basically I managed to do it all; My database works, reserved seats are red whenever I run the program etc.
The only thing I can not get working is updating the database with reserved seats.
private void OK_Click(object sender, EventArgs e)
{
con.Open();
SqlCommand command;
SqlDataAdapter adapter = new SqlDataAdapter();
String sql = "";
command = new SqlCommand(sql, con);
foreach (Button button in buttons)
{
if (button.BackColor == Color.Green)
{
sql = "UPDATE Seats SET Availability='" + "False" + "'WHERE SeatID=" + button.Name;
adapter.UpdateCommand = new SqlCommand(sql, con);
adapter.UpdateCommand.ExecuteNonQuery();
}
}
command.Dispose();
con.Close();
}
Above you see my code where I try to update the databse. I made the list of all buttons called "buttons" and the code above looks through all the buttons and checks whether they're green or not (green == clicked, so ready to be reserved). That is supposed to happen when I click on the "OK" button. When I run this, I get this error message:
Error Message
So, what am I doing wrong? How am I supposed to update the database by checking whether the SeatID corresponds with the button name?
Thanks in advance.
EDIT: Here I attach my database:
Datatable
Data
You should use parameters in your SQL query insead.
sql = "UPDATE Seats SET Availability= #Availabe WHERE SeatID = #SeatID" ;
adapter.UpdateCommand.Parameters.AddWithValue("#Available", false); //I assume that your Availibility column is a BIT type.
//If a varchar column for exemple, you can use
//adapter.UpdateCommand.Parameters.AddWithValue("#Available", "False"); //But, you should use a bit column instead.
adapter.UpdateCommand.Parameters.AddWithValue("#SeatID", button.Name);
adapter.UpdateCommand = new SqlCommand(sql, con);
adapter.UpdateCommand.ExecuteNonQuery();
To add parameters to your SQL Command, you can take a look at this :
https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=netframework-4.8
Did you try this command;
sql = "UPDATE Seats SET Availability='False' WHERE SeatID=" + button.Name;
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.
Afternoon All,
I have been tasked with turning what is currently a paper-based form which our users fill in, into an electronic form in a Windows Form c# application, where the user can fill it in electronically then click a button, which puts the data in the database.
I have already completed 5 other forms with no issues, however the one I have just reached, which I thought would be the simplest, has stumped me.
This is an example of what the paper one looks like and how it is filled in (it gets printed from excel first):
My database has the following tables:
User
UserID
UserName
EquipmentReturnSubmission
UserID (from User table)
ReturnID
ReturnDate
EquipmentReturnDetails
ReturnID (from EquipmentReturnSubmission table)
SerialNo
Description
When the data is put into the database, each row on the form above will have a row in the EquipmentReturnDetails table, but all have the same ReturnID, so this can be linked to produce a list of the equipment submitted by that user.
The bit that has stumped me is how to do this in my WinForms application. I've had a look at inserting data from a GridView into a database, but can only find how to do this one row at a time - i need this to insert all of the rows using the same ReturnID so it can be linked.
I thought I could do something like below, but not a clue where to start to get it coded, nor even if this is the best way to do it.
My thinking is that the user enters the serial number and description, and clicks add, which puts the details into listbox/gridview or some kind of holding area, and clears the text boxes. The user can then keep doing this, each time the details are added to the holding area, then the submit button writes it to the database.
Again i'm not sure how this could be done unless there's a way to create a parameter each time the Add button is clicked.
If anyone could point me in the right direction that would be great. I'm self taught so happy to be completely corrected.
Thanks in advance.
Well, thanks to Zath's comment I did a bit more research and managed to get this working with the below:
Tables:
User
UserID
UserName
EquipmentReturnSubmission
UserID //(from User table)
ReturnID
ReturnDate
EquipmentReturnDetails
ReturnID //(from EquipmentReturnSubmission table)
SerialNo
Description
I then added a DataGridView to my form, and added the columns SerialNo and Description. My C# code below:
private void Submit_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Are you sure these details are correct?", "Are you sure?", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
dataGridView1.AllowUserToAddRows = false; //Disables edit so the insert doesnt try and do an insert for the blank row created when the user clicks to add data.
#region SQL Insert
SqlConnection con = new SqlConnection(Home.ConString);
SqlCommand cmd = new SqlCommand("EquipmentReturnSubmission1", con);
cmd.CommandType = CommandType.StoredProcedure;
#region Parameters
cmd.Parameters.Add("#Name", SqlDbType.VarChar, 200).Value = OfficerName.Text;
cmd.Parameters.Add("#Area", SqlDbType.VarChar, 200).Value = Area.Text;
cmd.Parameters.Add("#SubmissionDate", SqlDbType.Date).Value = SubmissionDate.Value;
cmd.Parameters.Add("#SubmissionID", SqlDbType.Int).Direction = ParameterDirection.Output;
#endregion
try
{
con.Open();
cmd.ExecuteNonQuery();
}
catch (System.Exception ex1)
{
throw new System.Exception("Error submitting equipment return sheet." + ex1.Message);
}
finally
{
SubID = int.Parse(Convert.ToString(cmd.Parameters["#SubmissionID"].Value));
con.Close();
SecondInsert();
}
#endregion
}
}
}
private void SecondInsert()
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
SqlConnection con = new SqlConnection(Home.ConString);
{
SqlCommand cmd = new SqlCommand("INSERT INTO EquipmentReturnSubmissionDetails (SubmissionID, SerialNumber, Description) VALUES (#SubmissionID, #SerialNumber, #Description)", con);
cmd.CommandType = CommandType.Text;
{
cmd.Parameters.AddWithValue("#SubmissionID", SqlDbType.Int).Value = SubID;
cmd.Parameters.AddWithValue("#SerialNumber", row.Cells["SerialNo"].Value);
cmd.Parameters.AddWithValue("#Description", row.Cells["Description"].Value);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
MessageBox.Show("Data submitted.");
this.Close();
}
This worked exactly as I required it to and does it very quickly.