How to show all data results to listview? - c#

I have a code here showing the data from sqldatabase to listview when searching.
int flag = 0;
connectionstatus();
SqlCommand cmd = new SqlCommand("SELECT *FROM SampleDatabase WHERE IdNo=#IdNo", conn);
cmd.Parameters.Add("#IdNo", SqlDbType.VarChar).Value = txtIdNo.Text;
SqlDataReader objRead = cmd.ExecuteReader();
lvlist.Items.Clear();
while (objRead.Read())
{
if ((txtIdNo.Text) == (objRead["IdNo"].ToString()))
{
flag = 1;
break;
}
}
if (flag == 1)
{
ListViewItem list = new ListViewItem(basa["FID"].ToString());
list.SubItems.Add(objRead["FullName"].ToString());
list.SubItems.Add(objRead["Age"].ToString());
list.SubItems.Add(objRead["Gender"].ToString());
list.SubItems.Add(objRead["Relationship"].ToString());
list.SubItems.Add(objRead["SkillnOccupation"].ToString());
lvlist.Items.AddRange(new ListViewItem[] { list });
}
My problem is that when im searching and the database have data with the same IdNo it only shows 1 result. How can i show all the results that has the same IdNo? Can you guys help me out in this. Thanks in advance.

Put the item population code inside the loop:
while (objRead.Read())
{
ListViewItem list = new ListViewItem(basa["FID"].ToString());
list.SubItems.Add(objRead["FullName"].ToString());
list.SubItems.Add(objRead["Age"].ToString());
list.SubItems.Add(objRead["Gender"].ToString());
list.SubItems.Add(objRead["Relationship"].ToString());
list.SubItems.Add(objRead["SkillnOccupation"].ToString());
lvlist.Items.Add(list);
}

Replace your last line with this. Seems like you're making two ListViewItems for every item? See if it helps, then look here.
Add item to Listview control
lvlist.Items.Add(list);

Related

how to make the datagridview load faster with Multiple Row query - c# SQL

The code:
private void suppPopulate()
{
byCode.Text = "Supplier Code";
byDesc.Text = "Supplier";
DGViewListItems.Columns.Add("custcode", "Customer Code");
DGViewListItems.Columns.Add("customer", "Customer");
DGViewListItems.Columns[0].ReadOnly = true;
DGViewListItems.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
DGViewListItems.Columns[1].ReadOnly = true;
DGViewListItems.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
using (SqlConnection con = db.Connect())
{
SqlDataReader rd;
SqlCommand cmd = new SqlCommand("SELECT DISTINCT custcode, custname FROM Customers WHERE type = 'V';", db.Connect());
rd = cmd.ExecuteReader();
int i = 0;
if (rd.HasRows)
{
while (rd.Read())
{
DGViewListItems.Rows.Add();
DGViewListItems.Rows[i].Cells["custcode"].Value = rd["custcode"].ToString().Trim();
DGViewListItems.Rows[i].Cells["customer"].Value = rd["custname"].ToString().Trim();
}
}
cmd.Connection.Close();
}
}
The SSMS output:
The output form loads slowly, the rows for the query are over 1000 so I think the cause of the slow load is the number of returned rows? If yes, how do make the load of the datagridview faster?
NOTE - this answer relates to the first part of the original question regarding why only a single row of the DataGrid being populated.
Incrementing the counter "i" at the bottom of the while loop looks like it may fix the problem.
You are adding rows, but only updating the first.

How can i change the name of checkbox each time it iterates over while loop?

I am trying to generate a checkbox for all results from database for which the condition was matched .
I was abled to do that , now I would like to take that data from checkbox and insert into database , its for a voting project I am working on , I am not sure how I could achieve this because there's no specific name for the checkboxes to get data from .
I am new to this area and really lost.
If someone could help its much appreciated.
private void loadCandidates()
{
String qry = "SELECT * FROM candidate_tb WHERE party ='Samagi Jana Balawegaya'";
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(qry, conn);
SqlDataReader rd = cmd.ExecuteReader();
int i = 0;
while (rd.Read())
{
String no = (rd["no"].ToString());//Getting candidate no
CheckBox check = new CheckBox();//creating new checkbox
check.Margin = new Padding(0, 0, 0, 10);
check.Text = no + "candidate";
check.Name ="btn1"+i;
FLP.Controls.Add(check);
i++;
}
}
catch (Exception es)
{
MessageBox.Show($"Internal error: {es}");
}
}
private void voteCast()
{
//where the casted vote data would go to database
//but I cant seem to find a way
}

Remove existing items in listbox from database

