How to correctly highlight buttons on click? - c#

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;
}
}
}

Related

C# Winforms Application Button Event for Method in Another Class

My problem is that I have a button in a winforms application that I would like to create a hover effect for. I have already achieved this effect by selecting this button, moving to the properties pane, selecting the Events, and double clicking the MouseEnter Event. This automatically creates a method in the c# code, and I can go into that method change the background color, no problem. I use a similar process for the MouseLeave Event and change the color back. This I know how to do.
Since each user control also has many buttons on it, I've been able to create generic methods (like below), and reuse these methods for each button within the user control. This is easy to select a method with the appropriate signature from the properties under events. I can find it in the dropdown next to the method. However, I have many user controls which have buttons on them, so these 2 methods are repeated in every single class.
What I've done to attempt to clean this up, is create a little static class. Then I can go into the designer (after building) and this works 100%. This not only reduces redundant code but also allows for a style change if ever the hover color needed to change, without modifying each code behind. However, if I were ever to make a modification the the user control, my reference to the method in the designer gets wiped out by the designer. The line of code just disappears.
Everything I read says "don't change the designer" for this exact reason. However, the visual studio user interface does not allow me a way to reference a method in an outside class. Any advice would be much appreciated.
private void Mouse_Enter(object sender, EventArgs e)
{
Button btn = (Button)sender;
if (btn.Enabled == true) btn.BackColor = Color.LightGray;
}
private void Mouse_Leave(object sender, EventArgs e)
{
Button btn = (Button)sender;
if (btn.Enabled == true) btn.BackColor = Color.White;
}
public static class ButtonHelper
{
public static void Mouse_Enter(object sender, EventArgs e)
{
Button btn = (Button)sender;
if (btn.Enabled == true) btn.BackColor = Color.LightGray;
}
public static void Mouse_Leave(object sender, EventArgs e)
{
Button btn = (Button)sender;
if (btn.Enabled == true) btn.BackColor = Color.White;
}
designer
this.btnEdit.UseVisualStyleBackColor = false;
this.btnEdit.Click += new System.EventHandler(this.btnEdit_Click);
this.btnEdit.MouseEnter += new System.EventHandler(ButtonHelper.Mouse_Enter);
this.btnEdit.MouseLeave += new System.EventHandler(this.Mouse_Leave);
Here is the updated code based on the advice by 41686d6564
public class HoverButton:Button
{
protected override void OnMouseEnter(EventArgs e)
{
if (Enabled == true) BackColor = Color.LightGray;
base.OnMouseEnter(e);
}
protected override void OnMouseLeave(EventArgs e)
{
if (Enabled == true) BackColor = Color.White;
base.OnMouseLeave(e);
}
protected override void OnEnabledChanged(EventArgs e)
{
if (Enabled)
{
ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(22)))), ((int)(((byte)(137)))));
BackColor = Color.White;
}
else
{
ForeColor = Color.Gray;
BackColor = Color.LightGray;
}
base.OnEnabledChanged(e);
}
}

Event that would listen to any label click in form

Well, I'm making a chess game that's based on labels. I need to listen for label click, so when user clicks on an label, I get the name of label he clicked. I know I can do it for each label, but is there an universal event that would help me do the same thing for all of them in one event / loop?
Suppose you have taken 64 labels.
In windows form, on click event of Label1 you will write following code:
private void Label1_Click(object sender, EventArgs e)
{
var label = sender as Label;
MessageBox.Show(label.Name);
}
For remaining 63 Lables, In Design view, select all 63 lables by using Ctrl key --> Go to Property window --> Under Event option select Click option --> From dropdownlist select 'Label1_Click' option.
Just finish & run the application.
You can use a Panel
structure to group your labels and then call the desired event on that Panel, so it will trigger whenever you click one of it's elements.
Another solution would be to identify your label with the coordinates of the mouse click (the amount of code that requires depends how you placed them of course).
Like mentioned in the comments you can assign one event to all...
List<Label> lbls = this.Controls.OfType<Label>().ToList();
foreach (var lbl in lbls)
{
lbl.Click += lbl_Click;
}
void lbl_Click(object sender, EventArgs e)
{
Label lbl = sender as Label;
MessageBox.Show(lbl.Name);
}
You can assign these methods to every label you need to manage in the VS form designer (you go to events of controls, at the click line and select the method in the list instead of double click on it):
private void Label_Click(object sender, EventArgs e)
{
var nameLabel = ( sender as Label )?.Name ?? "Error";
// ...
}
private void Label_Enter(object sender, EventArgs e)
{
( sender as Label ).Cursor = Cursors.Hand;
}
private void Label_Leave(object sender, EventArgs e)
{
( sender as Label ).Cursor = Cursors.Default;
}
Cursor change added for convenience if you want.
If you want to dynamically assign events, you can use the #caner answer, and you can group all in a panel to parse Panel.Controls and assign event.
You can create a custom label class that inherits from Label. You can then subscribe to the Click event of the base class and do your thing.
public class MyLabel : Label
{
public MyLabel()
: base()
{
Click += ProcessClickEvent;
}
private void ProcessClickEvent(object sender, System.EventArgs e)
{
// Do what you want to do
}
}

