C# Increment for loop every time button is pressed - c#

I googled a few things before posting, but I couldn't find anything like this. Basically, I want to take text from a textbox, save as a variable (say history1) to then be able to call that in the future to display the text. I can do that, but what I'm stuck with is that I want 3 variables (history1, history2 and history3, for example) and each time the button is pressed the string is moved to the next variable.
For example, the button is pressed, the text is saved as variable history1. The text is changed and the button is pressed again, the text from history1 is moved to variable history2, and the new text is saved as history1. This would only need to work for 3 instances though, not infinitely, so when text is stored in history3 and the button is pressed the text is just overwritten.
The way I had thought of approaching this was:
string history1;
string history2;
string history3;
for (int i = 1; i < 4; i++)
{
history1 = txtOutput.Text;
btnToFile_Click()
{
history2=history1;
btnToFile_Click()
{
history3=history2;
}
}
}
However, this isn't going to work because the btnToFile_Click doesn't take any arguements. Is there an easier way to go about this or just a way to fix the method not taking arguements ?
Thanks in advance!

Make sure that you delcare history1, history2, and history3 on the form level (not inside any method).
Then, have the following code inside the handler of the click event of the button:
history3 = history2;
history2 = history1;
history1 = txtOutput.Text;

You don't need to call the btnToFile_Click() method multiple times in your loop, just move the text from end textbox to another in reverse order. Nor do you need a loop because you only have three textboxes.
Why reverse order? So you move the value to the next textbox before it is overwritten by the new value.
So:
history3 = history2;
history2 = history1;
history1 = txtOutput.Text;

btnToFile_Click() is a Click event handler for btnToFile (a button). You're not supposed to call that method yourself, it's called by the UI framework (say WPF or WinForms etc.). By the way, it does receive a parameter, then event source (since you can assign the same event handler to multiple buttons and do something based on which one sent the event)

You can try saving in a string array and move the strings within it when you call the button clicked event

Related

Concatenate some strings into a global variable in C#

i'm having a problem . I'm trying to make an application in C# (Windows Form Application) and i'm stuck into something.
I want to do a log-in form like in the photo. For username i'm having a combo-box where i can choose the user , but for password i want to place some buttons(like in the photo) , and when i press the button 1 for example , i want to have a string which is 1 .After that i will place 2 ,and i want to concatenate 1 and 2 into that string . Do you know how can i do that
In your case, I believe you have one event for each button. In each event you could just sum the values to a global variable or directly change the textbox. Like this:
txtPassword.Text += "0"; //the 0 button
It will change the textbox value and when you click "Sign in" you can get the txtPassword.Text as the final string.
You can also declare a string or StringBuilder globally and append the value in every button click, tho this won't change the textbox text directly.
Use a StringBuilder to concatenate strings.
StringBuilder builder = new StringBuilder();
builder.Append(a);// where "a" is your input character
And whenever you get a new character input call builder.Append(a);
In the end you get your final string by calling builder.ToString();
As a variation on the answer from #LeoFormaggi, you could have a single event handler for all the numeric buttons (i.e., one that every button's click handler points to). Then, in the handler:
var buttonText = (sender as Button)?.Text;
txtPassword.Text += buttonText ?? String.Empty;
Don't forget to make that textbox be a password field (by setting the PasswordChar property).
You don't want to bother with a StringBuilder here. It's normally the right tool for concatenating strings, but it buys you nothing in this case since you want the result to appear immediately in the text box. In this case it would simply add overhead for no good reason.
i want to thank you, i made my solution like this :
`private void nb6_Click(object sender, EventArgs e)
{
password_box.Text += "6";
}`
in every button event that i have, the password_box (which is my textbox) and i concatenate everytime the string that i want(in this case is number 6 )
Thank you and have a nice day . :)

Edit textbox in parallel to asynchronous updating

