How can assign specific timer EventHandler for specific value in c# - c#

I have array of timer.I want timer0 work with 1st dataValue in _dataValues, 2nd timer work with 2nd dataValue in _dataValues, 3rd timer work with 3rd dataValue in _dataValues and etc and also show result in label in windows form.I use System.Windows.Forms.Timer.Here is my code,
void PrepareTimers(List<int> _dataValues)
{
int i = 0;
foreach (int dataValue in _dataValues)
{
timerNames[i] ="timer"+ string.Format("{0}", i);
timer1[i] = new Timer();
t[i] = dataValue.ToString();
a[i] = timer1[i].ToString();
a[i] = t[i];
timer1[i].Tick += new EventHandler(timer_Tick);
timer1[i].Interval = (1000) * (1);
label = new Label();
label.Name = "label_name" + i;
label.Size = new Size(200, 20);
label.Location = new Point(45, 100 + i * 30);
label.TabIndex = i;
label.Visible = true;
this.Controls.Add(label);
dict[timer1[i]] = label;
timer1[i].Enabled = true;
timer1[i].Start();
i++;
}
}
private void timer_Tick =(object sender, EventArgs e)
{
string myconstring = "SERVER=localhost;" + "DATABASE=alicosms;" + "UID=root;" + "PASSWORD=;";
MySqlConnection mycon = new MySqlConnection(myconstring);
i = 0;
string u = "UPDATED";
mycon.Open();
foreach (int dataValue in _dataValues)
{
if (a[i] == dataValue.ToString())
{
MySqlCommand cmd = new MySqlCommand("UPDATE sms_data_bankasia set flag = " + (dataValue.ToString()) + " *2 , sendingstatus = '" + u + "' WHERE flag = " + dataValue.ToString() + " LIMIT 1", mycon);
cmd.ExecuteNonQuery();
Console.WriteLine("row update" + dataValue.ToString());
mycon.Close();
mycon.Open();
string sql = "SELECT count(flag) FROM sms_data_bankasia where sendingstatus='UPDATED' AND flag = " + (dataValue.ToString()) + " *2 group by flag";
MySqlCommand comd = mycon.CreateCommand();
comd.CommandText = sql;
MySqlDataReader dtr = comd.ExecuteReader();
try
{
while (dtr.Read())
{
Timer t = (Timer)sender;
dict[t].Text = dtr[0].ToString() + " program Updated " + dataValue.ToString();
}
dtr.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
i++;
}
mycon.Close();
}
But it update 4 row in per sec and every EventHandler work with every dataValue.I want 1st timer update 1 row in 1 sec and show in label that 1row update with 1st dataValue and 2nd timer update 1row in 1 sec and show in another label that 1 row update with 2nd dataValue and so on.What should i do? Any one can help me?

In PrepareTimers assign a tag to each timer: timer1[i] = new Timer(); timer1[i].Tag = i;
Then you can use this in timer_Tick instead of looping through the whole array:
i = (int)((Timer)sender).Tag;
int dataValue = _dataValues[i];
//...
instead of:
i = 0;
foreach (int dataValue in _dataValues)
{
if (a[i] == dataValue.ToString())
//...

Related

How to set datagridview scroll position in C# winform when enter key is used in keydown event?

I'm having problem setting the vertical scroll position. I have followed this similar question and I get the expected result for CellDoubleClick Event. But for KeyDown Event, where the user will press Enter key, it resets the vertical scroll position at the top
These are my CellDouble Click and KeyDown events.
private void dataGridSrch_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
addToSell();
}
}
private void dataGridSrch_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
addToSell();
}
This is my addToSell function, this function will call after that will update the DataGridView.
public void addToSell()
{
if (dataGridSrch.SelectedRows.Count > 0)
{
DataRow row = (dataGridSrch.SelectedRows[0].DataBoundItem as DataRowView).Row;
if (Convert.ToInt32(row["Stock"].ToString()) > 0)
{
string sellProd = row["Brand"].ToString() + " " + row["Part No."].ToString();
int sellQty = Convert.ToInt32(numSell.Value);
string sellUnit = row["Unit"].ToString();
double sellPrice = double.Parse(row["Price"].ToString()) * sellQty;
double sPrice = double.Parse(row["Price"].ToString());
dataGridSales.Rows.Add(sellProd, sellQty, sellUnit, sellPrice, sPrice, row["Part No."].ToString(), row["Stock"].ToString());
int count = 0;
double total = 0;
for (int i = 0; i < dataGridSales.Rows.Count; i++)
{
total += Convert.ToDouble(dataGridSales.Rows[i].Cells[3].Value);
count += Convert.ToInt32(dataGridSales.Rows[i].Cells[1].Value);
}
lblTotAmt.Text = "Total Amount: " + total.ToString("C2");
lblTotItem.Text = "Total Items: " + count;
amount = total;
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(#"UPDATE [dbo].[products]
SET Stock = Stock - '" + sellQty + "' WHERE [Part No.] = '" + row["Part No."] + "'", conn))
{
cmd.ExecuteNonQuery();
}
conn.Close();
}
>>>>>>>>>>>>>>>>after(); //THIS IS WHERE AFTER FUNCTION IS CALLED
}
else
{
MessageBox.Show("You dont have any stock for the selected item, please restock immediately.", "Please restock", MessageBoxButtons.OK);
}
}
if (dataGridSales.Rows.Count > 0)
{
cmbMOP.Enabled = true;
}
}
And this is my after function.
public void after()
{
string item = cmbItem.Text;
string brand = cmbBrand.Text;
string part = txtPart.Text;
string manu = cmbMan.Text;
string car = cmbCar.Text;
string year = cmbYr.Text;
conn.Open();
{
int index = dataGridSrch.SelectedRows[0].Index;
>>>>>>>>>>>>int scrollPos = dataGridSrch.FirstDisplayedScrollingRowIndex; //GET THE SCROLL POSITION
string sel = #"SELECT * FROM[dbo].[products] WHERE 1=1";
using (SqlCommand cmd = new SqlCommand())
{
if (!string.IsNullOrEmpty(item))
{
sel += " AND Item = #Item";
cmd.Parameters.Add("#Item", SqlDbType.VarChar).Value = item;
}
if (!string.IsNullOrEmpty(brand))
{
sel += " AND Brand = #Brand";
cmd.Parameters.Add("#Brand", SqlDbType.VarChar).Value = brand;
}
if (!string.IsNullOrEmpty(part))
{
sel += " AND [Part No.] = #Part";
cmd.Parameters.Add("#Part", SqlDbType.VarChar).Value = part;
}
if (!string.IsNullOrEmpty(manu))
{
sel += " AND Manufacturer = #Manufacturer";
cmd.Parameters.Add("#Manufacturer", SqlDbType.VarChar).Value = manu;
}
if (!string.IsNullOrEmpty(car))
{
sel += " AND Car = #Car";
cmd.Parameters.Add("#Car", SqlDbType.VarChar).Value = car;
}
if (!string.IsNullOrEmpty(year))
{
sel += " AND Year = #Year";
cmd.Parameters.Add("#Year", SqlDbType.VarChar).Value = year;
}
cmd.CommandText = sel;
cmd.Connection = conn;
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
DataTable dt = new DataTable();
DataView dv = dt.DefaultView;
sda.Fill(dt);
dataGridSrch.DataSource = dt;
dv.Sort = "Item, Brand, Manufacturer, Car, Year, Price ASC ";
dataGridSrch.Columns["Price"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dataGridSrch.Columns["Price"].DefaultCellStyle.Format = "C2";
dataGridSrch.Columns["Stock"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
dataGridSrch.Rows[index].Selected = true;
>>>>>>>>>>>>>>>>>>>>dataGridSrch.FirstDisplayedScrollingRowIndex = scrollPos; //AFTER UPDATE SET THE SCROLL POSITION
typeof(DataGridView).InvokeMember("DoubleBuffered", BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.SetProperty, null,
dataGridSrch, new object[] { true });
}
}
}
conn.Close();
}
I have also change my KeyDown Event to this
private void dataGridSrch_KeyDown(object sender, KeyEventArgs e)
{
int index = dataGridSrch.SelectedRows[0].Index;
int scrollPos = dataGridSrch.FirstDisplayedScrollingRowIndex;
if (e.KeyCode == Keys.Enter)
{
addToSell();
dataGridSrch.Rows[index].Selected = true;
dataGridSrch.FirstDisplayedScrollingRowIndex = scrollPos;
}
}
But still it resets the scroll position.

3 DataGridViews interlinking issues

I am having three Datagridviews in my windows Form. One brings the data of Villages, on clicking any cell, Second Datagridview is populated with Customer Details. On clicking the customer name, third Datagridview must populate and calculate the balance of customer, whether credit is remaining or advance is deposited, now where I am facing problem is the third datagridview.
It specifically throws exception: Object reference set to null.
private void dataGridView3_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
double loansum1 = 0;
double emisum1 = 0;
double dd1 = 0;
double ei1 = 0;
double finalsum = 0;
foreach (DataGridViewRow drr1 in dataGridView3.Rows)
{
if (drr1.Cells[1].Selected == true)
{
string customerid = drr1.Cells[0].Value.ToString();
label1.Text = customerid;
SqlConnection setcon = new SqlConnection(ConfigurationManager.ConnectionStrings["sismanager"].ConnectionString);
using (SqlCommand getsup = new SqlCommand("SELECT Ciid, Cdate, Cparticulars, Ccr, Cdr FROM Customerbills WHERE Cid = #Cid ORDER BY Cdate DESC", setcon))
{
getsup.Parameters.AddWithValue("#Cid", customerid);
SqlDataAdapter drrr = new SqlDataAdapter(getsup);
try
{
setcon.Open();
DataTable data1 = new DataTable();
drrr.Fill(data1);
if (data1.Rows.Count > 0)
{
dataGridView1.DataSource = data1;
dataGridView1.Columns[0].HeaderText = "Bill Number";
dataGridView1.Columns[1].HeaderText = "Bill Date";
dataGridView1.Columns[2].HeaderText = "Particulars";
dataGridView1.Columns[3].HeaderText = "Credit Balance";
dataGridView1.Columns[4].HeaderText = "Cash Balance";
for (int ij = 0; ij < (dataGridView1.Rows.Count); ++ij)
{
dd1 = Double.Parse(dataGridView1.Rows[ij].Cells[3].Value.ToString());
ei1 = Double.Parse(dataGridView1.Rows[ij].Cells[4].Value.ToString());
loansum1 += dd1;
emisum1 += ei1;
}
label4.Text = (Math.Round(loansum1)).ToString();
label5.Text = (Math.Round(emisum1)).ToString();
finalsum = (emisum1 - loansum1);
if (finalsum >= 0)
{
label6.Text = "Rs. " + finalsum + " (Previous Amount Clear)";
}
else
{
label6.Text = "Rs. " + finalsum + " (Previous Amount Due)";
}
}
}
catch (SqlException exx)
{
}
finally
{
setcon.Close();
}
}
}
}
}
The exception error comes at:
dd1 = Double.Parse(dataGridView1.Rows[ij].Cells[3].Value.ToString());
Error Image below; It shows in call stack that the data is coming.

