ListBox Selection keeps looping - c#

When I select an item from my list, the whole selection-process goes on twice.
private void serving_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
try
{
Debug.WriteLine("Serving added to diary");
login(null, null);
}
catch (WebException)
{
Debug.WriteLine(e.Error);
}
ServingList.SelectedIndex = -1;
}
When I leave out ServingList.SelectedIndex = -1; the process goes on once. But I need the selected index back to -1.
What am I missing?
Handler on SelectionChanged:
private void ServingList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Debug.WriteLine("\n[#] ServingList_SelectionChanged");
Debug.WriteLine("Selected item:" + ServingList.SelectedIndex);
Debug.WriteLine("ID of latest TP: " + tp.id);
String itemid = tp.id;
Produkt temp = (Produkt)ServingList.SelectedItem;
if (servingid.Length < 1)
{
servingid = temp.servingid;
}
WebClient addserving = new WebClient();
addserving.Credentials = new NetworkCredential(username.Text, passwort.Password);
addserving.Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
addserving.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
addserving.UploadStringAsync(new Uri("http://fddb.info/api/v8/diary/add_item.xml?apikey=ICPOKUI83555PU43"), "&item_id=" + itemid + "&serving_id=" + servingid);
addserving.UploadStringCompleted += new UploadStringCompletedEventHandler(serving_UploadStringCompleted);
Pivot.SelectedIndex = 0;
}

You are causing an infinate loop.
You have your list box and changing it causes an action
Change X > Action X > Handle X > Change X (-1) > Action X
Etc.
You need to have some form of break to the loop for a condition
private void serving_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
//Break condition
if (ServingList.SelectedIndex != -1)
{
try
{
Debug.WriteLine("Serving added to diary");
login(null, null);
}
catch (WebException)
{
Debug.WriteLine(e.Error);
}
ServingList.SelectedIndex = -1;
}
}
By doing this, you only set it to -1 when you need to, otherwise it will continuously keep setting the selected index to -1 even though it is already in fact set.

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.

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.

How to Load all the Objects in an Array List

I am trying to figure out how to load through an Array List of Objects. I am able to retrieve the last Object in the Array, but it will not let me Load any other Object after that. here is part of the code I have. As you can see it saves the object to the List, but when I click the loadLastBtn it will only load the most recent entry and if I hit it again after that nothing loads.
List<Members> lstMembers = new List<Members>();
private int hold;
private void submitBtn_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(firstNameTxt.Text) || string.IsNullOrEmpty(lastNameTxt.Text)
|| string.IsNullOrEmpty(userNameTxt.Text) ||
string.IsNullOrEmpty(passwordTxt.Text) || string.IsNullOrEmpty(confPassTxt.Text)
|| string.IsNullOrEmpty(majorBox.Text) || string.IsNullOrEmpty(specialtyBox.Text))
{
MessageBox.Show("You must enter in all fields before moving forward");
}
else
{
Members m1 = new Members(firstNameTxt.Text, lastNameTxt.Text, userNameTxt.Text,
passwordTxt.Text, confPassTxt.Text, majorBox.Text,
specialtyBox.Text);
lstMembers.Add(m1);
}
}
private void loadLastBtn_Click(object sender, EventArgs e)
{
firstNameTxt.Text = lstMembers[hold].FirstName;
lastNameTxt.Text = lstMembers[hold].LastName;
userNameTxt.Text = lstMembers[hold].UserName;
passwordTxt.Text = lstMembers[hold].Password;
confPassTxt.Text = lstMembers[hold].ConfPassword;
majorBox.Text = lstMembers[hold].Major;
specialtyBox.Text = lstMembers[hold].Specialty;
hold++;
}
I have edited my answer. this will now print each user one by one each time I hit loadLastBtn, but it does show them from the first user to the last, where I need it to shower the last user to the first.
What you need is something like this:
// -1 Indicates that you should start at the end of the list
int index = -1;
private void loadButton_Click(object sender, EventArgs e)
{
if (members != null && members.Count > 0) // Avoid accessing if list is empty or null
{
if (index == -1)
index = members.Count - 1;
firstNameTxt.Text = lstMembers[index].FirstName;
lastNameTxt.Text = lstMembers[index].LastName;
userNameTxt.Text = lstMembers[index].UserName;
passwordTxt.Text = lstMembers[index].Password;
confPassTxt.Text = lstMembers[index].ConfPassword;
majorBox.Text = lstMembers[index].Major;
specialtyBox.Text = lstMembers[index].Specialty;
if (index == 0) // Reached beginning of array
index = -1; // Indicate that next time the last element must be accessed
else
--index;
}
}
private int hold = lstMembers.Count -1;
private void loadLastBtn_Click(object sender, EventArgs e)
{
firstNameTxt.Text = lstMembers[hold].FirstName;
lastNameTxt.Text = lstMembers[hold].LastName;
userNameTxt.Text = lstMembers[hold].UserName;
passwordTxt.Text = lstMembers[hold].Password;
confPassTxt.Text = lstMembers[hold].ConfPassword;
majorBox.Text = lstMembers[hold].Major;
specialtyBox.Text = lstMembers[hold].Specialty;
hold--;
}

