So i have got a form in which there are two sections one to add and one to delete.
But the problem is when i add data and after which when i check the combobox associated with delete section i can see all previous data except the one which i just added. So i need some kind of solution to refresh and re get everything into combobox as soon as i click Add button but no luck the latest data wont show.
Code for add button:
private void btnAddSubj_Click(object sender, EventArgs e)
{
OleDbDataReader cmd = ad.select("SELECT TOP 1 ID FROM subjects WHERE ID = " + int.Parse(txtSubjID.Text));
if (cmd.Read())
{
MessageBox.Show("Subject ID you entered is taken, please select a different one");
}
else
{
ad.insert("insert into subjects (`ID`,`subjectName`) values(" + int.Parse(txtSubjID.Text) + ",'" + txtSubjName.Text + "')");
}
populateComboBoxSubjName();
}
Here ad is associated to class which i created and contains all the methods for insert,select,delete,update.
code for populateComboBoxSubjName:
private void populateComboBoxSubjName()
{
comboBoxSubjName.Items.Clear();
OleDbDataReader cmd = ad.select("SELECT * FROM subjects");
while (cmd.Read())
{
for (int f = 0; f < cmd.FieldCount; f+=2)
{
string data = (cmd.GetValue(f).ToString() + "-" + cmd.GetValue(f + 1).ToString());
comboBoxSubjName.Items.Add(data);
}
}
}
Button Delete Code:
private void btnDeleteSubj_Click(object sender, EventArgs e)
{
string selected = this.comboBoxSubjName.GetItemText(this.comboBoxSubjName.SelectedItem);
string[] idToDelete = selected.Split('-');
ad.delete("DELETE FROM subjects WHERE ID=" + int.Parse(idToDelete[0]));
}
I was trying to perform sql queries using another class (i created one and coded all the queries and connections with different methods for each like insert,delete,select) so i wouldnt need to write whole command again and again but for some reason it didnt work. I had to write every command again and again and that worked perfectyl.
Related
I am trying to edit a row from the datagridview. Every row has a button. When I press one of the rows button, a second form opens and show me the information in textboxes about that row and I need to edit what I want.
The problem is that I already wrote the code for editing but I can't add the DataGridViewCellEventArgs in the button function, or I can't use RowIndex to edit a specific row.
Here is the code:
public void btnUpdate_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(#"Data Source=DESKTOP-VUPD668;Initial Catalog=dbApp;Integrated Security=True");
SqlCommand cmd;
cmd = new SqlCommand("UPDATE tableApplication SET Name='" + txtName.Text + "',Package='" + txtPackage.Text + "',Hour='" + txtHour.Text + "',Date='" + txtDate.Text + "',Phone='" + txtPhone.Text + "',Observations='" + txtObservations.Text + "' WHERE ID=" + f1.dgvContactList.Rows[rowIndex].Cells[0].Value.ToString(), conn);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
MessageBox.Show("Edit was saved");
this.Close();
}
and here is the code from the main form with the dgv
public void dgvContactList_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 7)
{
formAddEditContact f2 = new formAddEditContact();
int rowIndex = e.RowIndex;
formContact f1 = new formContact();
f2.lblTitle.Text = "Edit";
f2.btnSave.Visible = false;
f2.btnUpdate.Visible = true;
f2.btnDelete.Visible = true;
f2.txtName.Text = f1.dgvContactList.Rows[rowIndex].Cells[1].Value.ToString();
f2.txtPackage.Text = f1.dgvContactList.Rows[rowIndex].Cells[2].Value.ToString();
f2.txtHour.Text = f1.dgvContactList.Rows[rowIndex].Cells[3].Value.ToString();
f2.txtDate.Text = f1.dgvContactList.Rows[rowIndex].Cells[4].Value.ToString();
f2.txtPhone.Text = f1.dgvContactList.Rows[rowIndex].Cells[5].Value.ToString();
f2.txtObservations.Text = f1.dgvContactList.Rows[rowIndex].Cells[6].Value.ToString();
f2.ShowDialog();
How I can use RowIndex in the button function. How I can add DataGridViewCellEventArgs.
It is seldom a good idea to access the displayed data in the DataGridView directly. You should separate the way that data is displayed from the actual values. This way you can easily change the display, without having to change the code that uses the data.
Apparently your DataGridView shows several properties of a sequence of Contacts. Every Row shows one Contact:
class Contact
{
public int Id {get; set;}
public string Name {get; set;}
public DateTime BirthDay {get; set;}
...
}
You have added DataGridViewColumns to your DataGridView. Every DataGridViewColumn shows one property. The name of the property that should be shown is in DataGridViewColumn.DataPropertyName
DataGridViewColumn columnBirthDay = new DataGridViewColumn();
columnBirthDay.DataPropertyName = nameof(Contact.BirthDay);
... // set other properties.
Now all you have to do is, get your data and put them in the DataSource of the DataGridView:
IEnumerable<Contact> contactsToDisplay = ...
this.DataGridViewContacts.DataSource = new BindingList<Contact>(contactsToDisplay);
Now every change that the operator edits, is automatically updated in the DataSource. Every change that your program makes to the data source is automatically displayed.
Programmatically add a contact:
BindingList<Contact> DisplayedContacts => (BindingList<Contact>)this.DataGridViewContacts.DataSource;
private void DisplayContact(Contact contact)
{
this.DisplayedContacts.Add(contact);
}
Access edited contacts, for instance after pressing a button:
private void OnButtonOkClicked(object sender, ...)
{
Collection<Contact> editedContacts = this.DisplayedContacts;
this.ProcessEditedContacts(editedContacts);
}
Every row in your DatagridView has a button. If the operator pressed the button you want to use the Contact that is displayed in that row to do something.
private Contact GetContact(DataGridViewRow row)
{
return (Contact)row.DataBoundItem;
}
private void dgvContactList_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
// in baby steps:
DataGridView dataGridView = (DataGridView)sender;
DataGridViewRow row = dataGridView.Rows[e.RowIndex];
Contact contact = GetContact(row);
EditContact(contact);
}
You can do this in one big statement. Not sure if this improves readability though.
private void EditContact(Contact contact)
{
using (var dlg = new EditContactDlg())
{
dlg.Contact = contact;
... // other dialog properties
var dialogResult = dlg.Show(this);
if (dlgResult == DialogResult.OK)
{
... // process edited contact
}
}
}
Be careful: you attach the original unedited contact to the dialog box. If the operator changes values and presses Cancel, the original contact might still be changed. Better is to attach a Cloned contact to the dialog, and if needed use the properties of the edited cloned contact to update the original contact.
Did you see, that because I didn't do everything in one big procedure, the procedures are much easier to understand. They are much easier to be changed slightly, and they can also be reused easily.
For instance, if you decide not to add a column with buttons, because you don't want to display 50 buttons in your form, you decide to add one button to edit the "currently selected row", code changes will be minimal:
private void OnButtonEditCurrentRow_Clicked(object sender, ...)
{
DataGridViewRow row = this.DataGridViewContacts.CurrentRow;
Contact contact = GetContact(row);
EditContact(contact);
}
This procedure can of course also be reused if you want to add a menu item to edit the current row.
Because you separated the way that Contacts are displayed in the datagridview from the actual contacts, code changes will be small if you decide to display the Contact differently, for instance if you decide not to display the Id of the contact anymore, or if you plan to use a Japanese method of displaying the birthday. Or if you implement ordering of the data. The BindingList always contains the internal contact data.
Similarly, if you want to change your contact. For example separate the firstname and the lastName, but still want to display them in one column, code changes will be very small.
I'm trying to give my client a way to SELECT a specific row by typing the id which is the auto incremented primary key of the table.
But there's an issue Showing the Selected row to the client using Text Boxes and letting the client UPDATE the row's cells by editing the Text Boxes and pressing another button.
I'd be glad if you guide be how to do this since I haven't got any help from the search results.
Here's the uncompleted code:
private void LookUpBtn_Click(object sender, RoutedEventArgs e)
{
if (UserIDUpdateTB.Text == "")
{
MessageBox.Show("Customer ID is needed.", "Error");
}
else
{
SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-8QAH8VK\SQLDB; Initial Catalog=Restaurant_DB; Integrated Security=True;");
con.Open();
SqlCommand lookforcustomer = new SqlCommand("LookForCustomer", con);
lookforcustomer.CommandType = CommandType.StoredProcedure;
lookforcustomer.Parameters.AddWithValue("userid", UserIDUpdateTB.Text);
//lookforcustomer.ExecuteNonQuery();
SqlDataReader reader = lookforcustomer.ExecuteReader();
reader.Read();
object test = reader.GetValue(1);
MessageBox.Show(test.ToString(), "Error");
var id = (int?)lookforcustomer.ExecuteScalar();
con.Close();
}
}
Here's the user interface:
The client enters the customer ID , presses the look up button and five cells of the row which belongs to the entered ID, appear in five other Text Boxes separately. the client makes whatever changes he/she wants by Changing the Text Boxes' text and pressing the "Update Info" button.
I'd be thankful if you help.
This is not a sql/database question, its a question regarding your UI. I'm assuming its WPF, although WinForms properties were pretty similar too.
Each button should have a separate _Click event right? So in the UpdateInfo_click, you can either send a full UPDATE statement to SQL, or detect changes between a model in memory and what is in each TextBox.Text and only update those which change (or best yet in the where clause say WHERE Name = {old value})
Also on each of your buttons you can set a Command= property, which is needed if this were part of a repeater or similar, and you can have the same handler inspect what command it was called with to determine the action needing to be taken
So I think if I understand right, basically what you want to do is pull a customers information when the lookup button is clicked, and update the customers information when the submit button is clicked. Possibly you want to also be able to add new records?
Some of the data readers are a little different, I've used Odbc and Npgsql. But I will try and show the basics of what you want below.
I like to have a separate class that deals with the Database connection, I use a method similar to this to run queries.
private SqlDataReader Query(string query)
{
SqlCommand command = null;
SqlDataReader result_reader = null;
try
{
//conn.Open();
command = new SqlCommand(query_to_perform, database_connection); //database_connection is the same as the as your "con" variable
result_reader = command.ExecuteReader();
this.successful_query = true;
this.error_message = "";
//conn.Close();
}
catch (SqlException ex)
{
this.successful_query = false;
this.error_message = ex.Message;
//destroy the connection on a failure
database_connection = new SqlConnection();
throw;
}
return result_reader;
}
Next we basically need to fill the text boxes from a select statement where the customer id is equal to the customer id on the table
private void LookUpBtn_Click(object sender, RoutedEventArgs e)
{
SqlDataReader reader = ConnectionClass.Query("SELECT * WHERE customer_id = '" + customerIdTextbox.Text + "';")
if (reader.Read())
{
//reader[0] probably is CustomerId
NameTextbox.Text = reader[1].ToString();
LastNameTextbox.Text = reader[2].ToString();
PhoneNumberTextbox.Text = reader[3].ToString();
CellphoneNumberTextbox.Text = reader[4].ToString();
AddressTextbox.Text = reader[5].ToString();
}
}
Update the customer, I'd suggest disabling the CustomerId box after they pull up an account, or they might change the number and update a different customer with all the information pulled from the first customer,
private void SubmitBtn_Click(object sender, RoutedEventArgs e)
{
if (//!exists)
{
CreateNewCustomer();
}
else
{
ConnectionClass.Query("UPDATE table SET name = '" + NameTextbox.Text + "', lastname = '" + LastNameTextbox.Text + "', phonenumber = '" + PhoneNumberTextbox.Text + "', cellphonenumber = '" + CellphoneNumberTextbox.Text + "', address = '" + AddressTextbox.Text + "' WHERE CustomerID = '" + customerIdTextbox.Text + '";");
}
}
I believe this should give you the very basics of what you are trying to do, you can still do the queries the way you were if you don't want to create a separate class to deal with the db connection. You might also want to look in to preventing SQL Injections, you will need to deal with things like apostrophes in the text, and creating a new customer will just use an insert query.
I have a dataGridView within a MainForm that is listing all the relevant data into it when the form loads.
When i want to go to edit a row. I select it and press edit, it then loads an EditForm. Here i can edit the data and save.
The information has been successfully edited and saved but the dataGridView isnt updating.
Is there an autoRefresh property i have not seen or a way to refresh it when closing the edit form?
MainForm
private void EditAdminBtn_Click(object sender, EventArgs e)
{
EditAdminForm Admin = new EditAdminForm();
Admin.idTxt.Text = this.dataGridView1.CurrentRow.Cells[0].Value.ToString();
Admin.usernameTxt.Text = this.dataGridView1.CurrentRow.Cells[1].Value.ToString();
Admin.firstnameTxt.Text = this.dataGridView1.CurrentRow.Cells[2].Value.ToString();
Admin.surnameTxt.Text = this.dataGridView1.CurrentRow.Cells[3].Value.ToString();
Admin.emailTxt.Text = this.dataGridView1.CurrentRow.Cells[4].Value.ToString();
Admin.statusCombo.Text = this.dataGridView1.CurrentRow.Cells[6].Value.ToString();
Admin.ShowDialog();
}
public void MainForm_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'student_CBDataSetAdmin.Admin' table. You can move, or remove it, as needed.
this.adminTableAdapter.Fill(this.student_CBDataSetAdmin.Admin);
}
EditForm
private void SaveBtn_Click(object sender, EventArgs e)
{
//SQL Connection and SQL for updating admin information
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\v11.0; AttachDbFilename=C:\Users\Donald\Documents\Visual Studio 2013\Projects\DesktopApplication\DesktopApplication\Student_CB.mdf ;Integrated Security=True");
SqlDataAdapter sda3 = new SqlDataAdapter("UPDATE Admin set Admin_Username='" + this.usernameTxt.Text + "' , Admin_FName='" + this.firstnameTxt.Text + "' , Admin_SName='" + this.surnameTxt.Text + "' , Admin_Email='" + this.emailTxt.Text + "', Admin_Status='" + this.statusCombo.Text + "' WHERE Admin_ID='" + this.idTxt.Text + "'", con);
DataTable dt3 = new DataTable();
sda3.Fill(dt3);
MessageBox.Show("Information Successfully Updated!");
dt3.Clear();
this.Close();
}
THIS IS WHAT IT LOOKS LIKE, GRIDVIEW SOURCE AND BINDING AT THE BOTTOM
The problem is that you are not sending any reference to a databound object or whatever, you are copying the values from the datagridView into the popup, and then you are not doing anything with it.
You need to either return the dataTable when you are closing the popup, or manually call a refresh of your dataAdapter. This second option is easier though it requires one more trip to the database.
at the end of your EditAdminBtn_Click add`
EDIT: As per your screenshot, I see that you use a bindingSource. Once you've refreshed your dataTable you can reset the bindings
this.adminTableAdapter.Fill(this.student_CBDataSetAdmin.Admin);
AdminBindingSource.ResetBindings(false);
In Windows forms
I have a listbox and two buttons UP and Down.. When I click one of the buttons, the list Item will move up or down, depending on which button was clicked.
My question is when I click Down button, the listItem will moving towards downside at the same time it will updated as same as listitems in run time.. I was trying a lot my code is shown below..
private void btndown_Click(object sender, EventArgs e)
{
//string myNextItem1 = frm2lstbx.Items[frm2lstbx.SelectedIndex + 1].ToString();
string globalNextItem1 = "";
{
int a = frm2lstbx.Items.Count - 1;
if (frm2lstbx.SelectedItem == null)
{
MessageBox.Show("Please select an Item");
}
else if (frm2lstbx.SelectedIndex == a)
{
MessageBox.Show("No Items to move Lower side");
}
else
{
int i = 0;
i = frm2lstbx.SelectedIndex;
string currItem = "";
string nextItem = "";
globalNextItem1= frm2lstbx.Items[i + 1].ToString();
currItem = frm2lstbx.SelectedItem.ToString();
frm2lstbx.Items.Insert(i, globalNextItem1.ToString());
MyDAL.UpdateData1(currItem, globalNextItem1);
MyDAL.UpdateData1(globalNextItem1, currItem);
frm2lstbx.Items.RemoveAt(i + 2);
}
}
}
In MYDAL class I have below method for Updatedata in SQL Server...
public static void UpdateData1(string UpdatedItem, string OldItem)
{
string strSql = #" Update tbl_srs set [Description]='" + UpdatedItem + "' where [Description]='" + OldItem + "'";
Utils.ExecuteSql(strSql);
}
Note: Utils is another class library which contains methods for executing sql commands and so on..
My problem is: SQL Server updating row below of the selected item correctly.. but selected item overwrite the same item... that's why entire listbox updated with same values of selected item...
For ex: I have taken i=0 indexed selected item...
When I click down button control goes to i=1 nd it will now selected item, so in SQL Server I updated i=1 indexed item with i =0 item..it updated correctly
after i=0 indexed item may not updated correctly..it overwrite the same value ,which is in i=0Indexed item.
I have a product page that on click event brings a selected product with price from a sql data source and it also allows the user to add a quantity. I send it to a list box on a new page called cart and display it with this which s part of the cartitem class
public string Display()
{
return cproduct.Description + " (" + cquantity.ToString() + " at " + cproduct.UnitPrice.ToString("c")
+ " each) " ;
}
and this from the cart.aspx.cs page
public partial class Cart : System.Web.UI.Page
{
CartItemList cart;
protected void Page_Load(object sender, EventArgs e)
{
cart = CartItemList.GetCart();
if (!IsPostBack)
{
this.DisplayCart();
}
}
protected void DisplayCart()
{
lstCart.Items.Clear();
CartItem item;
for (int i = 0; i < cart.count; i++)
{
item = cart[i];
lstCart.Items.Add(item.Display());
}
}
I want to add to this is a total of each item at the end (Unit price * Quantity).
But what I can't seem to figure out is where exactly would I add this. I have product.aspx page and a cart.aspx page with the list box and the behind the code page for each.. Product page is a simple drop down list from a sql database and a text box to enter the quantity in. I've got a cartitem, cartitemlist, and product class. I'd post more code but I figured that would not be necessary but I can if needed. Any help would be so very appreciated because I'm going grey over it. Thanks
Lynda
Well you could just tack it on to the display method:
public string Display()
{
return cproduct.Description + " (" + cquantity.ToString() + " at " + cproduct.UnitPrice.ToString("c") + " each) Total " + (cquantity*cproduct.UnitPrice).ToString("c") ;
}
Though honestly I am a bit confused as to why you are using a list box for this? It just seems an odd choice. I'd probably do a listview with a table or a datalist, which would give you a lot of functionality for free (like the ability to edit quantities and delete lines).