Search string in Listbox - c#

I'm having troubles finding a string into a listbox, my string NombreCompleto is made of 3 strings that I previously had read from a file(ESSD), after I had recovered this string, I want to know if this string is in my listbox3, I tried several methods but it doesnt seem to work.
Here is my code.
foreach (string h in Directory.EnumerateFiles(NomDirec, "resume*"))
{
this.listBox1.Items.Add(h);
var NombreLinea = File.ReadLines(h);
foreach (string item in NombreLinea)
{
NombreAbuscar.Add(item.Remove(item.IndexOf(':')));
this.listBox3.Items.Add(item.Remove(item.IndexOf(':')));
}
foreach (string t in Directory.EnumerateFiles(NomDirec, "ESSD1*"))
{
string[] Nombre = File.ReadLines(t).ElementAtOrDefault(6).Split(':');
string[] ApellidoPat = File.ReadLines(t).ElementAtOrDefault(7).Split(':');
string[] ApellidoMat = File.ReadLines(t).ElementAtOrDefault(8).Split(':');
string NombreCompleto = ApellidoPat[1]+" "+ ApellidoMat[1] +","+" "+ Nombre[1];
string Nom2 = NombreCompleto.ToString();
int index = listBox3.FindString(Nom2);
if (index != -1)
{
this.listBox1.Items.Add(t);
MessageBox.Show("Find It");
}
else { MessageBox.Show("Not Found :#"); }
}

You can try with this code - based on Linq operator Where, ...
var selectedItems = from li in listBox3.Items
where li.Text == Nom2
select li.Text;
if(selectedItems.Any())
....

Try this out:
int index = -1;
for (int i = 0; i < listBox3.Items.Count; ++i)
if (listBox3.Items[i].Text == Nom2) { index = i; break; }
if (index != -1)
{
this.listBox1.Items.Add(t);
MessageBox.Show("Find It");
}
else { MessageBox.Show("Not Found :#");

Really easy way to find if a certain string is in a listbox.
private void btnAddRecipe_Click(object sender, EventArgs e)
{
bool DoesItemExist = false;
string searchString = txtRecipeName.Text;
int index = lstRecipes.FindStringExact(searchString, -1);
if (index != -1) DoesItemExist = true;
else DoesItemExist = false;
if (DoesItemExist)
{
//do something
}
else
{
MessageBox.Show("Not found", "Message", MessageBoxButtons.RetryCancel, MessageBoxIcon.Stop);
}
PopulateRecipe();
}

Related

How to count duplicates from ListBox and show the number of duplicated items beside it?

So I have a button, where if you click it, it adds "Candy" to a listbox, how do I make it so, if another item with the same name is being added, instead of adding it in a new line, update the first line to show x2, 3, 4, etc. Is that possible or would I have to make another Listbox and match the index? I've tried the following with another listbox and an int variable.
private void btnCandy_Click(object sender, EventArgs e)
{
lstProducts.Items.Add("Candy");
foreach (var item in lstProducts.Items)
{
if (item.ToString() == "Candy")
{
++Productcount;
lstQuantity.Items.Add(Productcount);
if (Productcount > 1)
{
lstQuantity.Items.Insert(lstProducts.Items.IndexOf("Candy"), Productcount);
}
}
}
}
using System.Text.RegularExpressions;
Use:
private void btnCandy_Click(object sender, EventArgs e)
{
string query = "Candy";
bool isExist = false;
for (int i = 0; i < lstProducts.Items.Count; i++)
{
var s = lstProducts.Items[i].ToString();
if (s.StartsWith(query))
{
if (s == query)
{
lstProducts.Items[i] = query + "x2";
isExist = true;
break;
}
else
{
// Escape your plain text before use with regex
var pattern = Regex.Escape(query);
// Check if s has this formnat: queryx2, queryx3, queryx4, ...
Match m = Regex.Match(s, "^" + pattern + #"x(\d+)$");
if (m.Success)
{
lstProducts.Items[i] = query + "x" + (Int32.Parse(m.Groups[1].Value) + 1);
isExist = true;
break;
}
}
}
}
if (!isExist) lstProducts.Items.Add(query);
}
Note:
\d mean any digit (0 - 9)
I'd try to iterate through listbox items and if I find "Candy" then take that index and update title.
private void btnCandy_Click(object sender, EventArgs e)
{
bool found = false;
foreach (var item in lstProducts.Items)
{
if (item.ToString().StartsWith("Candy"))
{
// update item title
found = true;
break; // no need to continue
}
}
if(!found)
{
lstProducts.Items.Add("Candy");
}
}
this way you are not going to add duplicates
Here is some pseudo-code to help you. Add this to your button click event:
int i = 0;
foreach (string item in listbox1.Items)
{
If (item == textbox1.text) //textbox1.text contains the string such as 'candy'
{
i++;
listbox1.Items.Remove(item);
listbox1.Items.Add(textbox1.text + " " + i.ToString());
}
}
You may have to reset the counter as needed.

One row of list view is updating, but duplicate row is also inserted

Hello folks I am trying to update the quantity of a product that is being ordered. If the product already exists in the users 'basket' instead of inserting a new row, the quantity in the row with the existing item should be updated. It is updating but a new row is also inserted with the quantity that should have been added to the original row, like so:
I'm guessing something is wrong logically in my code but, I can't spot it.
private void btn_add_Click(object sender, EventArgs e)
{
try
{
ListViewItem item = new ListViewItem(list_Select_Product.SelectedItems[0].Text);
item.SubItems.Add(list_Select_Product.SelectedItems[0].SubItems[1].Text);
item.SubItems.Add(txt_quantity.Text);
bool ok = true;
if (!validNumbers(txt_quantity))
ok = false;
if (!validLength(txt_quantity, 1, 2))
ok = false;
if (ok == true)
{
foreach (ListViewItem lvi in list_view_orderitems.Items)
{
if(lvi.SubItems[0].Text == list_Select_Product.SelectedItems[0].Text)
{
int UpdateQunat = Convert.ToInt32(lvi.SubItems[2].Text);
int AddMe = Convert.ToInt32(txt_quantity.Text);
UpdateQunat = UpdateQunat + AddMe;
lvi.SubItems[2].Text = Convert.ToString(UpdateQunat);
list_view_orderitems.Items.Add(item);
}
else if (lvi.SubItems[0].Text != list_Select_Product.SelectedItems[0].Text)
{
list_view_orderitems.Items.Add(item);
}
}
if(list_view_orderitems.Items.Count == 0)
{
list_view_orderitems.Items.Add(item);
}
}
}
catch
{
MessageBox.Show("A product must be selected");
}
}
Look a little closer in the foreach loop. You actually add it there as well. (So you should remove that)
foreach (ListViewItem lvi in list_view_orderitems.Items)
{
if(lvi.SubItems[0].Text == list_Select_Product.SelectedItems[0].Text)
{
int UpdateQunat = Convert.ToInt32(lvi.SubItems[2].Text);
int AddMe = Convert.ToInt32(txt_quantity.Text);
UpdateQunat = UpdateQunat + AddMe;
lvi.SubItems[2].Text = Convert.ToString(UpdateQunat);
// adding it again. This line is not needed.
list_view_orderitems.Items.Add(item);
}
else if (lvi.SubItems[0].Text != list_Select_Product.SelectedItems[0].Text)
{
list_view_orderitems.Items.Add(item);
}
}
I this that it this if you need to get rid of the item.Add (i marked it:
if(lvi.SubItems[0].Text == list_Select_Product.SelectedItems[0].Text)
{
int UpdateQunat = Convert.ToInt32(lvi.SubItems[2].Text);
int AddMe = Convert.ToInt32(txt_quantity.Text);
UpdateQunat = UpdateQunat + AddMe;
lvi.SubItems[2].Text = Convert.ToString(UpdateQunat);
// list_view_orderitems.Items.Add(item);
}

Jump out from Inner-Foreach to Outer-Foreach, Keep Inner-Foreach where you left it

I have the following code:
foreach (XNode rowXml in elements.Nodes())
{
foreach (DataRow rowDB in dataSetDB.Tables[0].Rows)
{
string itemDB = rowDB[0].ToString().ToUpper();
string itemXml = rowXml.ToString().ToUpper();
if (itemDB == itemXml)
{
//If itemDB == itemXml; jump to Outer_Foreach
}
if (itemDB != itemXml)
{
//If itemDB != itemXml; jump to Outer_Foreach
}
}
How is it possible to get out of Inner-Foreach and up to Outer-Foreach, and still keep both foreach where you left it. I am looping through a DB and XML table rows. Break; completley jumps out of the Inner-Foreach and im not able to catch where I left it, so I start back on index[0], when I loop through it over and over again.
It sounds like you need 'for' loop.
int i = 0;
int k = 0;
bool shouldBreak;
var nodes = elements.Nodes();
var rows = dataSetDB.Tables[0].Rows;
for (i = 0; i < nodes.Count(); i++)
{
for(k = 0; k < rows.Count(); k++)
{
string itemDB = rows[k][0].ToString().ToUpper();
string itemXml = nodes[i].ToString().ToUpper();
if (itemDB == itemXml)
{
shouldBreak = true;
break;
}
if (itemDB != itemXml)
{
shouldBreak = true;
break;
}
}
if (toBreak)
break;
}
Now if you'll break the inner loop can know where it broke by accessing i and k
This answer is stolen from this answer here. What you want to achieve is a zip operation. For more information see the answer that I linked.
var xmlNodes = elements.Nodes();
var dbNodes = dataSetDB.Tables[0].Rows;
var xmlAndDB = xmlNodes.Zip(dbNodes , (x, d) => new { xNode = x, dNode = d });
foreach(var xd in xmlAndDB )
{
Console.WriteLine(xd.xNode + xd.dNode);
string itemDB = xd.dNode[0].ToString().ToUpper();
string itemXml = xd.xNode.ToString().ToUpper();
if (itemDB == itemXml)
{
//If itemDB == itemXml;
}
else /* if (itemDB != itemXml) */
{
//If itemDB != itemXml;
}
}

Trying to search ListView for subitems matching a string

I'm having trouble scanning through a ListView to locate a subitem matching a given string. Here's my code:
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
string date = datePicker.Value.ToShortDateString();
int count = Program.booker.listView.Items.Count;
for (int i = 0; i < count; i++)
{
ListViewItem lvi = Program.booker.listView.Items[i];
if (lvi.SubItems.Equals(date))
{
MessageBox.Show("Found!", "Alert");
Program.booker.listView.MultiSelect = true;
Program.booker.listView.Items[i].Selected = true;
}
else
{
MessageBox.Show("Nothing found for " + date, "Alert");
}
}
}
The ListView is located on the Booker form, and I'm accessing it from the Filter class. I'd like to search the entire ListView for any items matching my date string. Thanks!
You can use the FindItemWithText method.
ListViewItem searchItem = null;
int index = 0;
do
{
if (index < Program.booker.listView.Items.Count)
{
//true = search subitems
//last false param = no partial matches (remove if you want partial matches)
searchItem = Program.booker.listView.FindItemWithText(date, true, index, false);
if (searchItem != null)
{
index = searchItem.Index + 1;
//rest of code
}
}
else
searchItem =null;
} while (searchItem != null);

Datagridview sorting column based on matching string

I have a datagridview that I would like to have rows sorted based on the portion of a string entered from a user. The entered string is compared with all of the strings in a particular column. For instance, if I gave "comp" as the search word, the program would try to compare the search word with the strings on first column and sort the rows in a descending order which starts with "comp", such as "compare", "composition", "computer" etc. Rest of the words that do not match is either left alone or sorted in an alphabetical order (whichever is easier).
In LINQ, I am aware that you can apply the following code to achieve what you wanted with a string array:
var sortedWords = words.Where(x => x.Contains("comp"))
.OrderByDescending(x => x);
How can I achieve the same thing in Datagridview as I need to have the rows sorted, not just the items inside a particular column?
Edit:
The following code is giving a System.InvalidOperationException. (SetCurrentCellAddressCore is being called twice)
private void DGVPointCtrl_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
MatchComparer mc = new MatchComparer();
DGVPointCtrl.Sort(mc); //Error
}
I'm probably doing something wrong but I'm not sure why. Here is the code that programatically adds the rows for testing purposes:
private void BtnRefresh_Click(object sender, EventArgs e)
{
try
{
DGVPointCtrl.Rows.Clear();
int mainIndex = CmbMainDevice.SelectedIndex;
int subIndex = CmbSubDevice.SelectedIndex;
DDCDAO ddcdao = new DDCDAO(DDCGlobal.ddcEngineIP, ddc.Ip);
string pointListType;
object rs;
//Currently only supports IO DDC Request
//TO DO: Change DDCDAO to send proper subdevice requests
if (mainIndex == 0) //IO
{
#region Main Device: IO
}
//First row is for searching items
DGVPointCtrl.Rows.Add(new DataGridViewRow());
for (int i = 1; i < 5; i++)
{
DGVPointCtrl.Rows.Add(new DataGridViewRow());
DGVPointCtrl.Rows[i].ReadOnly = true;
}
DGVPointCtrl.Columns[0].SortMode = DataGridViewColumnSortMode.Programmatic;
DGVPointCtrl.Rows[0].DefaultCellStyle.Font =
new Font(DGVPointCtrl.DefaultCellStyle.Font, FontStyle.Italic | FontStyle.Bold);
if (subIndex == 1) //BI
{
PointDGVColumnGenerate("IO_BI");
}
else if (subIndex == 2) //BO
{
PointDGVColumnGenerate("IO_BO");
}
else if (subIndex == 3) //AI
{
PointDGVColumnGenerate("IO_AI");
}
else if (subIndex == 4) //AO
{
PointDGVColumnGenerate("IO_AO");
}
DGVPointCtrl.Rows[1].Cells[0].Value = "IO12314";
DGVPointCtrl.Rows[2].Cells[0].Value = "IO21948";
DGVPointCtrl.Rows[3].Cells[0].Value = "IO28194";
DGVPointCtrl.Rows[4].Cells[0].Value = "VP12984";
DGVPointCtrl.Rows[2].Cells[1].Value = "asdf";
#endregion
}
catch
{
}
}
private void PointDGVColumnGenerate(string key)
{
int colCount = 0;
DGVColumnTable.Clear();
for (int i = 0; i < COL_MAX; i++)
{
DGVPointCtrl.Columns[i].HeaderText = " ";
DGVPointCtrl.Columns[i].Visible = true;
}
foreach (string s in UIConstant.DDCPCtrlListColumnText[key])
{
DGVPointCtrl.Columns[colCount].HeaderText = s;
DGVColumnTable.Add(DGVPointCtrl.Columns[colCount]);
colCount++;
}
}
Edit2:
public class MatchComparer : IComparer
{
private static IComparer defaultComparer = new CaseInsensitiveComparer();
int IComparer.Compare(object x, object y)
{
DataGridViewRow xr = (DataGridViewRow)x;
DataGridViewRow yr = (DataGridViewRow)y;
string xs = "";
string ys = "";
try
{
xs = xr.Cells[0].Value.ToString();
}
catch
{
}
try
{
ys = yr.Cells[0].Value.ToString();
}
catch
{
}
if (HasMatch(xs) && !HasMatch(ys)) return -1;
else if (!HasMatch(xs) && HasMatch(ys)) return 1;
else return defaultComparer.Compare(xs, ys);
}
This is possible only if you are populating the grid yourself as opposed to binding it to the database.
Set DataGridViewColumn.SortMode to Programmatic.
Use DataGridView.Sort to impose a comparer like this:
public class MatchComparer : IComparer {
int IComparer.Compare(object x, object y) {
if (HasMatch(x) && !HasMatch(y)) return -1;
else if (!HasMatch(x) && HasMatch(y)) return 1;
else return defaultComparer.Compare(x, y);
}
private bool HasMatch(object x) {
return x is string && ((string)x).StartsWith("comp");
}
private static IComparer defaultComparer = new CaseInsensitiveComparer();
}

Categories