I have a form that is bound directly with a table adapter created with the designer. I also created a list box with the key value from each record. My thought is to allow the user to click on a specific key to load the desired record in the edit screen. I can access the list entry on click, but I don't know what command to use to move to the correct row.
I am wondering if it is really worth using the bound forms like this or just do it in code, similar to how I created the list box. Any suggestions? See my code below:
public partial class Customer : Form
{
public string dbConString = "Data Source=localhost\\BALLMILL;Initial Catalog=Ballmill;Integrated Security=True";
public SqlConnection dbCon = null;
public SqlDataReader dbRdr = null;
public SqlCommand dbCommand = null;
public Customer()
{
InitializeComponent();
}
private void cUSTOMERBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.cUSTOMERBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.bML_WMS245GDataSet);
}
private void Customer_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'bML_WMS245GDataSet.CUSTOMER' table. You can move, or remove it, as needed.
this.cUSTOMERTableAdapter.Fill(this.bML_WMS245GDataSet.CUSTOMER);
SqlConnection dbCon = new SqlConnection(dbConString);
SqlDataReader rdrCustomers = null;
try
{
dbCon.Open();
SqlCommand sqlCustomers = new SqlCommand("SELECT CustomerCode FROM Customer", dbCon);
rdrCustomers = sqlCustomers.ExecuteReader();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString(), "Error accessing database");
return;
}
while (rdrCustomers.Read())
{
listCustomers.Items.Add(rdrCustomers["CustomerCode"].ToString());
}
}
private void listCustomers_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show(listCustomers.SelectedItem.ToString(), listCustomers.SelectedIndex.ToString());
}
}
I found the answer after searching through the designer code.
cUSTOMERBindingSource.Position = listCustomers.SelectedIndex;
This automatically moves the navigator to the selected row.
Related
i'm currently working on my C# "WindowForm" Project and i want to know if it's possible to link a textbox from any form to a database and update the textbox content from time to time so the users of my application would get up to dates information of what i'm willing to post in this form (textbox).
thank you,
If you want to refresh the text in real time from a datatable, you can try SqlDependency.
The following is a simple demo.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
System.Data.SqlClient.SqlConnection conn = null;
System.Data.SqlClient.SqlCommand command = null;
// Set connection string
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder
{
DataSource = #"datasource name",
// set database
InitialCatalog = #"catalog name",
// access the database using the existing windows security certificate
IntegratedSecurity = true
};
private void Form1_Load(object sender, EventArgs e)
{
conn = new System.Data.SqlClient.SqlConnection(builder.ConnectionString);
command = conn.CreateCommand();
command.CommandText = "select text from dbo.TableText where id<>20 order by id desc ";
// Start
SqlDependency.Start(builder.ConnectionString);
// Get data
GetData();
}
private void GetData()
{
command.Notification = null;
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(sqlDependency_OnChange);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
System.Data.DataSet ds = new DataSet();
adapter.Fill(ds, "test");
string text = ds.Tables["test"].Rows[0]["Text"].ToString();
textBox.Text = text;
}
}
void sqlDependency_OnChange(object sender, SqlNotificationEventArgs e)
{
// Because it is a child thread, you need to update the ui with the invoke method.
if (this.InvokeRequired)
{
this.Invoke(new OnChangeEventHandler(sqlDependency_OnChange), new object[] { sender, e });
}
else
{
SqlDependency dependency = (SqlDependency)sender;
dependency.OnChange -= sqlDependency_OnChange;
// After the notification, the current dependency is invalid, you need to re-get the data and set the notification.
GetData();
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Clear resource
SqlDependency.Stop(builder.ConnectionString);
conn.Close();
conn.Dispose();
}
}
For more info about SqlDependency, you can refer to Detecting Changes with SqlDependency.
Hope this can help you.
I am trying to overwrite a content in an label several times by always clicking the same button. Unfortunately, I only know how to override it once.
The problem I am facing is that the data in the label are from an SQL database and it only displays the data with ID = 1 in the label.
This is my code:
MySqlConnection conn = new MySqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString); // Connectionstring to the database
public MainWindow()
{
InitializeComponent();
}
private void btContinue_Click(object sender, RoutedEventArgs e)
{
try
{
conn.Open();
MySqlCommand cmd = new MySqlCommand("SELECT l_question from l_liescale", conn);
MySqlDataAdapter adp = new MySqlDataAdapter(cmd);
DataSet ds = new DataSet();
lbquestion.Content = cmd.ExecuteScalar(); //here I get the data into the label
}
catch (MySqlException ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
conn.Close();
}
}
}
Is there a way to display every data record from the database in one label and always overwriting it with the next record by clicking the button?
You should use ExecuteReader() instead of ExecuteScalar() to retrieve collection of data.
StringBuilder sb = new StringBuilder();
using(var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var question = reader[0].ToString();
sb.AppendFormat("Q: {0}\n", question); // use any other format if needed
}
}
lbquestion.Content = sb.ToString();
But the better way is to use ItemsControl or ListBox or other list-controls.
If you want to iterate by clicking the button you can retrieve all records to the memory and then iterate it in the event handler:
private readonly List<string> _questions;
private int currentIndex = -1;
public MainWindow()
{
InitializeComponent();
_questions = GetQuestionsByDataReader();
}
private void btContinue_Click(object sender, RoutedEventArgs e)
{
if(currentIndex < _questions.Count)
{
lbquestion.Content = _questions[++currentIndex];
}
}
I want to add new values to MySql database from dataGridView1. The code itself appears to be correct, no errors in Visual Studio 2012, but there is no data inserted in my db.
Here's the code I'm using:
private void button2_Click(object sender, EventArgs e)
{
confirm exec = new confirm();
}
public class confirm
{
public void method(DataGridViewCellEventArgs f)
{
DataGridView dataGridView1 = new DataGridView();
Label label1 = new Label(); // contains User ID which is used for payer_code
Label label6 = new Label(); // contains current dayTime
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if ((bool)dataGridView1.Rows[f.RowIndex].Cells["paidDataGridViewTextBoxColumn"].Value == true)
{
try
{
string MyConnectionString = "Server=localhost; Database=contractsdb; Uid=root; Pwd=";
MySqlConnection connection = new MySqlConnection(MyConnectionString);
MySqlCommand cmd = new MySqlCommand();
cmd = connection.CreateCommand();
connection.Open();
cmd.CommandText = "INSERT INTO payments(pay_name, pay_code, payer_code, pay_sum, pay_date)VALUES(#pay_name, #pay_code, #payer_code, #pay_sum, #pay_date)";
cmd.Parameters.AddWithValue("#pay_name", dataGridView1.Rows[f.RowIndex].Cells["contractnameDataGridViewTextBoxColumn"].Value);
cmd.Parameters.AddWithValue("#pay_code", dataGridView1.Rows[f.RowIndex].Cells["contractcodeDataGridViewTextBoxColumn"].Value);
cmd.Parameters.AddWithValue("#payer_code", label1.Text);
cmd.Parameters.AddWithValue("#pay_sum", dataGridView1.Rows[f.RowIndex].Cells["sumDataGridViewTextBoxColumn"].Value);
cmd.Parameters.AddWithValue("#pay_date", label6.Text);
cmd.ExecuteNonQuery();
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
}
I think you are misunderstanding something about OOP. Do it like this:
your confirm class method should also have the reference of datagridview1 (you are creating an empty datagridview so it never goes even into the foreach loop)
public void method(DataGridView datagridview1) //remove your first argument, you don't need it anymore
{
//delete the line "DataGridView dataGridView1 = new DataGridView();"
//and keep the rest of the code as it is
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if(row.Cells["paidDataGridViewTextBoxColumn"].Value == true) //it will check every row, and you don't need "DataGridViewCellEventArgs" argument now
{
try
{
//your code, it will be same here
}
}
}
for calling the method:
(use the same button_click event as you were doing)
private void button2_Click(object sender, EventArgs e)
{
confirm exec = new confirm();
exec.method(datagridview1); //pass "datagridview1" reference
}
It will pass the reference of your original datagridview1 to the confirm class.
I have been able to bind the data in my MS Access database to textboxes on a form. But when I update the data, no changes are made to the database. I made a simplified example to demonstrate my problem. The form contains only two textboxes (txtFirstName and txtLastName) and two buttons (Save and Refresh). Refresh just reloads the DataTable from the database. I load the record with ID 1 and try to update. The code is below. I know that the updates to the textboxes also update the DataTable. However, the Update function of the data adapter does nothing because no Update commands are generated by the OleDbCommandBuilder. Can anyone tell me what I am doing wrong?
Thanks so much!
// Global data
public DataTable CaseTable = new DataTable();
private OleDbCommand dbCmd;
private OleDbDataAdapter adapter;
private OleDbCommandBuilder builder;
private OleDbConnection dbConn = null;
public frmCustomer()
{
InitializeComponent();
CaseTable.Columns.Add("ID");
CaseTable.Columns.Add("FirstName");
CaseTable.Columns.Add("LastName");
this.txtFirstName.DataBindings.Add("Text", CaseTable, "FirstName"); //, true, DataSourceUpdateMode.OnPropertyChanged);
this.txtLastName.DataBindings.Add("Text", CaseTable, "LastName"); //, true, DataSourceUpdateMode.OnPropertyChanged);
}
private void frmCustomer_Load(object sender, EventArgs e)
{
dbConn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Customers.accdb");
dbCmd = new OleDbCommand("Select * From Customers Where ID = 1", dbConn);
adapter = new OleDbDataAdapter(dbCmd);
builder = new OleDbCommandBuilder(adapter);
RefreshForm();
}
private void RefreshForm()
{
CaseTable.Clear();
adapter.Fill(CaseTable);
if (CaseTable.Rows.Count < 1)
{
MessageBox.Show("Item Not Found", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
private void btnSave_Click(object sender, EventArgs e)
{
if (adapter.Update(CaseTable) < 1)
MessageBox.Show("No updates");
}
private void btnRefresh_Click(object sender, EventArgs e)
{
RefreshForm();
}
I don't know why this works, but here is how I fixed my problem. At the end of RefreshForm I add the line
CaseTable.Rows[0].BeginEdit();
and at the beginning of the Save event handler I add the line
CaseTable.Rows[0].EndEdit();
Now the changes are carried back to the database. I'm not sure why none of the online references I found made reference to this.
I have looked all over the place but I cant seem to get this to work.
I am trying to update an Access database from a DataGridView. The loading of the database to the grid works fine. I used the instructions described in this site.
However, to update the database based on changes made to the DataGridView, I used the command dataAdapter.Update(datatable);, but depending on the placement (next to this code) the code runs but the database does not update. If I put it in a button it throws an exception "syntax error in insert into statement".
Other question: Should I close the connection variable after loading the DataGridView? If so, should I reopen it to perform the update and then reclose it? How does that work?.
Any help would be greatly appreciated.
EDIT: Putted whole class as Tim asked.
public partial class Pantalla_Proyecto : Form
{
private Inicio Inicio;
private List<string> Logueado;
private OleDbConnection conn;
private OleDbDataAdapter Adaptador;
private DataTable Tabla;
private BindingSource Bsource;
private OleDbCommandBuilder Builder;
public Pantalla_Proyecto(Inicio Inicio, List<string> Logueado)
{
this.Inicio =Inicio;
this.Logueado = Logueado;
InitializeComponent();
}
private void Pantalla_Proyecto_Load(object sender, EventArgs e)
{
}
private void importarCDPToolStripMenuItem_Click(object sender, EventArgs e)
{
Importar_CDP Importar_CDP = new Importar_CDP();
Importar_CDP.Show();
}
private void importarListasToolStripMenuItem_Click(object sender, EventArgs e)
{
WindowsFormsApplication1.Formularios.Lista_Lazos.Importar_Listas1 Importar_Listas = new WindowsFormsApplication1.Formularios.Lista_Lazos.Importar_Listas1();
Importar_Listas.Show();
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
}
private void flowLayoutPanel2_Paint(object sender, PaintEventArgs e)
{
}
private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string sql = "Select * From ["+TABLE (THIS IS A STRING I GET FROM PREVIOUS FORM)+"]";
conn = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=proyectos\" + Location(this is a string i get on the previous form) + ".mdb;User Id=admin;Password=;");
conn.Open();
// Extraemos info de mi database y la meto en un datatable
Adaptador = new OleDbDataAdapter(sql, conn);
Builder = new OleDbCommandBuilder(Adaptador);
Tabla = new DataTable();
Adaptador.Fill(Tabla);
// LLENO EL DATA GRID VIEW
Bsource = new BindingSource();
Bsource.DataSource = Tabla;
dataGridView1.DataSource = Bsource;
dataGridView1.Dock = DockStyle.Fill;
Adaptador.Update(Tabla);//if i put it here nothing happens
conn.Close();
}
private void dataGridView1_Validating(object sender, CancelEventArgs e)
{
}
private void button1_Click_1(object sender, EventArgs e)
{
conn.Open();
Adaptador.Update(Tabla);//IF i put it here i get an exception
conn.Close();
}
To elaborate, as per OP's request, on the using statement, let's take the comboBox1_SelectedIndexChanged method:
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string sql = "Select * From ["+TABLE (THIS IS A STRING I GET FROM PREVIOUS FORM)+"]";
using (conn = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=proyectos\" + Location(this is a string i get on the previous form) + ".mdb;User Id=admin;Password=;"))
{
conn.Open();
// Extraemos info de mi database y la meto en un datatable
Adaptador = new OleDbDataAdapter(sql, conn);
// Remove the OleDbCommandBuilder
Tabla = new DataTable();
Adaptador.Fill(Tabla);
// LLENO EL DATA GRID VIEW
Bsource = new BindingSource();
Bsource.DataSource = Tabla;
dataGridView1.DataSource = Bsource;
dataGridView1.Dock = DockStyle.Fill;
// ** NOTE:
// At this point, there's nothing to update - all that
// has happened is that you've bound the DataTable
// to the DataGridView.
Adaptador.Update(Tabla);//if i put it here nothing happens
} // Your connection will be closed at this point when the using
// statement goes out of scope.
}
UPDATE
MSDN says "When you create a new instance OleDbCommandBuilder, any existing OleDbCommandBuilder associated with this OleDbDataAdapter is released."
However, if you want to get away from the OleDbCommandBuilder completely, you can do so (I updated my code above to do just that). Since you believe you're having issues with special characters, it's probably worthwhile to do it this way.
Something like this should help - you'll have to modify the update command based on what your table columns are:
private void button1_Click_1(object sender, EventArgs e)
{
conn.Open();
Adaptador.UpdateCommand = "<Your SQL here>" // I.e., UPDATE [TABLE] SET....
try
{
Adaptador.Update((DataTable)Bsource.DataSource);
}
catch (Exception ex)
{
// Do something with the exception
}
}
This code is a slightly modified version of what MSDN has:
How to: Bind Data to the Windows Forms DataGridView Control
Note that they use a SqlDbCommandBuilder in the example, but the overall principle remains the same.
Based on David-W-Fenton's comment, you might want to do your connection and dataadapter initializations in the Form_Load event, and then close the connection on Form_Closing event.
First thing to check is the runtime path of the Access file that you're actually updating.
If you're using VS.NET, that the MDB file is part of your project, and that the "Copy Local" option is set to true on the MDB file, then it could just be that every time you run your program you overwrite the updates from the last execution.
I'm just mentioning because I've been bitten by this one ;-)
Cheers