I am trying to delete the items within the listbox, which already exists in my database. My listbox is populated by a set of random names, and the ones that are equal to the data from the table rows should be deleted.
My code:
SqlCommand RemoveUserName = new SqlCommand("SELECT * FROM Name WHERE ([Name] = #check)", Con);
RemoveUserName.Parameters.AddWithValue("#check", listbox1.Items);
SqlDataReader dr = RemoveUserName.ExecuteReader();
if (dr.HasRows)
{
listBox1.Items.Remove(); // ?? Remove the names which are already in the database
}
else
{
// remain in listbox
}
Getting an error in my parameter value and I don't know how to delete the said items.
EDITED my current code:
SqlCommand RemoveUserName = new SqlCommand("SELECT * FROM Name", Con);
SqlDataReader dr = RemoveUserName.ExecuteReader();
while (!dr.Read())
{
for (int i = 0; i < listBox1.Items.Count; ++i)
{
if (listBox1.Items[i].ToString() == dr["Name"].ToString())
listBox1.Items.Remove(listBox1.Items[i]);
}
}
Has no error anymore, but is still not functional.
WORKING CODE:
for (int i = listBox1.Items.Count - 1; i >= 0; --i)
{
using (var cmd = new SqlCommand("UPDATE [Name] SET [Name] = Name WHERE [Name] = #name", Con))
{
cmd.Parameters.AddWithValue("#name", listBox1.Items[i].ToString());
if (cmd.ExecuteNonQuery() > 0)
{
listBox1.Items.RemoveAt(i);
}
}
}
Thanks # LarsTech
It helps to loop backwards through the list in order to avoid indexing issues:
for (int i = listBox1.Items.Count - 1; i >= 0; --i) {
using (var cmd = new SqlCommand("DELETE FROM [Name] WHERE [Name] = #name", Con)) {
cmd.Parameters.AddWithValue("#name", listBox1.Items[i].ToString());
if (cmd.ExecuteNonQuery() > 0) {
listBox1.Items.RemoveAt(i);
}
}
}
ExecuteNonQuery will return the number of records affected, so if it's greater than zero, the name was found and deleted.
Make sure to close your connection object, too. Best by putting it also in a using block the way the SqlCommand object is in my example.
Your table and column names need to be improved.
As I understood,
1) You need to delete items from listbox that already exists in your database and read by SqlDataReader.
You first need to loop into reader. So instead of !while(reader.Read()) use while(reader.Read())
2) Now you want to remove actual item from listbox, if it exists in reader.
So try to do following to remove item from listbox inside reader while loop
for (int n = listBox.Items.Count - 1; n >= 0; --n)
{
var removelistitem = dr["Name"].ToString();
if (listBox.Items[n].ToString().Contains(removelistitem))
{
listBox.Items.RemoveAt(n);
}
}
Now after while loop execution. your listbox will only have items not present in your reader (data from database).
Hope this helps.
Edit
Its ok to loop in listbox items.
Use RemoveAt instead. (See above answer)
try this:
while (!dr.Read())
{
for (int i=0; i<listBox1.Items.Count; ++i)
{
if (listBox1.Items[i].ToString() == dr["columnName"].ToString())
listBox1.Items.Remove(listBox1.Items[i]);
}
}
SqlReader must be read before use it. If there's no rows in the Reader, code in while block won't be executed.
EDIT I got a problem making you unhappy....
The code you provided:
RemoveUserName.Parameters.AddWithValue("#check", listbox1.Items);
Is wrong, because #check parameter expects string, but you provided was ObjectCollection. Revise query "SELECT * FROM Name WHERE ([Name] = #check)" to "SELECT * FROM Name". and remove the line AddWithValue.

How to retrieve data from database to CheckedListBox and set the items as checked?

I am new in WPF. I am trying to load the values from database to fill in CheckedListBox. Based on a condition, some items must be set to checked while loading in checkedlistbox.
How to do this? I have tried the code below, items are loaded in CheckedListBox, but are not checked.
Below is values loaded to checked listbox
public void fillcheck()
{
con = new SqlConnection(connectionstring);
con.Open();
string comboquery = "SELECT [Machine] FROM Department Where active='True'";
SqlCommand cmd = new SqlCommand(comboquery, con);
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
string fil1 = rdr.GetString(0);
Checkedlistbox1.Items.Add(fil1);
}
rdr.Close();
}
int departmentID=60//for just refer
Object[] jobs = CheckedlistBox1.Items.Cast<Object>().ToArray();
foreach (Object obj in jobs)
{
string query = "SELECT [Machine] FROM Department Where ID='" + departmentID+ "'";
SqlCommand cmd = new SqlCommand(query, con);
SqlDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
{
string mac = rdr.GetString(0);//Here i get two values(XRAY,CT)but finally shown CT only be checked,so how to do both checked
if (mac == obj.ToString())
{
int indexx = CheckedlistBox1.Items.IndexOf(mac);
if (indexx >= 0)
{
CheckedlistBox1.SetItemChecked(indexx, true);
}
}
}
rdr.Close();
}
You need to transfer your SqlDataReader rdr content to a DataTable. That will help you get a DataTable object containing multiple rows like you have mentioned.
Now for the next step, you can apply a foreach on that DataTable object to iterate over all its rows like this :
foreach(DataRow dr in dt.Rows)
{
if(yourCondition)
{
//set isChecked = true for the checkbox.
}
}
UPDATE :
Try modifying your while loop like this :
while (rdr.Read())
{
string mac = rdr.GetString(0);
ListItem li = new ListItem();
li.Value = "yourBindedValue";// some value from database column
li.Text = "yourBindedText";// use mac if its text.
int index = Checkedlistbox1.Items.IndexOf(li);
if (index >= 0)
{
Checkedlistbox1.SetItemChecked(index, true);
}
}
I have tested this and it works. You just have to pass the Text and Value of the CheckBoxListItem that you are trying to find in the li object and you can get the index if it exists. Make sure you pass both the attributes.
You should have used code-
foreach (int indexChecked in chlstBox.Items)
instead of
foreach (int indexChecked in chlstBox.CheckedIndices)
At start you have 0 selected items and thats why your outer for loop is not working..
EDIT-
Basic Logic is also incorrect.
You should loop through dataset, find the string in checkboxlist and then check it. So, outer foreach loop is not required. Also, make sure that you are using correct checkboxlist variable. In for loop you are using chlstBox
and while searching you are using Checkedlistbox1 ....