So in my project I have a few textBoxes that hold the coordinates of two corners (Latitude & Longitude). The textBoxes are updated by a timer (which gets a value from a server and sets the textBoxes if the value received is different from the current value). Problem is, I want the textBoxes to be available for manual editing; However if I'm in the middle of typing the number and the timer checks the current value he sees that it's a different thing from what the server returned and changes it immediately. Is there a way to check if the textBox is being edited at the moment, or a better way to solve this solution?
code (samples, the code is the same for the two corners):
if (northEastLatitude != double.Parse(neLatTB.Text)) //neLatTB is the textBox
neLatTB.Text = northEastLatitude.ToString();
else //No answer returned from the server so we need to reset the textBoxes
{
northEastLatitude = 0;
northEastLongitude = 0;
if(neLatTB.Text != "0")
neLatTB.Text = northEastLatitude.ToString();
if(neLngTB.Text != "0")
neLngTB.Text = northEastLongitude.ToString();
}
in addition, I have functions for TextChanged events for all of the textBoxes (so that when I set the coordinates manually it uploads them to the server). Is there any way to prevent this function from being called whenever I press the dot key? apparently it calls the event too (marks the ending of the text entering).
It really depends on your design but if you want to use TextBox to show updatable values and also make it possible to edit you have to suppress code from your timer to execute. WinForms TextBox doesn't have an option to show you if text is changing programmatically or by user interaction. You have to somehow make it by yourself.
There is plenty of ways to do that of courde. One way is to use Enter/Leave events to detect when your TextBox gets or loses focus. But there will be a need to click somwhere out from the control after edit.
Another one, and probably desired by you would be using TextChanged event preventing your timer from updating field until text in TextBox will be typed in full. I would do it something like that:
Fisrtly I would declare two bool variables for blocking parts of code from execution:
private bool _isDirty; // used when user types text directly
private bool _suppresTextChanged; // used when timer updates value programmatically
After that I would write TextBox.TextChanged event listener:
private void neLatTBTextChanged(object sender, EventArgs args)
{
if(_suppressTextChanged)
return;
_isDirty = true; // toggle dirty state
if(/* text has good format */)
{
// Upload changes to server
_isDirty = false; // end manual edit mode
}
}
And inside timer method i would set:
_suppresTextChanged = true; // on the beginning
if (northEastLatitude != double.Parse(neLatTB.Text)) //neLatTB is the textBox
neLatTB.Text = northEastLatitude.ToString();
else //No answer returned from the server so we need to reset the textBoxes
{
northEastLatitude = 0;
northEastLongitude = 0;
if(neLatTB.Text != "0")
neLatTB.Text = northEastLatitude.ToString();
if(neLngTB.Text != "0")
neLngTB.Text = northEastLongitude.ToString();
}
_suppresTextChanged = false; // after edit was made
Personally i think this design can lead to a lot of problems (consider what to do when user stops typing and leave the TextBox in _isDirty state etc...). Instead of using just TextBox I would add a Label to store data from timer (and probably data the user will type) and left TextBox just for entering user specific values.

AutoCompleteStringCollection with TextChanged Event

I'm currently using a text box to filter some entries. I have the display updating on the text box TextChanged event, so the user isn't hitting enter or pressing a button to begin filtering. I want to use an AutoCompleteStringCollection to remember entries typed into the text box; however, if I save every string from the text box when the TextChanged event is fired then it will store all the substrings of each filter term.
So for instance, if I typed the string "test" it would display:
"t"
"te"
"tes"
"test"
as recommended strings. I just want the last string added to the AutoCompleteStringCollection.
I've thought about two separate methods I could implement.
1) I could create a Task that waits "x" amount of time after the last TextChanged event before it adds the string to the AutoCompleteStringCollection. If I did this I would have to use a cancellationToken to cancel the Task every time the textChanged event fired. This is slightly more complicated because I'm using .NET 4.0.
2) I could also search through the AutoCompleteStringCollection every time a string is added and remove all substrings (that start at the beginning of the word). This may backfire if the user types in a more specific filter, but still wants to store the shorter one.
Is there a better way to go about doing this? Which method would you recommend?
There are two things to be aware of when trying to dynamically fill the AutoCompleteStringCollection. First is Microsoft's Resolution to the issue:
Do not modify the AutoComplete candidate list dynamically during key events. (MSDN)
Having said that, I was able to figure out a way to dynamically add elements to the list.
I ended up opting for a modified version of the Task implementation. Instead of using a CancellationToken and TokenSource I used a bool. My code ended up looking roughly like this:
private void AddSearchToDropDown ()
{
Task.Factory.StartNew (() =>
{
if (CanAdd && filterTxtBox.Text.Length > 2)
{
CanAdd = false;
Thread.Sleep (4000);
this.Invoke(new Action(() =>
{
filterTxtBox.AutoCompleteMode = AutoCompleteMode.None;
m_suggestedTests.Add (filterTxtBox.Text);
filterTxtBox.AutoCompleteMode = AutoCompleteMode.Suggest;
CanAdd = true;
}));
}
});
}
You'll also want code in your textChanged event handler that will set the bool to false whenever they begin typing in the textbox. That way you don't add the first entry 4 seconds after the first text changed event.
Second thing to be aware of is that there was a Violation Exception if I used AutoCompleteMode.SuggestAppend or Append.
While this isn't a complete answer I hope that it helps anyone that manages to find this question.