Is there a WinForms control to show and hide another WinForms control?

Is there a WinForms control that can show and hide another WinForms control similar to the concept of a TreeNode collapse button?
The easy way to do it is add a button and a checkbox to a form, add an event handler for the checkbox CheckedChanged event and in the event handler code simply add:
button1.Visible = !checkBox1.Checked;
The better way to do it would be with data binding and INotifyProperyChanged
Do you mean something similar to an Accordian?
See this post winforms accordion
You could write wrappers for all the controls you want to use and make all their visibilities depend on the state of another control.
private delegate void ToggleVoid();
private static event ToggleVoid VisibilityToggle;
private void Form1_Load(object sender, EventArgs e)
{
DependantButton TestButton = new DependantButton();
TestButton.SetBounds(100, 100, 100, 100);
this.Controls.Add(TestButton);
Button ToggleButton = new Button();
ToggleButton.SetBounds(200, 200, 100, 100);
ToggleButton.Click += OnToggleButtonClicked;
this.Controls.Add(ToggleButton);
}
private void OnToggleButtonClicked(object sender, EventArgs e)
{
VisibilityToggle.Invoke();
}
private class DependantButton : Button
{
public DependantButton() : base()
{
VisibilityToggle += ToggleVisibility;
}
public void ToggleVisibility()
{
Visible = !Visible;
}
}

Click event not firing for custom UserControl on a form

I have created a UserControl called Toggle, this is my code for it
[DefaultEvent("Click")]
public partial class Toggle : UserControl {
public bool ToggleStatus { get { return toggleStatus; } }
private bool toggleStatus { get; set; }
public Toggle() {
InitializeComponent();
toggleStatus = true;
}
private void toggleClick(object sender, EventArgs e) {
if (toggleStatus) { // currently set as "true" or "on"
this.lblSwitch.Dock = DockStyle.Right;
this.pnlBackground.BackColor = System.Drawing.Color.Red;
toggleStatus = false;
} else { // currently set as "false" or "off"
this.lblSwitch.Dock = DockStyle.Left;
this.pnlBackground.BackColor = System.Drawing.Color.Green;
toggleStatus = true;
}
}
}
The toggleClick method is tied to the click event of controls within the UserControl; this fires off just fine.
However, when I put my Toggle control on a form and attempt to tie an event to the click of it, it won't fire off.
private void toggleSoundClick(object sender, EventArgs e) {
soundToggle = !soundToggle;
}
I've made sure that the proper method is tied to the click event in my Designer.cs file of both my UserControl and my form
UserControl:
this.lblSwitch.Click += new System.EventHandler(this.toggleClick);
this.pnlBackground.Click += new System.EventHandler(this.toggleClick);
(I have it tied to two controls on my Toggle since I want it to fire no matter where you click on the control)
Form:
this.tglSound.Click += new System.EventHandler(this.toggleSoundClick);
The expected behavior for the UserControl is to fire off toggleClick (which it does) then the form should fire off toggleSoundClick (which it doesn't). I have seen this behavior work fine for other UserControls I have designed and used in this same project.
To clarify:
I have a UserControl called ServerDisplay. I have a method tied to the click event of the background panel of ServerDisplay (in the code for ServerDisplay) that shows a random MessageBox:
private void ServerDisplay_Click(object sender, EventArgs e) {
MessageBox.Show("test");
}
Then, I have a ServerDisplay control contained within my form. I have a method tied to the click event of it as well (in the code for my form)
private void serverDisplayClick(object sender, EventArgs e) {
if (loaded) {
ServerDisplay display = (ServerDisplay)sender;
this.lblLastServer.Text = "Last server joined was " + display.Server.Name + " at " + DateTime.Now.ToString("h:mm tt");
centerControl(this.lblLastServer);
}
}
When I click on the ServerDisplay control in my form, it shows the MessageBox (code from within ServerDisplay), then updates the label I specified in the code (code from form). This is the intended behavior, but it is not working for my other UserControl.
I finally figured it out! The way I had the control set up, I had the control itself, a panel filling up the entire background (I used this for the color), and then another panel inside the first panel to act as the "switch".
When I got rid of the first panel and just used the background of the control for the color and a small panel for the switch, it works when I click the background, but not when I click the "switch" panel. I guess this opens up more questions that I'll have to ask separately from this one, but at least I got my answer.

Buttons in a Visual Studios form application

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.

Categories

Resources