Sorry if this is a dumb question, I'm taking an intro to programming class and need a bit of help with this project I'm working on.
I'm trying to write an application that has about 30 buttons. One common thing I want is for all the buttons to turn yellow when clicked. If they're clicked a second time, they change back to the default color. right now I use the code:
private void btn_1_Click(object sender, EventArgs e)
{
btn_1.BackColor = Color.Yellow;
}
But that only turns the buttons yellow, I can't turn them "off" by clicking it a second time.
Also, when I'm creating these button events in VS2010, I end up with 30 different event handlers for each button..Is there a way to get them all to do the same thing without having to write all the repetitive code?
I'm guessing that I would have to write my own buttons class? How would I go about doing that? Do i need to create a class library which inherits Buttons?
Sorry for the noob questions. THanks
If every button has a specific action that needs to be performed, then yes, you need to have a click handler for each; however, you can encapsulate the common behavior in a single method.
For example:
private void btn_1_Click(object sender, EventArgs e)
{
ToggleColor((Button)sender);
//rest of the code specific to this button
}
private void ToggleColor (Button button)
{
if(button.Color==Color.Yellow;
button.Color=Color.Black;
else
button.Color=Color.Yellow;
}
Note that above code is not tested.
Now, if all the buttons do the same thing, you can just set the on click handlers for all of them to be btn_1_Click; for example.
private void btn_1_Click(object sender, EventArgs e)
{
if (btn_1.BackColor != Color.Yellow)
{
btn_1.BackColor = Color.Yellow
}
else
{
btn_1.BackColor = Color.Control;
}
}
this is switching default and yellow
If all buttons do the exact same thing you can assign the same event handler to all buttons (instead of btn_1_Click, btn_2_Click etc... you'd have btton_click) - you can select this handler in the properties of each button.
You don't have to write your own class. You can simply assign all your buttons to the same event handler, like this:
button1.Click += new EventHandler(myEventHandler);
button2.Click += new EventHandler(myEventHandler);
button3.Click += new EventHandler(myEventHandler);
button4.Click += new EventHandler(myEventHandler);
Just keep in mind that your event handler has this signature:
private void myEventHandler(object sender, EventArgs e)
By doing that, all your buttons, when clicked, will trigger the same method.
Now to control the color, what you can do is create a simple property on your form which would hold the last color applied. It could be an enum, then you could simply check its value and apply the other one to the buttons, like this:
// Declare your enum:
private enum Colors { Yellow, Default }
private Colors ActualColor = Colors.Default;
// Write your custom event handler:
private void myEventHandler(object sender, EventArgs e)
{
if (ActualColor == Colors.Default)
{
// Apply yellow to buttons
ActualColor = Colors.Yellow;
}
else
{
// Apply default
ActualColor = Colors.Default;
}
}
In order to keep track whether it is the 'second time' you press the button, you should declare a variable OUTSIDE the method, which indicates whether you already pressed the button or not.
For example:
public bool IsButtonYellow;
private void btn_1_Click(object sender, EventArgs e) {
if(!IsButtonYellow) {
btn.BackColor = Color.Yellow;
IsButtonYellow = true;
}
else {
btn.BackColor = Control.DefaultBackColor;
IsButtonYellow = false;
}
}
Yes:
Create your own button class
Inherit from Button
Implement the handler in your button class and you're done
You can do something simple like this:
public class MyButton : Button
{
private bool _buttonState;
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
if (_buttonState)
{
BackColor = Color.Yellow;
}
else
{
BackColor = Color.White;
}
}
}
Then in your code you can just create as many of these "MyButton" objects as you need, with no code repetition.
To make all buttons use the same event handler in VS2010:
Click once on a button to select it.
In the “properties” window: click on the “lightning” (=events).
Paste the first button’s event name (btn_1_Click) next to “Click”.
Do the same for every button.
As for changing the color:
See answer by killie01.
Good luck.
Related
So I have built an application in C# using Winforms and my application uses a few different buttons. I'd like to have a highlight on the button that has been clicked to show what 'tab' you're in.
I've tried doing the following;
// BUTTONS //
private void dashboard_btn_Click(object sender, EventArgs e)
{
// Load Form
OpenChildForm(new FormDashboard());
dashboard_btn.FlatAppearance.BorderColor = Color.Red;
dashboard_btn.FlatAppearance.BorderSize = 1;
}
However, this of course doesn't work nicely since it adds a border around the button but when I click another button the border also stays around the previous button.
How would you implement a feature to add a border around the button that get's clicked but have the border disappear after you click another button?
Thank you for any feedback!
EDIT:
I've implemented Jimi's advice and used the Leave event to change the border around the button back to 0. However I'm not sure how to implement this in a global way so all my buttons are subscribed to this event.
My code now looks like this;
// BUTTONS //
private void dashboard_btn_Click(object sender, EventArgs e)
{
// Load Form
OpenChildForm(new FormDashboard());
// Button Highlight
dashboard_btn.FlatAppearance.BorderColor = Color.Red;
dashboard_btn.FlatAppearance.BorderSize = 1;
}
// BUTTON REMOVE HIGHLIGHT //
private void dashboard_btn_Leave(object sender, EventArgs e)
{
dashboard_btn.FlatAppearance.BorderSize = 0;
}
EDIT 2:
I ended up using Jimi's example and this worked for me :)
This might lend itself to a RadioButton style functionality because clicking a different radio button in the same container will uncheck the others. So, to implement the "generalized approach" that you mention in your comment, you could make a simple custom RadioButtonEx class where the Appearance property is set to Button then change your border style when the Checked property changes. In this example, the Click event has been changed to static so that clicking on any button directs the event to the common onAnyClick method.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
RadioButtonEx.Click += onAnyClick;
}
private void onAnyClick(object sender, EventArgs e)
{
label1.Text = ((RadioButtonEx)sender).Text;
}
}
public class RadioButtonEx : RadioButton
{
public static new event EventHandler Click;
public RadioButtonEx()
{
FlatAppearance.BorderColor = Color.Red;
FlatAppearance.BorderSize = 1;
Appearance = Appearance.Button;
}
protected override void OnCheckedChanged(EventArgs e)
{
base.OnCheckedChanged(e);
if(Checked)
{
FlatStyle = FlatStyle.Flat;
Click?.Invoke(this, EventArgs.Empty);
}
else
{
FlatStyle = FlatStyle.Standard;
}
}
}
I am trying to make a calculator in C# through code only (Just adding a groupBox and a label in designer).
I have successfully added buttons a coma and a +/- sign.
But now I am running into a problem.
I can assign a function to all of them but
I need to assign a function separately to one of the buttons.
so far I have tried this with one button :
double num = Convert.ToDouble(Answer.Text);
Answer.Text = (-num).ToString();
But since I am working with arrays I have no idea how I can separate one button from another.
Essentially I should be able to do this:
If(Numbers[10].IsPressed)
do this.
but again I don't know the syntaxe's well enough
I dont really know what you want to do... But you might try a 'big' event handler... example:
Button[] buttons;
foreach(var button in buttons)
{
button.Click += MyHandler;
}
// method1
private void MyHandler(object sender, EventArgs e)
{
if(sender == buttons[0])
// Do something...
else if(sender == buttons[1])
// do something else...
else if(sender == buttons[2])
// and so on...
}
// method2
private void MyHandler(object sender, EventArgs e)
{
var button = (Button)sender;
switch(button.Text)
{
case "+":
case "1":
case "2":
// and so on...
}
}
Another good approach is having own handler for every button. Usualy Visual Studio will generate own click handler when you double click button in the designer.
private void ButtonPlus_Click(object sender, EventArgs e)
{
// Do something when "+" pressed
}
private void ButtonMinus_Click(object sender, EventArgs e)
{
// Do something when "-" pressed
}
You can manually add event handlers to the buttons in constructor (in case you used Visual Studio for generating it - Visual Studio will automatically add generated event handler to the button)
this.ButtonPlus.Click += ButtonPlus_Click;
this.ButtonMinus.Click += ButtonMinus_Click;
With approach above you will have own functions for every operations, which can help to maintain your code base little bid easily/faster.
However if you want to use only one event handler for all buttons, then you can use Button.Tag property.
Create method for every operation you have
private void ExecutePlus()
{
// Do something when "+" pressed
}
private void ExecuteMinus()
{
// Do something when "+" pressed
}
Then in constructor save all operations in the .Tag property of correspondent button.
this.ButtonPlus.Tag = ExecutePlus;
this.ButtonMinus.Tag = ExecuteMinus;
// add "general" event handler
var buttons = new[] { this.ButtonPlus, this.ButtonMinus };
foreach(var button in buttons)
{
button.Click += Button_Click;
}
Then create "general" click handler
private void Button_Click(object sender, EventArgs e)
{
var button = (Button)sender;
Action execute = (Action)button.Tag;
execute();
}
You will still have separated method for every operation, but only one event handler for all buttons
I am trying to make a button visible = false if a quantity in a text box is less than or equal to 0. The problem I am having is that you have to click the button in order to activate the function.
Here is my code so far
int quantity = int.Parse(textBox33.Text);
if (quantity <= 0)
button13.Visible = false;
if (quantity > 0)
button13.Visible = true;
do I have to disable the visibility of the text box beforehand?
Simply go to the form editor and double click on the textbox. In the code presented to you after double clicking add your code or double click on the form itself if you want the code to be executed whenever the form is loaded.
At first you should encapsulate the code to update the button in a specific method:
private void UpdateButton13()
{
button13.Visible = quantity > 0; // no need for if/else
}
Then you can call this from every event after which the button should be updated. From your comments it seems you want to update that button
at Form load and
when the text in textBox33 has been changed.
So for example:
public class YourForm : Form
{
public YourForm()
{
InitializeComponents();
// register event handlers:
Load += YourForm_Load;
textBox33.TextChanged += textBox33_TextChanged;
}
private void YourForm_Load(object sender, EventArgs e)
{
UpdateButton13();
}
private void textBox33_TextChanged(object sender, EventArgs e)
{
UpdateButton13();
}
private void UpdateButton13()
{
button13.Visible = quantity > 0; // no need for if/else
}
}
Of course you can also create and register the event handlers in the designer window, without having to write the code in the constructor yourself.
The code above may now seem a little redundant (same code in two methods and a one-line method). But I assume that you want to do further things on loading the form and on changing text, and maybe you want to call UpdateButton13 from other parts of your code, too. So encapsulating here is good style (imho) to avoid problems for further development.
go to textbox events and insert the code to textChanged event.
but for better than that you can do digit validation event
private void textBox33_KeyPress(object sender, KeyPressEventArgs e)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(e.KeyChar.ToString(), "[1-9]"))
{
e.Handled = true;
}
}
in that case order can be only positive number
The question is this:
when the mouse cursor moved on the button some thing should be happen but I don't know what exactly have to write
When you select the button in the VS-designer you will have access to the properties and events (lightning Icon in the property window).
In the events-listing are all events that the button can fire. May be for your purpose the events: ´MouseEnter´ and ´MouseLeave´ would be a good choice. Just double click the event and Visual Studio will generate the appropriate method. Like this:
private void button1_MouseEnter(object sender, EventArgs e)
{
// my code
this.button1.BackColor = Color.Red;
}
private void button1_MouseLeave(object sender, EventArgs e)
{
// my code
this.button1.BackColor = Color.Green;
}
In my example I just change the backcolour of the button when the mouse is on the button and change it again when it leaves the button.
Practically you could run any code inside the generated method.
You can create eventHandler like this :
myButton.MouseMove += new MouseEventHandler(doSomething);
Where myButton is the button from which you want to trigger the event when mouse moves over it. and doSomething() is the method defined as like the following:
public void doSomething(object sender, MouseEventArgs e)
{
// do what ever you want
}
I'm new to C# and Windows Form but if I have a radiobutton and I call radiobutton1.Checked=true, is there a way for it to not fire the CheckedChange event? I want to distinguish between the user clicking on the radiobutton and me setting the radiobutton programmatically. Is this possible?
Stop trying to defeat the design of the CheckedChanged event. It's specifically supposed to include programmatic changes.
If you want user-triggered changes and not programmatic changes, use the Click event instead. (You may be thinking that you don't want to restrict yourself to mouse clicks, don't worry, there's a MouseClick event for that, Click includes keyboard changes as well.)
Here's a straightforward method of using the event when you feel like it.
private bool SuppressRadioButton1Event { get; set; }
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
if (!this.SuppressRadioButton1Event)
{
MessageBox.Show("Not suppressed!");
}
}
private void button1_Click(object sender, EventArgs e)
{
this.SetRadioButton1(false);
}
private void SetRadioButton1(bool checkedOn)
{
this.SuppressRadioButton1Event = true;
radioButton1.Checked = checkedOn;
this.SuppressRadioButton1Event = false;
}
A very easy way:
public void radio_OnCheckChanged(object sender, EventArgs e)
{
RadioButton r = sender as RadioButton;
bool isUserChange = r.Tag.Equals(1);
if (isUserChange) blabla
else blabla
r.Tag = null;
}
public void MyMethod()
{
radio1.Tag = 1;
radio.Checked = true;
}
You can use any kind of flag which users can't do by their clicking.But you can do via your code.
Why should your code care who checked the radiobutton?
EDIT: There are ways around this (subclass, flag), but don't. The only "legit" reason I can think of for wanting this is to prevent some side-effect from happening when the value is initially (programatically) displayed, and even that is suspect. Rethink the side-effect, does it really belong on the change-event, or the commit?
More info one why/what would help. On the surface, this looks like a design error.
One (hackish) way to do it would be to subclass RadioButton and override the OnCheckChanged virtual method, suppressing the event if the Checked property has been set programmatically.
However, since radio-buttons belong to a group, the event always fires in pairs (oen for the uncheck, one for the check). You will therefore want to suppress the event for the entire group when you choose the selected button programmatically. Here's an example implementation:
public class CustomRadioButton : RadioButton
{
private bool _suppressCheckedEvent;
public void SetChecked(bool value, bool suppressCheckedEvent)
{
if (!suppressCheckedEvent)
Checked = value;
else
{
SetSupressModeForGroup(true);
Checked = value;
SetSupressModeForGroup(false);
}
}
private void SetSupressModeForGroup(bool suppressCheckedEvent)
{
foreach (var crb in Parent.Controls.OfType<CustomRadioButton>())
crb._suppressCheckedEvent = suppressCheckedEvent;
}
protected override void OnCheckedChanged(EventArgs e)
{
if (!_suppressCheckedEvent)
base.OnCheckedChanged(e);
}
}
In this implementation, changing the checked-state through the Checked property will always fire the event. When you call the SetChecked method, you have the choice to suppress the event.
You could try to attach the event programmatically. Based on my application configuration I check several radio buttons but I don't want to fire events.
To attach an event programmatically:
chbOptionX.CheckedChanged += new System.EventHandler(this.chbShowStockBySizeAndColor_CheckedChanged);