Efficient way to retrieve multiple values from the same column

I want to set some buttons text (content) with values I retrieve from a mysql.
till now I always did it like this:
if (rdr.Read())
{
Item1.Visibility = Visibility.Visible;
Item1txt.Text = rdr.GetString("item_name");
}
if (rdr.Read())
{
Item2.Visibility = Visibility.Visible;
Item2txt.Text = rdr.GetString("item_name");
}
if (rdr.Read())
{
Item3.Visibility = Visibility.Visible;
Item3txt.Text = rdr.GetString("item_name");
}
This way works fine because I retrieve the right values in each button, but it makes the readability horrible..
When I started this project I had zero knowledge of C# so I tried some things like:
while (rdr.Read())
{
Item4.Visibility = Visibility.Visible;
Item4txt.Text = rdr.GetString("item_name");
Item5.Visibility = Visibility.Visible;
Item5txt.Text = rdr.GetString("item_name");
}
But this gave me the same value retrieved from my database in my buttons..
example:
button 1: test1 | button 2: test1 | button 3: test1.. etc..
what i need:
button 1: test1 | button2: test2 | button 3: test3.. etc..
Now my knowledge of C# is getting better every day so I want to learn some new things.
Right now I'm trying to use the foreach loop but I have a feeling I'm missing something:
using (MySqlConnection conn = new MySqlConnection(_CS))
{
conn.Open();
string cmd = "SELECT * FROM ordertopos LIMIT 10";
MySqlCommand custid = new MySqlCommand(cmd, conn);
using (MySqlDataReader rdr = custid.ExecuteReader())
{
System.Data.DataTable dt = new System.Data.DataTable();
dt.Load(rdr);
foreach (System.Data.DataRow row in dt.Rows)
{
Orderl1.Text = row["customerid"].ToString();
}
}
}
Essentially I want to know how I can set the content of my buttons, retrieved from mysql, in a more efficient en easier to maintain code..
I'm fairly new with foreach, so please be specific.
i would recommend to do it in several step's for a better reusability
Step 1
List<string> myItems;
using (MySqlConnection conn = new MySqlConnection(_CS))
{
conn.Open();
string cmd = "SELECT * FROM ordertopos LIMIT 10";
MySqlCommand custid = new MySqlCommand(cmd, conn);
using (MySqlDataReader rdr = custid.ExecuteReader())
{
myItems= new List<string>();
while (rdr.Read())
{
myItems.Add(rdr.GetString("item_name"));
}
}
}
Step 2
modified Olivier Jacot-Descombe version
for(int i =0; i< myItems.count; i++) {
Button btn = FindChild<Button>(this, "Item" + i); //"this" will be the control which contains your button's
TextBlock tb = FindChild<TextBlock>(btn, "Item" + i + "txt");
btn.Visibility = Visibility.Visible;
tb.Text =myItems[i];
i++;
}
If you want to scale your problem in order to use loops than you need to have a List or an Array that contains objects for which you want to set values of properties. In your particular case, put your Orders in a List<Order> and then you could use something like this:
int count = 0;
foreach (System.Data.DataRow row in dt.Rows)
{
if(count<orders.Count)
orders[count++].Text = row["customerid"].ToString();
}
You need to traverse through your Items to set respective values. As DJ Kraze suggested, you are just overwriting the same control. And it will have the last accessed value (as it won't be overwritten once loop has ended).
You you just need to have somehow reference to your target controls, or if you are creating controls on the fly, than you can simply pass reference of newly created control every time you access a row from database.
You can access controls by their name instead of their member variable by using the FindChild method found here: WPF ways to find controls.
int i = 1;
while (rdr.Read()) {
Button btn = FindChild<Button>(this, "Item" + i);
TextBlock tb = FindChild<TextBlock>(btn, "Item" + i + "txt");
btn.Visibility = Visibility.Visible;
tb.Text = rdr.GetString("item_name");
i++;
}
This enables you to loop through them by using a counter (i).

Categories