I have two text box and i want to calculate each text box when the other changed.but my program fall into a loop.
private bool suspendEvents = false;
private void txtYourPercent_ValueChanged(object sender, EventArgs e)
{
if (suspendEvents)
return;
suspendEvents = true;
txtMyPercent.value = 100 - txtYourPercent.value;
suspendEvents = false;
}
private void txtMyPercent_ValueChanged(object sender, EventArgs e)
{
if (suspendEvents)
return;
suspendEvents = true;
txtYourPercent.value = 100 - txtMyPercent.value;
suspendEvents = false;
}
It's my way.This method is disgusting.Any better solution? ("WinForms")
If there is not another solution tell me to delete this question and use my (beep) solution.
You could assign both textboxes the same chenge event handler:
this.txtMyPercent.TextChanged += new System.EventHandler(this.txtPercent_TextChanged);
this.txtYourPercent.TextChanged += new System.EventHandler(this.txtPercent_TextChanged);
and then:
private void txtPercent_TextChanged(object sender, EventArgs e)
{
if (sender == txtMyPercent)
{
txtYourPercent.Text = (100 - int.Parse(txtMyPercent.Text)).ToString();
}
else if (sender == txtYourPercent)
{
txtMyPercent.Text = (100 - int.Parse(txtYourPercent.Text)).ToString();
}
}
Related
I am working on Winforms with C#.
I have a problem with the logic, there are two different methods that I need to call, so that if I click the button, the first action should get applied and if I click the same button again, the second action should get applied.
This is not the exact code but I have an idea something like this:
private void button1_Click(object sender, EventArgs e)
{
if(button1.click==true)
{
fileNumber = 1;
ImgSave();
}
else
{
ImgSave.exit();
}
}
Here I have two problems regarding whether the button is already clicked:
If it's not clicked the Imgsave() should get activated.
If button is clicked the Imgsave() should get closed.
Can anyone please help me with this? Thanks.
You need to keep state somewhere. You can do this:
private bool buttonClicked = false;
private void button1_Click(object sender, EventArgs e)
{
if(!buttonClicked)
{
buttonClicked = true;
fileNumber = 1;
ImgSave();
}
else
{
ImgSave.exit();
}
}
This assumes you never going to click it a third time. If you are, you would need to handle that in some way.
I'd have either a class level variable track the number of times a button is clicked:
private bool _unclicked = false;
private void button1_Click(object sender, EventArgs e)
{
if(!_unclicked)
{
_unclicked = true; //toggle so next time the ELSE will be performed
fileNumber = 1;
ImgSave();
}
else
{
_unclicked = false; //toggle it off again
ImgSave.exit();
}
}
, or I'd store it in the .Tag of the button:
private void button1_Click(object sender, EventArgs e)
{
if(!button1.Tag.ToString() == "unclicked")
{
button1.Tag = "clicked"; //toggle so next time the ELSE will be performed
fileNumber = 1;
ImgSave();
}
else
{
button1.Tag = "unclicked"; //toggle it off again
ImgSave.exit();
}
}
You could also remove one event handler and add another:
private void button1_FirstClick(object sender, EventArgs e)
{
button1.Clicked -= button1_FirstClick;
button1.Clicked += button1_SecondClick;
fileNumber = 1;
ImgSave();
}
private void button1_SecondClick(object sender, EventArgs e)
{
button1.Clicked -= button1_SecondClick;
button1.Clicked += button1_FirstClick;
ImgSave.exit();
}
I've always been less of a fan of adding and removing event handlers to achieve things like this but it's quite a clean solution
You should save your state in a variable. Your state will change after first click and you can change the state of Clicking button with calling ConditionChanger() method anytime.
For example you may need change the state of variable when you clicked a second button.
private void ConditionChanger(){
myState = !myState;
}
Your variable :
private bool myState = false;
And your click event :
private void button1_Click(object sender, EventArgs e)
{
if(!myState)
{
myState = true;
fileNumber = 1;
ImgSave();
}
else
{
ImgSave.exit();
}
}
I have 40 buttons that all do something slightly different when clicked, I would like to condense this down if I can. I also want to say, if one of the buttons is clicked, create a timestamp which can be accessed by the class.
Here is the code for 2 out of 40 of the buttons:
private void Btn1_Click(object sender, RoutedEventArgs e)
{
for (int i = 1; i < 5; i++)
{
CheckBox CheckBox = (this.FindName(string.Format("Check{0}", i)) as CheckBox);
if (CheckBox != null)
{
CheckBox.IsChecked = true;
}
}
}
private void BtnDisable1_Click(object sender, RoutedEventArgs e)
{
for (int i = 1; i < 5; i++)
{
CheckBox CheckBox1 = (this.FindName(string.Format("Check_D{0}", i)) as CheckBox);
if (CheckBox1 != null)
{
CheckBox1.IsChecked = false;
}
}
}
I think one way of doing it is putting it in an array and whenever one of the 40 buttons are clicked it looks in the array on what to do next? I'm not really sure, thank you!
You can make this simple using one method.
Answer is updated based on this discussion
private void DoWork(int checkboxGroup, bool enable)
{
int start = checkboxGroup * 4;
for (int i = start; i < start + 4; i++)
{
CheckBox CheckBox = this.FindName("CheckBox" + i) as CheckBox;
if (CheckBox != null)
{
CheckBox.IsChecked = enable;
}
}
}
private void Btn1_Click(object sender, RoutedEventArgs e)
{
DoWork(1 , true);
}
private void BtnDisable1_Click(object sender, RoutedEventArgs e)
{
DoWork(1 , false);
}
Because there are 40 methods like this you can use Expression bodied methods. You must have C#6 to use this feature.
private void Btn1_Click(object sender, RoutedEventArgs e) => DoWork(1 , true);
private void BtnDisable1_Click(object sender, RoutedEventArgs e) => DoWork(1 , false);
private void Btn2_Click(object sender, RoutedEventArgs e) => DoWork(2, true);
private void BtnDisable2_Click(object sender, RoutedEventArgs e) => DoWork(2, false);
// and so on
I have a text box which the user shouldn't be allowed to write spaces in.
So far I have this code:
private void SearchCriteria_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key.ToString() == "Space")
{
DelLast = SearchCriteria.Text;
NeedsToDelete = true;
}
}
private void SearchCriteria_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (NeedsToDelete == true)
{
SearchCriteria.Text = DelLast;
NeedsToDelete = false;
}
}
It works, but the cursor is being placed in front of the text. Is there another way to do this?
Save the SelectionStart in your OnKeyDown event and then set it again within the OnKeyUpEvent
private void SearchCriteria_KeyDown(object sender, System.Windows.Input.KeyEventArgs e
{
if (e.Key.ToString() == "Space")
{
DelLast = SearchCriteria.Text;
NeedsToDelete = true;
_selectionStart = SearchCriteria.SelectionStart;
}
}
private void SearchCriteria_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (NeedsToDelete == true)
{
SearchCriteria.Text = DelLast;
SearchCriteria.SelectionStart = _selectionStart;
NeedsToDelete = false;
}
}
try this :
private void SearchCriteria_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (NeedsToDelete == true)
{
SearchCriteria.Text = DelLast;
NeedsToDelete = false;
SearchCriteria.Select(SearchCriteria.Text.Length, 0);
}
}
I have three radio buttons. The code behind their change events is as follows:
private void uxRajRadioButton_CheckedChanged(object sender, EventArgs e)
{
if (uxRajRadioButton.Checked == true)
{
uxPersonBettingLabel.Text = "Raj";
GuySelected = 0;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
private void uxPaulRadioButton_CheckedChanged(object sender, EventArgs e)
{
if (uxPaulRadioButton.Checked == true)
{
uxPersonBettingLabel.Text = "Paul";
GuySelected = 1;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
private void uxMikeRadioButton_CheckedChanged(object sender, EventArgs e)
{
if (uxMikeRadioButton.Checked == true)
{
uxPersonBettingLabel.Text = "Mike";
GuySelected = 2;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
With just three radio buttons this is acceptable but if I had say 7 radio buttons each with 20 lines of code behind its change event then it would be a lot of (needless?) code. I've attempted to shorten the above and ended up with the following. Is this correct?
private void uxRajRadioButton_CheckedChanged(object sender, EventArgs e)
{
radioButtonCode(this.uxRajRadioButton, 0);
}
private void uxPaulRadioButton_CheckedChanged(object sender, EventArgs e)
{
radioButtonCode(this.uxPaulRadioButton,1);
}
private void uxMikeRadioButton_CheckedChanged(object sender, EventArgs e)
{
radioButtonCode(this.uxMikeRadioButton, 2);
}
int GuySelected=0;
public void radioButtonCode(RadioButton myRadio, int mybettorIndex)
{
if (myRadio.Checked == true)
{
GuySelected = mybettorIndex;
uxPersonBettingLabel.Text = Guys[GuySelected].Name;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
Could you have the same event handler for all the radio buttons? Something like
private void uxRadioButton_CheckedChanged(object sender, EventArgs e)
{
radioButtonCode((RadioButton)sender);
}
public void radioButtonCode(RadioButton myRadio)
{
if (myRadio.Checked == true)
{
int guySelected = getGuySelectedIndex(myRadio);
uxPersonBettingLabel.Text = Guys[guySelected].Name;
uxBetNumericUpDown.Maximum = Guys[guySelected].Cash;
}
}
public int getGuySelectedIndex(RadioButton myRadio)
{
int index = 0;
if (myRadio == this.uxRajRadioButton) index = 0;
else if (myRadio == this.uxPaulRadioButton) index = 1;
else if (myRadio == this.uxMikeRadioButton) index = 2;
return index;
}
Your second code sample, where you have extracted the commonalities out to a function looks like the way I would have done this refactoring.
It is about as good as you can make it, barring the name (UpdateUserInfo might be slightly better).
There is a better way. Declare an array of radio buttons and bind them to above event at run time. This binding code won't be inside designer page. This will result in single ArrayRadio_checkedChange event. In this method you can use sender property to figure out the proper radio button's index and take action accordingly.
you can use
uxRajRadioButton.CheckedChanged += new EventHandler(rb_CheckedChanged);
uxPaulRadioButton.CheckedChanged += new EventHandler(rb_CheckedChanged);
...
uxRajRadioButton.Tag =new KeyValuePair<string,int>("Raj",0);
uxPaulRadioButton.Tag =new KeyValuePair<string,int>("Paul",1);
....
private void rb_CheckedChanged(object sender, EventArgs e)
{
if(!(sender is RadioButton))
return;
RadioButton myRadio= sender as RadioButton;
if (myRadio.Checked == true)
{
myRadio.Text = (myRadio.Tag as KeyValuePair<string,int>).Key;
GuySelected = (myRadio.Tag as KeyValuePair<string,int>).Value;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
What I usually do is I put the index in the tag attribute. This way you can bind this event to every RadioButton
public void uxRadioButton_CheckedChanged(object sender, EventArgs e)
{
RadioButton myRadio = (RadioButton) sender;
if (myRadio.Checked)
{
GuySelected = (int)myRadio.Tag;
uxPersonBettingLabel.Text = Guys[GuySelected].Name;
uxBetNumericUpDown.Maximum = Guys[GuySelected].Cash;
}
}
So in my very small program I am generating a random percentage and based off that percentage it should display one of two panels. However, it is only ever displaying one.
Here is my code:
Random random = new Random();
private void button1_Click(object sender, EventArgs e)
{
bool button1Clicked = true;
if (button1Clicked == true) { ITIpanel.Visible = true; }
}
private void ITIpanel_Paint(object sender, PaintEventArgs e)
{
ITItimer.Enabled = true;
}
private void ITItimer_Tick(object sender, EventArgs e)
{
double rand = random.NextDouble();
if (rand <= .50) { bluestimPanel.Visible = true; }
if (rand >= .50) { redstimPanel.Visible = true; }
ITItimer.Enabled = false;
}
private void bluestimPanel_Paint(object sender, PaintEventArgs e)
{
Trialtimer.Enabled = true;
}
private void redstimPanel_Paint(object sender, PaintEventArgs e)
{
Trialtimer.Enabled = true;
}
private void Trialtimer_Tick(object sender, EventArgs e)
{
bluestimPanel.Visible = false;
redstimPanel.Visible = false;
Trialtimer.Enabled = false;
ITIpanel.Visible = true;
}
I think what is happening here is that in the TrialTimer_Tick method setting ITIPanel.Visible to true is not causing ITIPanel to repaint and hence ITITimer never restarts.
You can put a breakpoint in the ITITimer_Click method and see if it is ever invoked again after the first invocation.