Updating data in listbox from datatable

I want to show data from data table on form_load using list box, and later update that data from list box on button click by Insert command. Function for that is fill_List(). This is my code:
OleDbConnection konekcija;
OleDbDataAdapter adapter = new OleDbDataAdapter();
DataTable dt = new DataTable();
public Form2()
{
InitializeComponent();
string putanja = Environment.CurrentDirectory;
string[] putanjaBaze = putanja.Split(new string[] { "bin" }, StringSplitOptions.None);
AppDomain.CurrentDomain.SetData("DataDirectory", putanjaBaze[0]);
konekcija = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=|DataDirectory|\B31Autoplac.accdb");
}
void fill_List()
{
konekcija.Open();
OleDbCommand komPrikaz = new OleDbCommand("SELECT * FROM GORIVO ORDER BY GorivoID ASC", konekcija);
adapter.SelectCommand = komPrikaz;
adapter.Fill(dt);
listBox1.Items.Clear();
for (int i = 0; i < dt.Rows.Count; i++)
{
string pom;
pom = dt.Rows[i][0].ToString() + " " + dt.Rows[i][1].ToString() + " " + dt.Rows[i][2];
listBox1.Items.Add(pom);
}
konekcija.Close();
}
private void Form2_Load(object sender, EventArgs e)
{
fill_List();
}
private void btnUpisi_Click(object sender, EventArgs e)
{
string s1, s2, s3;
s1 = tbSifra.Text;
s2 = tbNaziv.Text;
s3 = tbOpis.Text;
string Upisi = "INSERT INTO GORIVO (GorivoID, Naziv, Opis) VALUES (#GorivoID, #Naziv, #Opis)";
OleDbCommand komUpisi = new OleDbCommand(Upisi, konekcija);
komUpisi.Parameters.AddWithValue("#GorivoID", s1);
komUpisi.Parameters.AddWithValue("#Naziv", s2);
komUpisi.Parameters.AddWithValue("#Opis", s3);
string Provera = "SELECT COUNT (*) FROM GORIVO WHERE GorivoID=#GorivoID";
OleDbCommand komProvera = new OleDbCommand(Provera, konekcija);
komProvera.Parameters.AddWithValue("#GorivoID", s1);
try
{
konekcija.Open();
int br = (int)komProvera.ExecuteScalar();
if(br==0)
{
komUpisi.ExecuteNonQuery();
MessageBox.Show("Podaci su uspesno upisani u tabelu i bazu.", "Obavestenje");
tbSifra.Text = tbNaziv.Text = tbOpis.Text = "";
}
else
{
MessageBox.Show("U bazi postoji podatak sa ID = " + tbSifra.Text + ".", "Obavestenje");
}
}
catch (Exception ex1)
{
MessageBox.Show("Greska prilikom upisa podataka. " + ex1.ToString(), "Obavestenje");
}
finally
{
konekcija.Close();
fill_List();
}
}
Instead of this
It shows me this (added duplicates with new data)
Is there a problem in my function or somewhere else?
Another bug caused by global variables.
You are keeping a global variable for the DataTable filled by the fill_list method. This datatable is never reset to empty when you call fill_list, so at every call you add another set of rows to the datatable and then transfer this data inside the listbox. Use a local variable.
But the same rule should be applied also to the OleDbConnection and OleDbCommand. There is no need to keep global instances of them. Creating an object is really fast and the convenience to avoid global variables is better than the little nuisance to create an instance of the connection or the command.
void fill_List()
{
using(OleDbConnection konekcija = new OleDbConnection(......))
using(OleDbCommand komPrikaz = new OleDbCommand("SELECT * FROM GORIVO ORDER BY GorivoID ASC", konekcija))
{
DataTable dt = new DataTable();
konekcija.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(komPrikaz);
adapter.Fill(dt);
listBox1.Items.Clear();
for (int i = 0; i < dt.Rows.Count; i++)
{
string pom;
pom = dt.Rows[i][0].ToString() + " " + dt.Rows[i][1].ToString() + " " + dt.Rows[i][2];
listBox1.Items.Add(pom);
}
}
}
Clear your DataTable before filling it again.
void fill_List()
{
konekcija.Open();
OleDbCommand komPrikaz = new OleDbCommand("SELECT * FROM GORIVO ORDER BY GorivoID ASC", konekcija);
adapter.SelectCommand = komPrikaz;
dt.Clear(); // clear here
adapter.Fill(dt);
listBox1.Items.Clear();
for (int i = 0; i < dt.Rows.Count; i++)
{
string pom;
pom = dt.Rows[i][0].ToString() + " " + dt.Rows[i][1].ToString() + " " + dt.Rows[i][2];
listBox1.Items.Add(pom);
}
konekcija.Close();
}

