Sending data between 2 forms - c#

I have form1 with datagridview and a button. When i click a button, a new form opens up where there is a textbox and also a button. In this textbox i can write query and with a click of a button query results are shown in form1 datagridview. The problem is that it opens up another instance of form1 , but i would like that form1 stays open the whole time and only records in datagridview are changing, according to the query input in form2. Both form1 and form2 needs to be opened and active when called.
Here is my code:
//FORM 1
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var queryForm = new Form2();
queryForm.Show(this);
}
//FORM 2
public Form2()
{
InitializeComponent();
}
private SqlConnection Conn;
private void Form1_Load(object sender, EventArgs e)
{
Conn = new SqlConnection(#"Data Source=srvr;Initial Catalog =db; User ID =user; Password =pass");
}
private void btnExecute_Click(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
frm1.Show(this);
frm1.Activate();
SqlCommand cmd = new SqlCommand();
cmd.Connection = Conn;
cmd.CommandText = txtQuery.Text;
try
{
Conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
frm1.dataGridView1.Columns.Clear();
frm1.dataGridView1.Rows.Clear();
if (reader.HasRows)
{
DataTable schema = reader.GetSchemaTable();
int field_num = 0;
foreach (DataRow schema_row in schema.Rows)
{
int col_num = frm1.dataGridView1.Columns.Add(
"col" + field_num.ToString(),
schema_row.Field<string>("ColumnName"));
field_num++;
frm1.dataGridView1.Columns[col_num].AutoSizeMode =
DataGridViewAutoSizeColumnMode.AllCells;
}
object[] values = new object[reader.FieldCount];
while (reader.Read())
{
reader.GetValues(values);
frm1.dataGridView1.Rows.Add(values);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error executing command.\n" + ex.Message);
}
finally
{
Conn.Close();
}
}

Well, since you are calling Form1 frm1 = new Form1(); - what else did you expect than opens up another instance of form1 ? - Why should new Form1() not produce another instance?
You will need to get the reference of the already created Form1.
See this for example
Find the open forms in c# windows application
When you found it you can activate it for example:
var frm1 = Application.OpenForms[0];
//frm1.Show(this); <- don't need to call Show since its already open
frm1.Activate();
Also you should change your btnExecute_Click to this.
private void btnExecute_Click(object sender, EventArgs e)
{
var frm1 = Application.OpenForms[0] as Form1; //find `Form1` like you want, I only take [0]
//always create a new instance of SqlConnection here and dispose it with the using Keyword
//don't use a private field to try to keep the Connection, let the internal Connection pool handle that case
using (var con = new SqlConnection(#"Data Source=srvr;Initial Catalog =db; User ID =user; Password =pass"))
{
try
{
con.Open();
//clean up, Command/Reader with using keyword
using (var cmd = con.CreateCommand())
{
cmd.CommandText = txtQuery.Text;
using (SqlDataReader reader = cmd.ExecuteReader())
{
//read data
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error executing command.\n" + ex.Message);
}
}
//should activate the `Form1` AFTER the job is done, you can consider if you only want to activate it if the previous Code didn't fail
frm1.Activate();
}
Don't really get what you are doing in your "read_data" routine.
This Code block:
frm1.dataGridView1.Columns.Clear();
frm1.dataGridView1.Rows.Clear();
if (reader.HasRows)
{
DataTable schema = reader.GetSchemaTable();
int field_num = 0;
foreach (DataRow schema_row in schema.Rows)
{
int col_num = frm1.dataGridView1.Columns.Add(
"col" + field_num.ToString(),
schema_row.Field<string>("ColumnName"));
field_num++;
frm1.dataGridView1.Columns[col_num].AutoSizeMode =
DataGridViewAutoSizeColumnMode.AllCells;
}
object[] values = new object[reader.FieldCount];
while (reader.Read())
{
reader.GetValues(values);
frm1.dataGridView1.Rows.Add(values);
}
}
Try if the following is sufficient, replace my comment "//read data" in the above code with this:
frm1.dataGridView1.AutoGenerateColumns = true; //say to automatically create columns, based on the result inside the datatable
frm1.dataGridView1.Columns.Clear();
var dataTable = new DataTable();
dataTable.Load(dataReader); //load the SqlDataReader into the DataTable
frm1.dataGridView1.DataSource = dataTable; //set the dataGridView's DataSource to the dataTable

On button click in form1, you can simply open a new instance of form2 and do your work there and on closing receive that value in form1. Or you can pass the instance of your form1 into form2 via constructor and update form1 from form2. For example:
var isFormClosed = false;
using(form1 frm = new form1())
{
// do something here
frm.ShowDialog();
isFormClosed = true;
}
Or, if you prefer to pass the reference of form1 into form2,
var isFormClosed = false;
using(form1 frm = new form1(this))
{
// do something here
frm.ShowDialog();
isFormClosed = true;
}
Here, in form2, you can simply use the passed reference of form1 to update properties or grids.

Related

Update datagridview from usercontrol using event button click form

I'm try to update datagridview in usercontrol using event buttonclick from another form. But i still can't resolve it.
I have form1, already display usercontrol in panel.
Code from usercontrol like this.
public partial class suppliers : UserControl
{
SqlConnection conn = new SqlConnection(#"Data Source=HENDRICK;Initial Catalog=mydb");
public void displaydata()
{
conn.Open();
DataTable dt = new DataTable();
SqlDataAdapter adp = new SqlDataAdapter("SELECT [id_supplier] as 'ID' ,[nama_supplier] as 'Nama' ,[telepon_supplier] as 'Telepon' ,[alamat_supplier] as 'Alamat' FROM[mydb].[dbo].[supplier]",conn);
adp.Fill(dt);
datagridsuppliers.DataSource = dt;
conn.Close();
}
public suppliers()
{
InitializeComponent();
displaydata();
}
private void btnaddsuppliers_Click(object sender, EventArgs e)
{
Form1 frm = new Form1();
new PopupEffect.transparentBg(frm, new addsuppliers());
}
}
When I click the btnaddsuppliers, the addsuppliers form will appear, that is useful for inserting data.
The code from addsuppliers form like this.
public partial class addsuppliers : Form
{
SqlConnection conn = new SqlConnection(#"Data Source=HENDRICK;Initial Catalog=mydb");
suppliers supp = new suppliers();
void reset_txtbox()
{
txtnama.Text = "";
txttelepon.Text = "";
txtalamat.Text = "";
}
public addsuppliers()
{
InitializeComponent();
}
private void btnadd_Click(object sender, EventArgs e)
{
try
{
conn.Open();
String insertQuery = "insert into [mydb].[dbo].[supplier] ([id_supplier],[nama_supplier],[telepon_supplier],[alamat_supplier]) values (#id,#nama,#telepon,#alamat)";
cmd = new SqlCommand(insertQuery, conn);
cmd.Parameters.AddWithValue("#id", "SP1");
cmd.Parameters.AddWithValue("#nama", txtnama.Text);
cmd.Parameters.AddWithValue("#telepon", txttelepon.Text);
cmd.Parameters.AddWithValue("#alamat", txtalamat.Text);
cmd.ExecuteNonQuery();
conn.Close();
Bunifu.Snackbar.Show(this.FindForm(), "Add Supplier Successfully.", 2000, Snackbar.Views.SnackbarDesigner.MessageTypes.Success);
supp.displaydata();
reset_txtbox();
}
catch
{
Bunifu.Snackbar.Show(this.FindForm(), "Failed,Check database connection.", 2000, Snackbar.Views.SnackbarDesigner.MessageTypes.Error);
}
}
}
}
The problem is when btnadd is clicked, the database has been updated but the datagridview on usercontrol is not updated automatically.
I have tried to use the call displaydata() function to update the DataGridView. But the result of DataGridView remains unchanged or not updated.
Please help to resolve this problem. Thank You.

C# Button with multiple events

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];
}
}

Not able to hold string from one form to other

Able to show the database when c.Show() execute. When i close form 2 and click on the button6 the gridview on form 2 was empty. Any idea how to fix this bug?
Form 1:
private void System_btn_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
Bitmap picture = new Bitmap(openFileDialog1.FileName);
ZoneStatus c = new ZoneStatus();
c.dbname = System.IO.Path.GetFileNameWithoutExtension(openFileDialog1.SafeFileName);
//c.Show();
}
}
private void button6_Click(object sender, EventArgs e)
{
ZoneStatus zoneStatus_form = new ZoneStatus();
zoneStatus_form.Show();
}
Form 2:
public string dbconnection;
public string dbname {get;set;}
private void ZoneStatus_Load(object sender, EventArgs e)
{
dbconnection = #"Data Source=" + dbname + ".db;Version=3;";
SQLiteConnection sqliteCon = new SQLiteConnection(dbconnection);
{
sqliteCon.Open();
// Create new DataAdapter
using (SQLiteDataAdapter a = new SQLiteDataAdapter(
"SELECT * FROM Alarm_Info", sqliteCon))
{
// Use DataAdapter to fill DataTable
DataTable dt = new DataTable();
a.Fill(dt);
dataGridView1.DataSource = dt; // to update my database
}
sqliteCon.Close();
}
}
change "public string dbname" to "public static string dbname".(same with dbconnection if you want to use that variable too.)
let's assume that you have declare your string in from1 and you want to use this string in form2 so your code will look like this.
form1:
public static string dbname;
in form2 create object of form1 and access this variable like this.
form2:
form1 objf1 = new form1();
string str=objf1.dbname;
now you can do whatever you want to do with variable dbname. you can assign to other variable like i did.

Insert DataGridView values into MySql database. c#

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.

How do I pass a string value from a TextBox between Forms?

I have two forms: Form1 which is my app and Form2 which is a login page. I want to pass a value entered into the username textbox (LoginTbox) on Form2 to Form1. This is what I have so far. No error is received, but it seems to be passing nothing. I've tried constructors, but couldn't seem to get that to work either. What am i doing wrong?
Program.cs
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form2 fLogin = new Form2();
if (fLogin.ShowDialog() == DialogResult.OK)
Application.Run(new Form1());
else
Application.Exit();
}
Form2 (Login Form)
public string strVar = string.Empty;
public Form2()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
strVar = loginTbox.Text.ToString();
string _pass = textBox2.Text;
string conStr = "Data Source=CA-INVDEV\\RISEDB01;Initial Catalog=RISEDB01;Integrated Security=True";
string sqlcmd = "select * from accounts where Username=#Username and Password=#Password";
using (SqlConnection conn = new SqlConnection(conStr))
{
conn.Open();
SqlCommand cmd = new SqlCommand(sqlcmd, conn);
cmd.Parameters.AddWithValue("#Username", _username);
cmd.Parameters.AddWithValue("#Password", _pass);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
{
MessageBox.Show("Login Successful");
}
else
{
MessageBox.Show("Login Failed Invalid Credentials. Please try again");
Application.Restart();
}
}
}
Form1 (App)
private void button7_Click(object sender, EventArgs e)
{
if (textBox6.Text != "")
{
Form2 frm = new Form2();
string strValue = frm.strVar;
string Owner = textBox6.Text;
string Time = DateTime.Now.ToString(#"MM\/dd\/yyyy h\:mm tt");
string Serial = textBox4.Text;
string conStr = "Data Source=CA-INVDEV\\RISEDB01;Initial Catalog=RISEDB01;Integrated Security=True";
string sqlcmd2 = "Select * from Sheet1 where Serial#=#Serial#";
string sqlcmd = "UPDATE Sheet1 SET Owner=#Owner, Checked_In=NULL, Checked_Out=#Checked_Out, Modified_By=#Modified_By WHERE Serial#=#Serial#";
using (SqlConnection conn = new SqlConnection(conStr))
{
conn.Open();
SqlCommand cmd = new SqlCommand(sqlcmd, conn);
SqlCommand cmd2 = new SqlCommand(sqlcmd2, conn);
cmd2.Parameters.AddWithValue("#Serial#", Serial);
cmd.Parameters.AddWithValue("#Serial#", Serial);
cmd.Parameters.AddWithValue("#Owner", Owner);
cmd.Parameters.AddWithValue("#Checked_Out", Time);
cmd.Parameters.AddWithValue("#Modified_By", strValue);
SqlDataReader dr = cmd2.ExecuteReader();
if (dr.HasRows)
{
dr.Close();
cmd.ExecuteNonQuery();
conn.Close();
Form1_Load();
}
else
{
dr.Close();
MessageBox.Show("Serial Does Not Exist");
textBox4.Clear();
}
}
}
else
{
MessageBox.Show("Owner was not assigned to asset. Please provide a Owner for this asset");
}
}
You're dealing with two completely separate instances of Form2. Your first instance, which the user used to login, is inaccessible from within Form1. The instance of Form2 that you created inside the button click event in Form1 only has the initial value of string.Empty stored in strVar.
To get it up and working, I'd change your Main method to pass the value you need into the constructor of Form1:
...
if (fLogin.ShowDialog() == DialogResult.OK)
{
Application.Run(new Form1(fLogin.strVar));
}
...
And then modify the constructor of Form1 (which I don't see in your snippet) to accept that argument:
private string userName = string.Empty;
public Form1(string userName)
{
InitializeComponent();
this.userName = userName;
}
Get rid of the separate instance of Form2 inside the button click event in Form1.
As a side FYI, if someone figures out how you're currently passing your textbox values to the database, they may be able to type something like '; DELETE FROM ACCOUNTS; into textBox2.Text and wreak havoc. (I haven't tried this specifically but something similar may work...)
If you're curious at all, look up articles on SQL injection attacks, such as this one.

Categories