compare the items in list in c# - c#

i want to compare the selecteditem of combobox with the selecteditem of other combobox
for this i have registered all the comboboxes in a list and named it "panel1kilist"
now the problem i am facing is that when there are same items in two comboboxes first the messagebox shows "no mattch found" and then it shows "match found" actually it goes to the else statement of inner loop first and then to if statement kindly help
private void button1_Click(object sender, EventArgs e)
{
bool check = false;
bool check1 = false;[![in this image you can see that there are two same items but message is showing "no match found"][1]][1]
try[![after clicking on ok button of message box showing "no match found" this message box shows up][1]][1]
{
for (int i = 1; i < panel1kilist.Count; i++)
{
for (int j = i + 1; j < panel1kilist.Count; j++)
{
if (panel1kilist[i].SelectedItem.ToString() == panel1kilist[j].SelectedItem.ToString())
{
if (check == false)
{
MessageBox.Show("match found");
}
check = true;
}
else
{
if (check1 == false)
{
MessageBox.Show("no match found");
}
check1 = true;
}
}
}
}
catch (System.NullReferenceException)
{
MessageBox.Show("please fill all the boxes first");
}
}

Your question is not really clear but I still try to give you some help. As mentioned in the comments there are several small issues in your code:
1. The outter for-loop
for (int i = 1; i < panel1kilist.Count; i++)
You define i = 1, which means you skip the very first item in your panel1kilist because lists and arrays start at index 0
2. Use of your bool variables
if (panel1kilist[i].SelectedItem.ToString() == panel1kilist[j].SelectedItem.ToString())
{
if (check == false)
{
MessageBox.Show("match found");
}
check = true;
}
else
{
if (check1 == false)
{
MessageBox.Show("no match found");
}
check1 = true;
}
You define your bool variables before starting your for-loops. So whenever you set your variables check and check1 to true, the if conditions check == false and check1 == false will never return true anymore. So you will never get any message except the very first "Match found" and "no match found".
3. My proposed solution
Make use of the foreach-loop and break the loops once you found a match, after the loops just show the message. Code:
var matchFound = false;
foreach (var combobox in panel1kilist)
{
foreach (var comboboxToMatch in panel1kilist.Skip(1))
{
if (combobox.SelectedItem.ToString() == comboboxToMatch.SelectedItem.ToString())
{
matchFound = true;
// Stops the inner loop in case of a match
break;
}
}
// Stops the outer loop in case of a match
if(matchFound)
{
break;
}
}
if(matchFound)
{
MessageBox.Show("match found");
}

Related

Image index not always changes

