i create a winform application with a listbox datasource that come from ms access database. the problem is when i click the Update button the listbox is not getting update. example i change the "ITEM1" to ITEM2", its just not working but the database do because i execute a command that will update the database. i need to reload(re-open) my application then on that time i will see my modification. how do i update the listbox? i've read something about this problem before but i dont understand about it clearly..i wish someone could help me out..
private BindingList<PRODUCTLIST> _productlist;
public Form1()
{
InitializeComponent();
}
public class PRODUCTLIST
{
public string ID { get; set; }
public string ITEM { get; set; }
public string ITEM_DESC { get; set; }
}
private static OleDbConnection GetConnection()
{
OleDbConnection mdbConn = new OleDbConnection();
try
{
string connectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=shop.mdb;Jet OLEDB:Database Password=xxxxx;";
mdbConn = new OleDbConnection(connectionString);
mdbConn.Open();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return mdbConn;
}
private void Form1_Load(object sender, EventArgs e)
{
// make ID textbox un editable
textBoxID.Enabled = false;
_productlist = new BindingList<PRODUCTLIST>();
string strSQL = "SELECT * FROM Item ORDER BY ITEM";
OleDbDataAdapter myCmd = new OleDbDataAdapter(strSQL, GetConnection());
DataSet dtSet = new DataSet();
myCmd.Fill(dtSet, "Item");
DataTable dTable = dtSet.Tables[0];
foreach (DataRow dtRow in dTable.Rows)
{
_productlist.Add(new PRODUCTLIST() { ID = dtRow["ID"].ToString(), ITEM = dtRow["ITEM"].ToString(), ITEM_DESC = dtRow["ITEM_DESC"].ToString() });
}
listBox1.DisplayMember = "ITEM";
listBox1.DataSource = _productlist;
//listBox1.DataBindings = _productlist;
listBox1.ValueMember = "ID";
// set the textbox binding and DataSourceUpdateMode to Never because i have other button to add the new item
textBoxID.DataBindings.Add("Text", _productlist, "ID", false, DataSourceUpdateMode.Never);
textBoxITEM.DataBindings.Add("Text", _productlist, "ITEM", false, DataSourceUpdateMode.Never);
textBoxITEMDESC.DataBindings.Add("Text", _productlist, "ITEM_DESC", false, DataSourceUpdateMode.Never);
}
private void buttonUpdate_Click(object sender, EventArgs e)
{
// update data on database
OleDbCommand cmd = new OleDbCommand("UPDATE Item SET ITEM = #ITEM, ITEM_DESC = #ITEM_DESC WHERE ID = #ID", GetConnection());
cmd.Parameters.AddWithValue("#ITEM", textBoxITEM.Text);
cmd.Parameters.AddWithValue("#ITEM_DESC", textBoxITEMDESC.Text);
cmd.Parameters.AddWithValue("#ID", Convert.ToInt32(textBoxID.Text));
cmd.ExecuteNonQuery();
// make the listbox datasource update
//listBox1.Refresh();
//listBox1.DataSource = null;
//listBox1.DataSource = _productlist;
//_productlist = new BindingList<PRODUCTLIST>();
//string strSQL = "SELECT * FROM Item ORDER BY ITEM";
//OleDbDataAdapter myCmd = new OleDbDataAdapter(strSQL, GetConnection());
//DataSet dtSet = new DataSet();
//myCmd.Fill(dtSet, "Item");
//DataTable dTable = dtSet.Tables[0];
//foreach (DataRow dtRow in dTable.Rows)
//{
// _productlist.Add(new PRODUCTLIST() { ID = dtRow["ID"].ToString(), ITEM = dtRow["ITEM"].ToString(), ITEM_DESC = dtRow["ITEM_DESC"].ToString() });
//}
//listBox1.DisplayMember = "ITEM";
//listBox1.DataSource = _productlist;
////listBox1.DataBindings = _productlist;
//listBox1.ValueMember = "ID";
}
The way you are doing it you need to clear and repopulate your list box.
You should extract that code as a method from the FormLoad event handler and call it after you run the update query.
It's hard to tell which way you want to go. Based on what you are asking.
What you should be doing is making your products data table a private property. Creating and open it up and bind to the list box.
Then your update function should be changing the datatable. Then you'd see the changes in your list box. The thing to appreciate though is until you flush the changes (ApplyChanges method) you have made to the datatable back to the database server all you've done is change a local copy of the data.
That can be good and bad. Depends on what you want to do with multiple users updating products at the same time.
So you've got datatable with a local copy and shown it.
Then you've updated the table you copied, and now your copy is out of step.
Exactly the same problem you would have, if you ran up another copy of your app and changed one of the records you'd already shown in the first one.
Related
Here is my code :
public partial class Form1 : Form
{
SqlCommandBuilder cmbl;
string con = "Data Source=localhost;Initial Catalog=db;Persist Security Info=True;User ID=sa;Password=1234";
SqlDataAdapter sdaHFP;
string QueryDgvHFP = "SELECT * FROM HFP";
DataTable dtHFP;
SqlConnection cn;
public Form1()
{
InitializeComponent();
}
private void Form1(object sender, EventArgs e)
{
sdaHFP = new SqlDataAdapter(QueryDgvHFP, con);
dtHFP = new DataTable();
sdaHFP.Fill(dtHFP);
foreach (DataRow item in dtHFP.Rows)
{
int n = dgvHFP.Rows.Add();
dgvHFP.Rows[n].Cells[0].Value = item["HFP"].ToString();
dgvHFP.Rows[n].Cells[1].Value = item["YearPeriod"].ToString();
if (item["Active"].ToString() == "Y")
{
dgvHFP.Rows[n].Cells[2].Value = true;
}
else
{
dgvHFP.Rows[n].Cells[2].Value = false;
};
dgvHFP.Rows[n].Cells[3].Value = item["ID"].ToString();
}
}
That's was load data from Sql Query to DataGridView, And I was add a Button for execute update or insert within this code :
private void btUpdate_Click(object sender, EventArgs e)
{
try
{
cmbl = new SqlCommandBuilder(sdaHFP);
sdaHFP.Update(dtHFP);
MessageBox.Show("Success", "Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
When I Update / Insert data in DataGridView and click that Update Button, a Success MessageBox appears, but the Data in Database not Updated nor Inserted
Please help me solve this problem, why the Update Button doesn't work?
Thank You Very Much.
You should bind the DataGridView to DataTable, then when you change a cell value or add or remove rows, the changes apply on DataTable. Then you can save data table changes using a TableAdapter:
this.dataGridView1.DataSource = dataTable;
Note: To store true/false or Yes/No values, it's better to use bit data type in sql server. But in the below example I supposed you need to store values as Y/N as nvarchar(50) and I setup a DataGridViewCheckBoxColumn to support editing a string column.
Example
Suppose we have a table Table1:
Column1: int, primary key
Column2: nvarchar(50), Allows Null, Containing Y or N as vaule
And we want to edit data of Table1 in a DataGridView:
Here is the code you can use to load and edit and save data:
private DataTable table;
private SqlDataAdapter dataAdapter;
private void sampleForm_Load(object sender, EventArgs e)
{
var command = "SELECT * FROM Table1";
var connection = #"Your connection string";
table = new DataTable();
dataAdapter = new SqlDataAdapter(command, connection);
var commandBuilder = new SqlCommandBuilder(dataAdapter);
dataAdapter.Fill(table);
//Set false as default value for Column2
table.Columns["Column2"].DefaultValue = false;
var column1 = new DataGridViewTextBoxColumn();
column1.Name = "Column1";
column1.DataPropertyName = "Column1";
var column2 = new DataGridViewCheckBoxColumn();
column2.Name = "Column2";
column2.DataPropertyName = "Column2";
column2.TrueValue = "Y";
column2.FalseValue = "N";
this.dataGridView1.Columns.Add(column1);
this.dataGridView1.Columns.Add(column2);
//Bind grid to table
this.dataGridView1.DataSource = table;
}
private void saveButton_Click(object sender, EventArgs e)
{
//Save data
this.dataGridView1.EndEdit();
dataAdapter.Update(table);
}
im making a wpf wherein one combobox populates depending on another combobox. however, only one combobox populated.
this is my code below.
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
this.Load += Form4_Load;
}
string connstring = ("Server=localhost;Port=5432;User Id=postgres;Password=021393;Database=postgres;");
private void Form4_Load(object sender, EventArgs e)
{
string query = "SELECT * FROM data_organsystem";
fillCombo(comboBox3, query, "name", "id");
comboBox3_SelectedIndexChanged(null, null);
}
private void fillCombo(ComboBox combo, string query, string displayMember, string valueMember)
{
NpgsqlConnection conn = new NpgsqlConnection(connstring);
NpgsqlCommand cmd = new NpgsqlCommand(query, conn);
NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
combo.DataSource = dt;
combo.DisplayMember = displayMember;
combo.ValueMember = valueMember;
}
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
int val;
Int32.TryParse(comboBox3.SelectedValue.ToString(), out val);
string query = "SELECT * FROM data_symptom WHERE organ_system_id = " + val;
fillCombo(comboBox4, query, "name", "id");
}
}
}
if you have any idea on how to edit this code, it would be a big help. thanks!
You will get error when you executing method comboBox3_SelectedIndexChanged àt the line
Int32.TryParse(comboBox3.SelectedValue.ToString(), out val);
Because comboBox3.SelectedValue is null if no item selected in the ComboBox, I didn't see in your code that you selected some items before calling comboBox3_SelectedIndexChanged first time.
Because method comboBox3_SelectedIndexChanged executed inside Form.Load eventhandler exception wasn't shown. Check this: https://stackoverflow.com/a/3209813/1565525.
That is why you didn't get any errors
You need to check SelectedValue for null before using it
If(this.comboBox3.SelectedValue is null)
{
this.comboBox4.DataSource = null; //Remove all items if nothing selected
}
else
{
Int32 val= (Int32)this.ComboBox3.SelectedValue;
string query = "SELECT id, name FROM data_symptom WHERE organ_system_id = " + val;
fillCombo(this.comboBox4, query, "name", "id");
}
Because you using DataBinding when filling ComboBox with items it will be logically to use SelectedValueChanged event handler
private void comboBox3_SelectedValueChanged(object sender, EventsArgs e)
{
//same code
}
You never add comboBox4 to your form. comboBox3 is added via constructor but comboBox4 is created and added to nowhere.
I have a method in my DAL which populates a ComboBox from a DataTable. ComboBox displays correctly and I have a 'Save' button which saves back to my DB, job's a good'un...
public string populateLookUp(ref System.Windows.Forms.ComboBox Combo, string Id)
{
SqlCommand _comm = new SqlCommand();
_comm.Parameters.AddWithValue("#id", Id);
_comm.CommandText = "SELECT [name] FROM dbo.fnGetName(#id) ORDER BY [name]; ";
_comm.Connection = _conn;
_comm.CommandTimeout = _command_timeout;
DataTable dt = new DataTable();
try
{
SqlDataReader myReader = _comm.ExecuteReader();
dt.Load(myReader);
}
catch
{
MessageBox.Show("Unable to populate Name LookUp");
}
Combo.DataSource = dt;
Combo.DisplayMember = "name";
foreach (DataRow dr in dt.Rows)
{
if (dr["company_int_name"].ToString() == Contract.Company_trans_Selling_Entity.ToString())
{
Combo.SelectedItem = dr["company_int_name"].ToString();
}
}
return "";
}
However obviously when I re-edit the record, this method is called again. Ok, I now have written a ForEach loop which iterates over my DataTable and compares the string in the rows to the Name I am passing in. If the two match I'm setting the
Combo.SeletedItem = dr["company_int_name"].ToString();
However the selectedItem is not being set, presumably I'll need some sort of event to notify the property changed?
Thanks
You have to bind the Combo Box with the ValueMember function and can reflect the combo box with the matched string value as selected
public string populateLookUp(ref System.Windows.Forms.ComboBox Combo, string Id)
{
SqlCommand _comm = new SqlCommand();
_comm.Parameters.AddWithValue("#id", Id);
_comm.CommandText = "SELECT [name] FROM dbo.fnGetName(#id) ORDER BY [name]; ";
_comm.Connection = _conn;
_comm.CommandTimeout = _command_timeout;
DataTable dt = new DataTable();
try
{
SqlDataReader myReader = _comm.ExecuteReader();
dt.Load(myReader);
}
catch
{
MessageBox.Show("Unable to populate Name LookUp");
}
Combo.DataSource = dt;
Combo.DisplayMember = "name";
Combo.ValueMember = "name";
foreach (DataRow dr in dt.Rows)
{
if (dr["company_int_name"].ToString() == Contract.Company_trans_Selling_Entity.ToString())
{
Combo.SelectedValue = dr["company_int_name"].ToString();
}
}
return "";
}
I'm trying to make a windows application for Library Management.
I'm trying to bind the data generated by SQLQuery to comboBoxBranch, but its only showing --Select-- in the options. Is there anything wrong with following code?
private void Form1_Load(object sender, EventArgs e)
{
bindBranch();
}
private void bindBranch()
{
OleDbCommand SQLQuery = new OleDbCommand();
string sqlQueryString = "Select br_id from branch";
DataTable data = null;
SQLQuery.Connection = null;
OleDbDataAdapter dataAdapter = null;
try
{
SQLQuery.CommandText = sqlQueryString;
SQLQuery.Connection = database;
data = new DataTable();
dataAdapter = new OleDbDataAdapter(SQLQuery);
dataAdapter.Fill(data);
comboBoxBranch.DisplayMember = "br_id";
DataRow dr = data.NewRow();
dr[0] = "--Select--";
data.Rows.InsertAt(dr, 0);
comboBoxBranch.DataSource = data;
}
catch (Exception ex)
{
}
}
Is there anything else I need to add to some other pages to make this work?
You can bind data like this.
comboBoxBranch.DataSource = new BindingSource { DataSource = data };
comboBoxBranch.DisplayMember = "br_id";
comboBoxBranch.ValueMember = //> something else
string Sql_type = "select property_type_id,type_name from lk_tb_property_type";
OleDbCommand cmd_type = new OleDbCommand(Sql_type, con);
OleDbDataReader DR_two = cmd_type.ExecuteReader();
DataTable table_two = new DataTable();
table_two.Load(DR_two);
//begin adding line
DataRow row_two = table_two.NewRow();
row_two["type_name"] = "Select Poperty Name";
row_two["property_type_id"] = 0;
table_two.Rows.InsertAt(row_two, 0);
//end adding a line
combo_type.DataSource = table_two;
combo_type.DisplayMember = "type_name";
combo_type.ValueMember = "property_type_id";
combo_type.Text = "Select Poperty Name";
with this code i am fetching values for a combobox from database.now suppose my combobx is having 2 items named A and B..I have one more combobox...now what i want is that when user chooses item A from combobox the second combobox should display data related to item A when user chooses item B then data related to item B should be displayed...sohow to achieve this...??
you can fetch the data and bind it to combobox2 on SelectedIndexChanged event of combobox1
private void combobox1_SelectedIndexChanged(object sender, EventArgs e)
{
var val = combobox1.SelectedValue;
// fetch data from database
// you need to set SQL parameter value form SelectedValue
combobox2.DataSource = ...; // set this value
combobox2.DisplayMember = .....; // set this value
combobox2.ValueMember = ....; // set this value
}
Please assign an event SelectedIndexChanged and AutoPostBack = true is this is a web Application in C#
In SelectedIndexChanged of combo box write your code. and make AutoPostBack = true of your combobox
You can do like these steps.
First, bind data to comboBox1 (I suppose that your first ComboBox named "comboBox1", and your form named "Form1"), please make sure that your SQL query command is correct for comboBox1
private void Form1_Load(object sender, EventArgs e)
{
OleDbConnection con = new OleDbConnection(constr);
con.Open();
string Sql_cust_name = "select customer_name from tb_customer";
OleDbCommand cmd_cust_name = new OleDbCommand(Sql_cust_name, con);
OleDbDataReader DR_cust_name = cmd_cust_name.ExecuteReader();
DataTable table_cust_name = new DataTable();
table_cust_name.Load(DR_cust_name);
DataRow row_cust_name = table_cust_name.NewRow();
row_cust_name["customer_name"] = "Select Customer Name";
table_cust_name.Rows.InsertAt(row_cust_name, 0);
combo_cust_name.DataSource = table_cust_name;
combo_cust_name.DisplayMember = "customer_name";
combo_cust_name.ValueMember = "customer_name";
combo_cust_name.Text = "Select Customer Name";
con.Close();
}
Next, bind data to comboBox2 (I suppose that your second ComboBox named "comboBox2"), you have to get comboBox1.SelectedValue whenever it is changed, this value will be used in the filtering for data in comboBox2, so you have to handle SelectedIndexChanged event for comboBox1, please make sure that you have this code somewhere in your project: this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
To bind data to comboBox2 (I suppose that your second ComboBox named "comboBox2"), you have to get comboBox1.SelectedValue whenever it is changed
private void combo_cust_name_SelectedIndexChanged(object sender, EventArgs e)
{
OleDbConnection con = new OleDbConnection(constr);
con.Open();
string customerName = "";
if (combo_cust_name.SelectedValue.GetType() == typeof(DataRowView))
{
DataRowView selectedRow = (DataRowView)combo_cust_name.SelectedValue;
customerName = selectedRow["customer_name"].ToString();
}
else
{
customerName = combo_cust_name.SelectedValue.ToString();
}
string Sql2 = "SELECT customer_number FROM tb_customer WHERE customer_name = '" + customerName + "'";
OleDbCommand cmd_type = new OleDbCommand(Sql2, con);
OleDbDataReader DR_two = cmd_type.ExecuteReader();
DataTable table_two = new DataTable();
table_two.Load(DR_two);
DataRow row_two = table_two.NewRow();
row_two["customer_number"] = "Select Customer Number";
table_two.Rows.InsertAt(row_two, 0);
comboBox2.DataSource = table_two;
comboBox2.DisplayMember = "customer_number";
comboBox2.ValueMember = "customer_number";
comboBox2.Text = "Select Customer Number";
}
Please correct the SQL query command as you want, but don't forget to put a correct filter like my sample code above.