Thread Method Outrunning ProgressChanged

I have a simple application that executes a function in a separate thread via a BackgroundWorker and am running into issues. I am collecting a string array of values and passing that back to my ProgressChanged event via the ReportProgress method and I'm running into a problem where the thread continues and is so fast, it outruns the ProgressChanged event and overwrites the values before they can be added to a grid. Below is my code...
Button Click Event Fires my thread...
private void LoadButton_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(WorkingPathTextBox.Text))
{
this.dataGridView1.Rows.Clear();
this.progressBar1.Visible = true;
this.LoadButton.Visible = false;
this.BrowseButton.Enabled = false;
this.WorkingPathTextBox.Enabled = false;
this.CancelBtn.Visible = true;
this.ProcessingLabel.Visible = true;
beginTime = DateTime.Now;
WorkflowCleanup wc = new WorkflowCleanup();
wc.WorkflowPath = this.WorkingPathTextBox.Text;
backgroundWorker1.RunWorkerAsync(wc);
}
}
In the DoWork, it loads the class where my work exists...
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
System.ComponentModel.BackgroundWorker worker;
worker = (System.ComponentModel.BackgroundWorker)sender;
// Get the Words object and call the main method.
WorkflowCleanup wc = (WorkflowCleanup)e.Argument;
wc.LoadAssemblies(worker, e);
wc.LoadDataDefinitions(worker, e);
wc.LoadDataDefinitionsDirty(worker, e);
wc.LoadProcesses(worker, e);
wc.LoadProcessesDirty(worker, e);
wc.LoadWorkflows(worker, e);
// wc.UpdateWorkflows(worker, e);
}
WorkflowCleanup class...the ReportProgress in stuck right in the middle of the try/catch because I could not figure out what was causing the problem. So, I moved it in the try, and even had to add a Thread.Sleep(100) to slow the process down to give the ProgressChanged event time enough to add the row of data I passed it to the grid before it was overridden...
namespace WorkflowMaintenance
{
public class WorkflowCleanup
{
private int errorCount = 0;
private int fixCount = 0;
public class Workflow
{
// code truncated
}
public class WorkflowAssembly
{
// code truncated
}
public class DataDefinition
{
// code truncated
}
public class CurrentState
{
public int Percentage;
public string StateString;
public List<string[]> ProcessResults;
public string[] Result;
public int ErrorCount;
public int FixCount;
}
public void LoadAssemblies(System.ComponentModel.BackgroundWorker worker, System.ComponentModel.DoWorkEventArgs e)
{
CurrentState state = new CurrentState();
fixCount = 0;
errorCount = 0;
string[] asmbfiles = System.IO.Directory.GetFiles(WorkflowPath + "\\Assemblies", "*.asmb", System.IO.SearchOption.AllDirectories);
int asmbIndex = 0;
Assemblies = new List<WorkflowAssembly>();
// Assemblies (NEW)
foreach (string asmb in asmbfiles)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
else
{
//results = new List<string[]>();
asmbIndex += 1;
int percentage = (asmbIndex * 100) / asmbfiles.Length;
state.StateString = string.Format("Loading Assemblies... {0}%", percentage);
state.Percentage = percentage;
try
{
XDocument xdoc = XDocument.Load(asmb);
XElement asmbElement = xdoc.Descendants(wf + "assembly").First();
XElement asmbTypes = asmbElement.Element(wf + "types");
string asmbid = asmbElement.Attribute("id").Value;
string asmbname = asmbElement.Element(wf + "name").Value;
string asmbpath = asmbElement.Element(wf + "assemblyPath").Value;
Assemblies.Add(new WorkflowAssembly() { ID = asmbid, Name = asmbname, FileName = asmb, AssemblyPath = asmbpath, Types = asmbTypes });
//results.Add(new string[] { "SUCCESS", "ASSEMBLY PROCESSED SUCCESSFULLY", asmbname, asmbid, null, asmb });
state.Result = new string[] { "SUCCESS", "ASSEMBLY PROCESSED SUCCESSFULLY", asmbname, asmbid, null, asmb };
fixCount += 1;
//if (results != null && results.Count > 0)
//{
// state.ProcessResult = results;
//}
state.FixCount = fixCount;
state.ErrorCount = errorCount;
worker.ReportProgress(percentage, state);
Thread.Sleep(100);
}
catch (Exception)
{
// need to report the exception...
errorCount += 1;
}
finally
{
//if (results != null && results.Count > 0)
//{
// state.ProcessResult = results;
//}
//state.FixCount = fixCount;
//state.ErrorCount = errorCount;
//worker.ReportProgress(percentage, state);
}
}
}
}
}
}
ProgressChanged Event...
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// This method runs on the main thread.
WorkflowCleanup.CurrentState state = (WorkflowCleanup.CurrentState)e.UserState;
this.progressBar1.Value = state.Percentage;
this.ProcessingLabel.Text = state.StateString;
this.errorLabel.Text = string.Format("Errors: {0}", state.ErrorCount);
this.fixLabel.Text = string.Format("Fixed: {0}", state.FixCount);
this.ElapsedTimeLabel.Text = string.Format("Elapsed Time: {0}", GetProgressElapsedString());
if (state.Result != null)
{
this.dataGridView1.Rows.Add(state.Result);
}
}
Problem...the problem is that if I have 3 files in the folder (named Assembly1, Assembly2, and Assembly3), the output in the grid shows that all three are named Assembly3. The only way I could fix this was to tell the Thread to sleep. This is not an option as I have to run this for a folder that has approximately 18,000 files and having to sleep for a millisecond would take forever. BUT, I need to get valid results. Help please :-)
Rather than creating the state object outside the loop and mutating it in each iteration, create a new instance for each iteration. This can be done by simply moving the declaration of the variable inside the loop.