How to automatic add the first line of text from a list box to a text box

Right I have got a list box which contains a list of tracks and when the track is pressed it moves to a second list box, what I now need to happen is have the first item that's in the second list box move automatic to a text box.
This is my current code for the first move
private void genreListBox_DoubleClick(object sender, EventArgs e)
{
playlistListBox.Items.Add(genreListBox.SelectedItem);
}
I am thinking it should be something like this
presentlyPlayingTextBox.AppendText(playlistListBox.);
But I'm not sure how to add the first line without clicking it.
I have tried this but I get an error for the value.
presentlyPlayingTextBox.Text = playlistListBox.SelectedItem.Value;
Normally you would use something like the 'SelectedIndexChanged' or 'SelectedValueChanged' action of a listbox, otherwise events like DoubleClick will fail if the keyboard is used to change the selection.
Also that event should be triggered on the second listbox when it is changed by the first.
EDIT:
On a standard Listbox, there is no .SelectedItem.Value, only .SelectedItem.
However as a listbox holds objects, not just text, you need to say you want the text value.
presentlyPlayingTextBox.Text = playlistListBox.SelectedItem.ToString();
I don't know if I fully understand your question, but if you're just attempting to move the first item from ListBox_2 to a textbox, would the following work?
presentlyPlayingTextBox.Text = playlistListBox.Items[0]?.Value; // C# >= 6
presentlyPLayingTextBox.Text = ((playlistListBox.Items == null) ? playlistListBox.Items[0].Value : "" ); // C# < 6
You could also create your own delegate/event that would fire when the user did some action.

C# breaking out of a loop from separate class/method

I have a block of code that repeats using a "for" loop, and each loop constructs a form to display some text. Some thing like the shorthand code below.
Main()
{
For (int x: x<=20; x++)
{
createform(string[x]);
}
}
So for each loop a different string is passed to a method that will construct a form as below.
createform void (string input_)
{
...
code to build form and add a button "cancelbutton"
form.text = intput_
....
form.cancelbutton.Click += // and I want this to cause the original loop to end....
}
No I know I could use the button to make int x greater than 20 and that would end the loop, but I don't actually know what the max value will be as this is dynamic. Again I could work this out and do he same thing but it seems a bit "messy".
Is there a neater way to cause the button click to exit the loop. How about if the Createform method is in a separate class to main, does that make any difference?
If your loop runs from 0 to 20 (or even over 9000) the user won't be able to click the cancel button in time. In fact, since it is all on one thread, the loop will finish before the UI responds to the click, but maybe I have misunderstood. Could you just have a boolean flag which you check each time you enter the loop and set it to false once the user clicks the button?
Just add a variable and code the click event:
static bool clicked;
Main()
{
clicked = false;
For (int x: (x<=20) && !clicked; x++)
{
createform(string[x]);
}
}
public static void Click_Detector(object sender, EventArgs e) {
clicked = true;
}
Your routine would need to do something like this:
createform void (string input_)
{
...
code to build form and add a button "cancelbutton"
form.text = intput_
....
form.cancelbutton.Click += MainClass.Click_Detector;
}
You shouldn't be using a loop to create each form. Assuming you have a submit button. Every time the user clicks submit, you should explicitly show the next form. That way, if a user clicks cancel, you don't have to worry about the rest of the forms.
The first solution that comes to my mind is: return value of the method True/False and in foreach check for its return value, if False=> break.
Your psuedo code isn't indicating how you are showing the form in CreateForm(). Is this going to be a modal or non modal? It would have to be modal, otherwise, you'd just keep creating forms until the cows come home. Remember, adding a handler to the click button doesn't actually execute the handler method until the click button is clicked.
Presumably your click event handler could set the value of x to be greater than 20, but since you said you're not sure what the maximum is, you could have a do loop governed by a boolean flag, and your createform() could set the state of the flag.
I'd recommend rethinking your problem space, as this overall approach seems really convoluted. I don't understand your UI, but it seems like your intent is to have the user control the exit of an infinite loop, like those old RPGs that ask you "Do you want to go on an adventure Yes/No", and it would continue asking you until you hit "Yes". These are pointless and confusing.
Add a boolean to the class and have the click event set the boolean value. Then you can break from the loop. However, if your real world use is the question above I would agree with the answer given by mikerobi.
One good solution would be to use the CancelAsync() method of the BackgroundWorker class: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.cancelasync.aspx
If you don't want to work with a separate thread to improve the performance, that I don't recommend, is to set a class level boolean value when the button clicked, then the for loop checks that boolean value in each next process.

Categories