Foreach loop not reaching going further than first panel items

It seems to me that my foreach loop is not reaching my second panel or something is making it skip the items in the loop.
Here is the creating of the panels and loop(I know the SQL is vulnerable to injections but for the sake of making the question shorter I just used SQL):
This is what is created for every product in the product table:
Label lbName = new Label();
lbName.Text = name + "\n" + row[7].ToString();
lbName.Height = 40;
lbName.Width = 150;
lbName.Name = name + row[7].ToString();
lbName.Location = new Point(ptX, ptY);
pt.Controls.Add(lbName);
Label lbID = new Label();
lbID.Text = row[0].ToString();
lbID.Height = 40;
lbID.Width = 150;
lbID.Name = "ID" + name + row[7].ToString();
lbID.Location = new Point(ptX, ptY);
lbID.Visible = false;
pt.Controls.Add(lbID);
TextBox txtStockCount = new TextBox();
txtStockCount.Text = "0";
txtStockCount.Height = 40;
txtStockCount.Width = 100;
txtStockCount.Name = "txtTS" + name + row[7].ToString();
txtStockCount.Location = new Point(ptX + 150, ptY);
txtStockCount.GotFocus += txtStockCount_GotFocus;
txtStockCount.KeyPress += txtStockCount_KeyPress;
txtStockCount.LostFocus += txtStockCount_LostFocus;
pt.Controls.Add(txtStockCount);
TextBox txtBroken = new TextBox();
txtBroken.Text = "0";
txtBroken.Height = 40;
txtBroken.Width = 100;
txtBroken.Name = "txtTB" + name + row[7].ToString();
txtBroken.Location = new Point(ptX + 300, ptY);
txtBroken.GotFocus += txtStockCount_GotFocus;
txtBroken.KeyPress += txtStockCount_KeyPress;
txtBroken.LostFocus += txtStockCount_LostFocus;
pt.Controls.Add(txtBroken);
TextBox txtRecieve = new TextBox();
txtRecieve.Text = "0";
txtRecieve.Height = 40;
txtRecieve.Width = 100;
txtRecieve.Name = "txtTR" + name + row[7].ToString();
txtRecieve.Location = new Point(ptX + 450, ptY);
txtRecieve.GotFocus += txtStockCount_GotFocus;
txtRecieve.KeyPress += txtStockCount_KeyPress;
txtRecieve.LostFocus += txtStockCount_LostFocus;
pt.Controls.Add(txtRecieve);
Label lbDifference = new Label();
lbDifference.Text = " 0 ";
lbDifference.Height = 40;
lbDifference.Width = 150;
lbDifference.Name = "lblDiff" + name + row[7].ToString();
lbDifference.Location = new Point(ptX + 600, ptY);
pt.Controls.Add(lbDifference);
Button btnConfirm = new Button();
btnConfirm.Text = "Confirm";
btnConfirm.Height = 30;
btnConfirm.Width = 80;
btnConfirm.Name = "btnConfirm" + name + row[7].ToString();
btnConfirm.Location = new Point(ptX + 750, ptY);
btnConfirm.Click += btnConfirm_Click;
pt.Controls.Add(btnConfirm);
and the reading the panels to update the database from the text boxes:
private void txtStockCount_LostFocus(object sender, EventArgs e)
{
TextBox txtB = (sender as TextBox);
string name = txtB.Name.Remove(0,5);
string prodID = "";
string QtyToday = "";
string QtyBD = "";
string QtyRev = "";
string table = "";
foreach (Panel p in pnls)
{
IEnumerable<Label> labels = p.Controls.OfType<Label>();
foreach (Label label in labels)
{
string Compare = label.Name.Remove(0, 2);
if (name == Compare)
{
prodID = label.Text;
if (Regex.IsMatch(Compare, #"^[a-hA-H]"))
{
table = "ProductHistoryAH";
}
else if (Regex.IsMatch(Compare, #"^[i-qI-Q]"))
{
table = "ProductHistoryIQ";
}
else if (Regex.IsMatch(Compare, #"^[r-zR-Z]"))
{
table = "ProductHistoryRZ";
}
}
}
string sql = "Select * From Product WHERE ProdID = '" + prodID + "'";
DataTable dtP = db.GetDataTable(sql);
IEnumerable<TextBox> textBoxes = p.Controls.OfType<TextBox>();
foreach (TextBox textBox in textBoxes)
{
string name1 = textBox.Name.Remove(0, 5);
label2.Text = name1;
if (name == name1)
{
if (textBox.Name == "txtTS" + dtP.Rows[0][1].ToString() + dtP.Rows[0][7].ToString())
{
QtyToday = textBox.Text;
}
if (textBox.Name == "txtTB" + dtP.Rows[0][1].ToString() + dtP.Rows[0][7].ToString())
{
QtyBD = textBox.Text;
}
if (textBox.Name == "txtTR" + dtP.Rows[0][1].ToString() + dtP.Rows[0][7].ToString())
{
QtyRev = textBox.Text;
}
}
}
string sql1 = "Select * From " + table + " WHERE ProdID = '" + prodID + "' AND ProdHDate = '" + DateTime.Today.Date.ToShortDateString() + "'";
DataTable dt = db.GetDataTable(sql1);
if (dt.Rows.Count == 0)
{
dbh.addnewstockhistory(ph);
}
else if (dt.Rows.Count > 0)
{
dbh.updatestockhistory(ph);
}
}
}
Everything works 100%, it inserts and updates data with ease, with the first panel but no other textboxes on the other panels work.
The error lies in the foreach panel loop, the foreach loops inside the panel loop. It says there is a syntax error near the where of string sql1. But what i dont understand is that it works for the first panel but non of the other panels and it does have the prodID, I know this cause i placed the statement in a label just to see how it looks.
Please help. Ask for anything if you need.
I think I solved it. All I had to do was check if the panel is the panel hosting the control by checking if the panel was the buttons parent and it worked.
if(p == btn.Parent)
{
//Do my stuff
}
in my foreach panel loop.

c# confusing on loop

MessageBox.Show(urls[m]);
of the code below it show 16 time like a,a,a,a,b,b,b,b,c,c,c,c,d,d,d,d how can i add 4 non duplicate to urls[m]. My code is purpose to swlwct url from data base to open on 4 different browser1 browser 2 .. but on browser show the same URL
namespace tabcontrolweb
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string MyConString = "SERVER=192.168.0.78;" +
"DATABASE=webboard;" +
"UID=aimja;" +
"PASSWORD=aimjawork;" +
"charset=utf8;";
MySqlConnection connection = new MySqlConnection(MyConString);
MySqlCommand command = connection.CreateCommand();
MySqlDataReader Reader;
command.CommandText = "SELECT urlwebboard FROM `listweb` WHERE `urlwebboard` IS NOT NULL AND ( `webbordkind` = 'เว็บท้องถิ่น' ) and `nourl`= 'n' order by province, amphore limit 4 ";
connection.Open();
Reader = command.ExecuteReader();
string[] urls = new string[4];
string thisrow = "";
string sumthisrow = "";
while (Reader.Read())
{
thisrow = "";
for (int i = 0; i < Reader.FieldCount; i++)
{
thisrow += Reader.GetValue(i).ToString();
System.IO.File.AppendAllText(#"C:\file.txt", thisrow + " " + Environment.NewLine);
sumthisrow = Reader.GetValue(i).ToString();
}
for (int m = 0; m < 4 ; m++)
{
urls[m] = sumthisrow;
MessageBox.Show(urls[m]);
}
webBrowser1.Navigate(new Uri(urls[0]));
webBrowser1.Dock = DockStyle.Fill;
webBrowser2.Navigate(new Uri(urls[1]));
webBrowser2.Dock = DockStyle.Fill;
webBrowser3.Navigate(new Uri(urls[2]));
webBrowser3.Dock = DockStyle.Fill;
webBrowser4.Navigate(new Uri(urls[3]));
webBrowser4.Dock = DockStyle.Fill;
}
connection.Close();
}
I can't understand this code:
for (int m = 0; m < 4 ; m++)
{
urls[m] = sumthisrow;
MessageBox.Show(urls[m]);
}
Why are you inserting in urls[m] the same value?
Bear in mind that in the previous loop the variable sumthisrow will keep only the last value just like:
sumthisrow = Reader.GetValue(Reader.FieldCount - 1).ToString();
EDIT: Also consider using a StringBuilder for creation of thisrow variable.
EDIT 2: Put your disposable objects into a using statement.

Categories