Check if the selected item in a listbox contains specific characters

I am trying to figure out how to check if a listbox contains a specific string at a selected index, but i can't figure it out. It's an WAF project.
private void UpdateGUI(string name, double price)
{
//Check if the seat is already reserved??
//Check if the seat is already canceled??
int index = lstSeats.SelectedIndex;
if (index < 0)
{
MessageBox.Show("Please select an item in the list!");
return;
}
string strOut = string.Empty;
string strReserved = "Vacant";
if (rbtnReserve.Checked)
{
strReserved = "Reserved";
}
else
{
name = string.Empty;
price = 0.0;
}
strOut = string.Format("{0,3} {1,14} {2,11} {3,13:f2}", index + 1, strReserved, name, price);
lstSeats.Items.RemoveAt(index);
lstSeats.Items.Insert(index, strOut);
lblNumOfReservedSeats.Text = numOfReservedSeats.ToString();
lblNumberOfVacantSeats.Text = (totalNumOfSeats - numOfReservedSeats).ToString();
lblTotalNumOfSeats.Text = totalNumOfSeats.ToString();
}
Basically, i don't want to reserve a seat (in the cinema) that already has been reserved, or if the seat already is cancelled, i don't want to cancel it again. Any suggestions?
Or would it be better to check in the following code?:
private void btnOK_Click(object sender, EventArgs e)
{
string name = string.Empty;
double price;
bool inputOK = ReadAndValidateInput(out name, out price);
if (inputOK)
{
if (rbtnReserve.Checked)
{
numOfReservedSeats++;
}
else
{
numOfReservedSeats--;
}
UpdateGUI(name, price);
}
}
EDIT:
for WFA and checking if an item contains given string use this:
if (listBox1.SelectedIndex != -1)
{
int itemAtPostion = listBox1.SelectedIndex;
string reserved = "Reserved";
if (listBox1.Items[itemAtPostion].ToString().Contains(reserved))
{
MessageBox.Show("We are sorry, but this seat is reserved!");
//your code
}
}
You can use this one. It's so simple
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each i In ListBox1.Items
If i.ToString.Contains("your specific characters") Then
//what happen if it true
Else
//what happen if it false
End If
Next
//what happen when its finish work
End Sub
You can also use C#:
private void Button1_Click(object sender, EventArgs e)
{
foreach (var i in ListBox1.Items)
{
if (i.ToString().Contains("your specific characters"))
{
//what happen if it true
}
else
{
//what happen if it false
}
}
//what happen when its finish work
}

Categories