I have a for loop, and each time through I invoke the same method. I need to find a way to learn what the previous equation was. I have to find this without using the value of incrementation. for example:
for (int i = 0; i < 101; i++) {
checkBox[i].Click += new System.EventHandler(checkBoxMethod); }
Somehow checkBoxMethod should get the previous function in this case for instance:
checkBox[50].Click
Inside of the for loop, also set the tag of each checkbox. I am assuming you are using Windows Forms here. So, here is what the modified for loop would look like:
for (int i = 0; i < 101; i++) {
checkBox[i].Click += new System.EventHandler(checkBoxMethod);
checkBox[i].Tag = i;
}
Then in your event handler you can cast the sender variable to a checkbox like so:
void checkBoxMethod (object sender, EventArgs args)
{
CheckBox box = (CheckBox)sender;
int number = (int)box.Tag;
}
Whatever 'i' was at the time of creating that checkbox's event handler will be retrieved in the variable 'number' and you can use it however you want.
Instead of using a for loop, use recursion and pass the current count into the function:
void checkBoxMethod (object sender, EventArgs args)
{
CheckBox box = (CheckBox)sender;
int number = (int)box.Tag;
myRecursiveMethod(number);
}
private void myRecursiveMethod(int count)
{
//do whatever stuff I need to do
if (!timeToExitTheMethod)
myRecursiveMethod(count++);
}
You've given us no explanation of exactly what you are doing in your for loop and your question doesn't make a lot of sense (i.e. what are the CheckBoxes you allude to?), so I can't be very specific with my code example. Note that you'll have to code an exit point for the recursive method (otherwise it will be called until you get a stack overflow).
If you are simply looking to count the number of times a function has been called then do this:
public class MyClass
{
private int _myCounter = 0;
void checkBoxMethod (object sender, EventArgs args)
{
CheckBox box = (CheckBox)sender;
//do whatever you need to do
_myCounter++;
}
}
If you be more specific with your requirements then we can be more specific with our suggestions.
You can pass the required information to handler using lambda experssions.
for (int i = 0; i < n; i++) {
int number = i;
buttons[i].Click += (sender, args) => OnButtonClick(sender, args, number);
}
...
private void OnButtonClick(object sender, RoutedEventArgs e, int number) {
MessageBox.Show(number.ToString(CultureInfo.InvariantCulture));
}
Related
I am looking for the best practice to pause foreach or for loops (it has to wait until the user inserts text and presses a button to confirm).
private void btnStarten_Click(object sender, RoutedEventArgs e)
{
//using a foreach loop blocks the UI I read?
for (int i = list.Count; i >= 0; i--)
{
//Here I want to pauze the loop and being able to insert a valeu in a textbox after I
//clicked another button to confirm, I resume the Loop
}
}
My final code looked like this:
private void btnResultaat_Click(object sender, RoutedEventArgs e)
{
if (leerlingIngave.RandomLijst.Count - 1 == leerlingIngave.AntwoordEnUitkomstLijst.Count)
//I compair my 2 lists to eachother (theRandom list was already filled)
{
btnResultaat.IsEnabled = false; // I ended the loop by disabeling the button
leerlingIngave.VerderZettenLoop();
}
else
{
leerlingIngave.VerderZettenLoop();
}
}
public void VerderZettenLoop() // Add object to the list
{
AntwoordEnUitkomstLijst.Add(new LeerlingModel(Uitkomst, Antwoord));
}
I would recommend separating out your code a bit, rather than having a loop that "waits".
For example:
private int _loopIndexer = 0;
public void ContinueLoop()
{
for (; _loopIndexer < list.Count; ++_loopIndexer)
{
if (list[_loopIndexer].Property == "value")
{
// on a matching condition do something and then exit the method
++_loopIndexer; // we need to increment the position before we exit the method
return;
}
}
}
private void btnStarten_Click(object sender, RoutedEventArgs e)
{
// reset to the beginning
_loopIndexer = 0;
ContinueLoop();
}
private void btnContinue_Click(object sender, RoutedEventArgs e)
{
// If the end of the loop is reached, quit (or do whatever)
if (_loopIndexer + 1 == list.Count)
{
// _loopIndexer = 0; // you could reset it to 0 if you wanted to loop again
return;
}
ContinueLoop();
}
The idea is that btnStarten will start the loop, and the loop will stop whenever a condition is met. Then, when you click the Continue button, it will continue the loop if there are any list items left.
Try it online
I am fairly new to C#.
I trying to create a Combo Box that displays numbers from 1-100 generated from the method below. I am using an example that found on the internet and modifying it to meet my needs.
I can't get my combo box to display anything. Please offer suggestions or a better way to execute my intended goal.
private void Range()
{
ArrayList arr = new ArrayList();
for (int i = 0; i <= 100; i++)
{
arr.Add(i);
}
}
public void FillInComboBox(ComboBox target, int start, int end)
{
for(int i = start; i <= end; i++)
{
target.Items.Add(i);
}
}
Usage
private void Form2_Load(object sender, EventArgs e)
{
FillInComboBox(comboBox1, 0, 100);
}
I am trying to make my button take input from a textbox and add it to the index. The problem is that with everything I have tried, I cannot get it to give a unique value to each position in the index.
private void addBtn_Click(object sender, EventArgs e)
{
for (int i = 0; i < nums.Length; i++)
{
if (nums[0] == 0)
{
nums[0] = int.Parse(inputText.Text);
i++;
}
if (nums[1] == 0)
{
nums[1] = int.Parse(inputText.Text);
i++;
}
}
MessageBox.Show(nums[i].ToString());
}
Right now my code inserts the value to both index positions instead of assigning a value to position 0 and then allowing the user to insert a different value into position 1 and so on and so on.
It's not clear what your intent is, but it looks like you might be trying to add numbers to an array. This code will assign the parsed string to the first item in the array that isn't zero.
private void addBtn_Click(object sender, EventArgs e)
{
int i = 0;
for (; i < nums.Length; i++)
{
if (nums[i] == 0)
{
nums[i] = int.Parse(inputText.Text);
break;
}
}
MessageBox.Show(nums[i].ToString());
}
But this would be a better way, because the user might type "0":
private int _lastUsedIndex = -1;
private void addBtn_Click(object sender, EventArgs e)
{
var number = int.Parse(inputText.Text);
// Increment by one
++_lastUsedIndex;
nums[_lastUsedIndex] = number;
MessageBox.Show(number.ToString());
}
But still, arrays aren't a great idea: They can't grow as you add things. First they're bigger than you need, then suddenly they're too small and you crash. We have better options now. Unless your teacher insists that you must use an array, use List<int> instead. In this version, we'll also use a different way to parse the number, which won't crash if the user types "LOLWUT?!?!" instead of a number:
private List<int> nums = new List<int>();
private void addBtn_Click(object sender, EventArgs e)
{
int number;
if (int.TryParse(inputText.Text, out number))
{
nums.Add(number);
MessageBox.Show(number.ToString());
}
else
{
MessageBox.Show(inputText.Text + " isn't a number, smart guy.");
}
}
This is what i want to do:
....
for(i=0;i<=99;i++)
{
btn[i].Click += new EventHandler(btn_Clicked,i);
}
}
private void btn_Clicked(object sender, EventArgs e,int i)
{
compute((Button)sender, picRetrieved[i]);
}
Please help. It is showing error. But, I want to send the value of i for further processing. Is there any way to do it?
Thank you.
Thanks to closures and anonymous functions you can do something similar:
for(int i=0;i<=99;i++)
{
int j = i;
btn[i].Click += (sender, e) =>
{
// Very important! Here use only j, not i!
compute((Button)sender, picRetrieved[j]);
};
}
There is a small "problem" (that isn't a problem, it's how they are done) so that you mustn't use the i variable inside the anonymous function, but if you copy it somewhere else (j for example) then you can use j.
You can't. The signature of the event handler is fixed, you can't change it.
In this case, you could use an anonymous delegate to get what you want.
for(i = 0; i <= 99; i++)
{
int dummy = i;
btn[i].Click += delegate(object sender, EventArgs e)
{
compute(btn[dummy], picRetrieved[dummy]);
}
}
Another option is to 'tag' the button:
for(i = 0; i <= 99; i++)
{
btn[i].Click += btn_Clicked;
btn[i].Tag = i;
}
private void btn_Clicked(object sender, EventArgs e,int i)
{
Button b = (Button)sender;
int i = (int)b.Tag;
compute(b, picRetrieved[i]);
}
I have a class called "Player" with a constructor that takes 2 strings and an int.
These are declared in Textboxes on a form, with each team (Home H / Away A) having a different name, and each name type (Last L / First F) adding to the textbox's name. therefor giving a unique name such as txtFHome1.
In a foreach loop I want to create a new Player with the details of the textboxes on a page.
This is what I have got so far.
List <Player> HomeTeam = new List<Player>
private void btnAccept_Click(object sender, EventArgs e)
{
foreach (Control c in this.Controls)
{
for (int i = 0; i < 10; i++)
{
HomeTeam.Add (new Player(c.Name.EndsWith("FHome"+i),c.Name.EndsWith("LHome"+i),c.Name.EndsWith("upDownH"+i)));
}
}
}
any help?
From you post I understand that there are always 3 controls for 11 players, so there is no need to iterate trough all Controls in the form.
private void btnAccept_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
var player = new Player(((TextBox)this.Controls.FindControl("FHome" + i)).Text, ((TextBox)this.Controls.FindControl("LHome" + i)).Text, ((NumericUpDown)this.Controls.FindControl("upDownH" + i)).Value);
HomeTeam.Add(player);
}
}
The first way is to use dictionaries with all controls. It is the fastest and easiest way.
Dictionary<int, TextBox> FHome;
Dictionary<int, TextBox> LHome;
Dictionary<int, TextBox> upDownH;
You should add the controls like this:
FHome.Add(0, textBoxLHome0);
FHome.Add(1, textBoxLHome1);
Then in your code you can use
for (int i = 0; i < 10; i++)
{
HomeTeam.Add (new Player(FHome[i].Text, LHome[i].Text, upDownH[i].Text));
}
try this:
Controls.OfType<TextBox>().ToList().ForEach((textbox) =>
{
for (int i = 0; i < 10; i++)
{
textbox.Text = "your text";
}
});
remember to include using System.Linq
I advice you to at lease try an encapsulate the three textboxes into a single UserControl like so:
public partial class ControlPlayerParams : UserControl {
public string Param1 { get { return this.textBox1.Text; } }
public string Param2 { get { return this.textBox2.Text; } }
public string Param3 { get { return this.textBox3.Text; } }
public ControlPlayerParams() {
this.InitializeComponent();
}
}
That way, you could at least do what you wanted to do more fluently and more safely (plus you get to modify just one UserControl in case you need something changed (Validation ??)):
foreach (ControlPlayerParams cpp in this.Controls.OfType<ControlPlayerParams>())
HomeTeam.Add(new Player(cpp.Param1, cpp.Param2, cpp.Param3));
BUT you should rethink the architecture of the app a bit if you ask me.