So, I'm trying to code simple memory game in Windows Forms but I've met a simple problem that somehow I can't pass.
This is a single button code(they all look very similar):
Match CheckForMatches = new Match();
private void Pathfinder_Click(object sender, EventArgs e)
{
CheckForMatches.AddButton(Pathfinder);
CheckForMatches.Matched();
}
(where CheckForMatches object is shared between all buttons in given form)
And here are called methods codes:
public void AddButton(Button newButton)
{
if (firstButtonPressed == null)
{
firstButtonPressed = newButton;
firstButtonPressed.ImageIndex = 0; //uncovering card
}
else
{
secondButtonPressed = newButton;
secondButtonPressed.ImageIndex = 0;
Thread.Sleep(1000);
}
}
public bool Matched()
{
if (firstButtonPressed != null && secondButtonPressed != null )
{
if (firstButtonPressed.Name != secondButtonPressed.Name)
{
if (firstButtonPressed.Text == secondButtonPressed.Text)
{
DisposeButtons();
return true;
}
else
{
NullButtons();
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
Now this method call one of two others, depending if last 2 clicked buttons are a pair or not(basing on their name and text):
This in case of succes disposes buttons and null Match class variables:
public void DisposeButtons()
{
firstButtonPressed.Dispose();
secondButtonPressed.Dispose();
firstButtonPressed = null;
secondButtonPressed = null;
}
This is case of failure covers cards and also nulls Match class variables:
public void NullButtons()
{
firstButtonPressed.ImageIndex = 1; //covering cards
secondButtonPressed.ImageIndex = 1;
firstButtonPressed = null;
secondButtonPressed = null;
}
The point is, no matter where I place Thread.Sleep(1000), user can never see second card he choses. He always see the first one and then, when he choses second one, either both cards are disposed(app is freezing due to that delay) or the first one becomes covered, without uncovering the second one.
EDIT:
I added output to debugger window, so now method AddButton looks like this:
public void AddButton(Button newButton)
{
if (firstButtonPressed == null)
{
firstButtonPressed = newButton;
Debug.WriteLine("Before index chaning: " + firstButtonPressed.ImageIndex);
firstButtonPressed.ImageIndex = 0; //uncovering card
Debug.WriteLine("After index chaning: " + firstButtonPressed.ImageIndex);
}
else
{
secondButtonPressed = newButton;
Debug.WriteLine("Before index chaning: " + secondButtonPressed.ImageIndex);
secondButtonPressed.ImageIndex = 0;
Debug.WriteLine("After index chaning: " + secondButtonPressed.ImageIndex);
Thread.Sleep(1000);
}
}
I can see there, that ImageIndex buttons' property actually changes between 1 and 0. However, in practice, it's only visible when first if block of this method is called. I would be grateful for answering why and how to change that.
Okay, I found out maybe not best solution, but it works. I simply forced button to refresh.
Correct form of AddButton method is:
public void AddButton(Button newButton)
{
if (firstButtonPressed == null)
{
firstButtonPressed = newButton;
Debug.WriteLine("Before index changing: " + firstButtonPressed.ImageIndex);
firstButtonPressed.ImageIndex = 0; //uncovering card
Debug.WriteLine("After index changing: " + firstButtonPressed.ImageIndex);
}
else
{
secondButtonPressed = newButton;
Debug.WriteLine("Before index changing: " + secondButtonPressed.ImageIndex);
secondButtonPressed.ImageIndex = 0;
secondButtonPressed.Refresh();
Debug.WriteLine("After index changing: " + secondButtonPressed.ImageIndex);
Thread.Sleep(500);
}
}
I hope it will be useful for someone one day.

Additional information: InvalidArgument=Value of '0' is not valid for 'index'

I realize this may look like a duplicate question (I've seen many other questions asking about this error), however I cannot find an answer which explains the issue I'm having. The error is provoked by a call to
invList.SelectedItems[0].Text //invList is a ListView
From what I've read, the error when provoked by this instruction is indicative of attempted access to an empty list (or array?) of selected items in the ListView. However, the ListView I am attempting to access is populated with items at the time of the instruction's execution. Here are the methods in which I issue this instruction:
Method #1: deleteItem
public bool deleteItem()
{
if (invList.SelectedItems.Count == 0) //if no item selected...
{
MessageBox.Show("Error: No item selected", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
else
{
DialogResult dialogResult = MessageBox.Show(
"Are you sure you want to delete item: " + invList.SelectedItems[0].Text + "?",
"Error", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (dialogResult == DialogResult.Yes)
{
for (int i = 0; i < itemRecords.Count; i++)
{
if ((itemRecords[i].id.ToString() == invList.SelectedItems[0].Text) && (itemRecords[i].practice == clinicName))
{
itemRecords.Remove(itemRecords[i]);
listRefresh();
}
}
return true; //return true to indicate that data has been edited
}
return false; // return false to indicate that nothing has changed
}
}
Method #2: updateItem
public bool updateItem()
{
if (invList.SelectedItems.Count == 0) //if no item selected
{
MessageBox.Show("Error: No item selected", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return false;
}
else
{
for (int i = 0; i < itemRecords.Count; i++)
{
//if id == the id of the selected item
if((itemRecords[i].id.ToString() == invList.SelectedItems[0].Text) && (itemRecords[i].practice == this.Text))
{
ItemAddition itemAddition = new ItemAddition(itemRecords, itemRecords[i], this);
itemAddition.ShowDialog();
}
}
return true;
}
}
listRefresh:
public void listRefresh()
{
invList.Items.Clear();
loadItems();
}
loadItems:
private void loadItems()
{
foreach (Record r in itemRecords)
{
if (r.practice == clinicName)
invList.Items.Add(r.ToString());
}
}
The error is invoked when the first method is called, but NOT when the second method is called. This inconsistency is the reason for my confusion. Is there some reason this error would only occur in the first method?
Move refreshing method after remove items. If you move item and rebind, then you will lost selection.
for (int i = 0; i < itemRecords.Count; i++)
{
if ((itemRecords[i].id.ToString() == invList.SelectedItems[0].Text) && (itemRecords[i].practice == clinicName))
{
itemRecords.Remove(itemRecords[i]);
//listRefresh();
}
}
listRefresh();
return true;

Weird behavior in combobox C#

I have a weird behavior in my combobox. I have two combobox, one is cboSede an the other is cboGroup. CboSede enable cboGroup. I have already done this in other forms but here I get this message: ArgumentOutOfRangeException was unhandled by user code. The idea is if the user does not choose any value in cboSede then cboGroup is not enabled and in the other hand, if the user choose a valid option in cboSede, cboGroup is enable.
This is my code:
The SelectedIndexChanged of cboSede
private void cboSede_SelectedIndexChanged(object sender, EventArgs e)
{
if (Util.Security.ConexionBD)
{
if (Convert.ToInt32(cboSede.SelectedIndex) == 0 || Convert.ToInt32(cboSede.SelectedIndex) == -1)
{
cboGroup.Enabled = false;
cboGroup.SelectedIndex = 0;
}
else
{
this.FillGroupCombo();
cboGroup.Enabled = true;
}
}
else
MessageBox.Show("Error", "Warning",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
the FillGroupCombo function
private void FillGroupCombo()
{
try
{
Entity.Group objGroup = new Entidad.Group ();
objGroup .IdSede = Convert.ToInt32(cboSede.SelectedValue);
objGroup = Control.Group.ListBySede(objGroup );
if (objGroup != null && objGroup.ListGroup.Count > 0)
{
Entity.Group objMsje = new Entity.Group();
objMsje.IdGroup = -1;
objMsje.Name= "--- Select group ---";
objGroup.ListGroup.Insert(0, objMsje);
}
else
{
Entity.Group objMsje = new Entity.Group();
objMsje.IdGroup = 0;
objMsje.Name= "-- No groups found --";
objGroup.ListGroup.Insert(0, objMsje);
}
Util.Utilitario.FillCombo(objGroup.ListGroup, this.cboGroup, "IdGrupo", "Name");
}
catch (Exception ex)
{
Util.Security.Insert(ex);
Util.Security.SaveLog(ex.Message);
}
}
Any idea about why this happens?
This one
if (Convert.ToInt32(cboSede.SelectedIndex) == 0 || Convert.ToInt32(cboSede.SelectedIndex) == -1)
{
cboGroup.Enabled = false;
cboGroup.SelectedIndex = 0;
}
Will kill the code when SelectedIndex == -1 and you actually have no item in your comboBox (when index = 0, it is OutOfRange)
you can give an if condition if you want
if (cboGroup.Items.Count > 0)
cboGroup.SelectedIndex = 0;
This way, it first check of the comboBox really have anything. And if it doesn't then it won't produce OutOfRange error

How to add condition to loop

I wanna check a value in array and if it exist return the value else return the message and read another value from array. add
else
{
MessageBox.Show("This Item ID Does Not Exist");
}
but the problem is when the the value is not in array, it want to show the message for 1258038 times.
how can I check the value (input) and if it exists, i can continue and if it does not exist in array , it returns back and read another value (input can be several values that must read one by one)
for (int cun = 0; cun < ItemIdNumber.Length; cun++)
{
int Item_Id = Convert.ToInt32(ItemIdNumber[cun]);
for (int yyu = 0; yyu <= 1258038; yyu++)
{
int weer = c[yyu];
if (weer == Item_Id)
{
itemseq = yyu;
}
else
{
MessageBox.Show("This Item ID Does Not Exist");
}
}
float[] i_ff = b[itemseq];
for (int ii = 0; ii < i_ff.Length; ii++)
{
.......
Use break to leave the loop early. You'll also need to change your logic a bit so you're not displaying a message in every iteration. This is just one possibility:
int? itemseq = null;
for (...) // outer loop
{
...
for (...) // inner loop
{
if (weer == Item_Id)
{
itemseq = yyu;
break;
}
}
if (!itemseq.HasValue)
MessageBox.Show("This Item ID Does Not Exist");
...
}
I think with a little bit of thought, you could make this more readable.
You've got two collections to search - ItemIdNumber and c.
You're looking for the first value in ItemIdNumber that matches an item in the first 1258038 values of c.
Something like this LINQ statement maybe, although I'm not exactly sure what type your collections are. And I'm writing this free-hand, so it might not compile as-is. Should give you something to work with though.
var id = (from id in ItemIdNumber
join cid in c.Take(1258038) on Convert.ToInt32(id) equals cid
select cid).FirstOrDefault();
if (!id.HasValue)
MessageBox.Show("This Item ID Does Not Exist");
for (int cun = 0; cun < ItemIdNumber.Length; cun++) {
...
boolean found = false;
for (int yyu = 0; yyu <= 1258038; yyu++) {
int weer = c[yyu];
if (weer == Item_Id)
{
itemseq = yyu;
found = true;
break;
}
}
if(!found) {
MessageBox.Show("This Item ID Does Not Exist");
}
...
}

dropdownlist items find by partial value

To find an item (and select it) in a dropdownlist using a value we simply do
dropdownlist1.Items.FindByValue("myValue").Selected = true;
How can I find an item using partial value? Say I have 3 elements and they have values "myValue one", "myvalue two", "myValue three" respectively. I want to do something like
dropdownlist1.Items.FindByValue("three").Selected = true;
and have it select the last item.
You can iterate from the end of the list and check if value contains the item (this will select the last item which contains value "myValueSearched").
for (int i = DropDownList1.Items.Count - 1; i >= 0 ; i--)
{
if (DropDownList1.Items[i].Value.Contains("myValueSearched"))
{
DropDownList1.Items[i].Selected = true;
break;
}
}
Or you can use linq as always:
DropDownList1.Items.Cast<ListItem>()
.Where(x => x.Value.Contains("three"))
.LastOrDefault().Selected = true;
You can iterate the items in your list, and when you find the first one whose items's string contains the pattern, you can set its Selected property to true.
bool found = false;
int i = 0;
while (!found && i<dropdownlist1.Items.Count)
{
if (dropdownlist1.Items.ToString().Contains("three"))
found = true;
else
i++;
}
if(found)
dropdownlist1.Items[i].Selected = true;
Or you could write a method (or extension method) that does this for you
public bool SelectByPartOfTheValue(typeOfTheItem[] items, string part)
{
bool found = false;
bool retVal = false;
int i = 0;
while (!found && i<dropdownlist1.Items.Count)
{
if (items.ToString().Contains("three"))
found = true;
else
i++;
}
if(found)
{
items[i].Selected = true;
retVal = true;
}
return retVal;
}
and call it like this
if(SelectByPartOfTheValue(dropdownlist1.Items, "three")
MessageBox.Show("Succesfully selected");
else
MessageBox.Show("There is no item that contains three");
Above mentioned answers are perfect, just there are not case sensitivity proof :
DDL.SelectedValue = DDL.Items.Cast<ListItem>().FirstOrDefault(x => x.Text.ToLower().Contains(matchingItem)).Text

Categories