Question Reset button color from another form.

AlexJames

Well-known member
Joined
Mar 20, 2020
Messages
65
Programming Experience
10+
Hi All

I'm building a C# winForms app, I have my main form with with some buttons as a menu. I have a docked panel which i show my forms in with the code below.

C#:
Form frm = new FrmSetupExchanges
            {
                TopLevel = false,
                ControlBox = false,
                Dock = DockStyle.Fill
            };

PnlContainer.Controls.Add(frm);

When the user clicks on the button to show the above form I change the back color of the button so that the user can visually see which menu item he clicked. The problem i'm having is when i close the form i want to reset the button color back to normal on my main form but i cant figure out how to do it. All my coding experience has been in Visual basic, so would simply do

Visual Basic:
FrmMain.Cmdsetup.Backcolor = Color.Red

Me.Close

How do i achieve this in C# ?
many thanks in advance
AJ
 
Last edited by a moderator:
I would suggest that you don't actually use Button controls. You can use RadioButton controls and set their Appearance properties to Button. The controls will then look like regular Button controls but clicking one will automatically leave it with a depressed appearance while also releasing the one that was previously depressed. Just note that, instead of handling the Click event, you will handle the CheckedChanged event. You will need to test the Checked property to decide whether or not to open a form. You haven't indicated so specifically but you might also want to close the form when Checked is false.
 
Thanks JM

I never thought of doing that, i wish i knew this earlier LOL, spent loads of time designing and coding for the different pressed states etc. This might be easier to change over now, as you mentioned i can close my form when the checked state is false instead of doing it from the form. But as a matter of interest, how would you call a control that's on another form ?
 
But as a matter of interest, how would you call a control that's on another form ?
In this scenario, you wouldn't. The correct course of action is for the second form to raise an event and for the first form to handle that event and then update itself. In this case, the FormClosed event already exists, so there's no need to declare a custom event. Basically, when your first form creates the second form, it registers a handler for the FormClosed event and, in that method, it would reset the colour of its own Button.
 
Thanks a mil JM

I'm going to give that a try, but ultimately I'm going to convert my existing buttons to RadioButtons, this will be far more easier to manage in the log run.
 
When you try the event option, just remember that you also need to remove the event handler when you're done with the object. You can do that in the event handler itself, using the sender parameter to reference the object. For instance, if you register an event handler like this:
C#:
myObject.SomeEvent += SomeMethod;
then, inside SomeMethod, you would do this:
C#:
((SomeType) sender).SomeEvent -= SomeMethod;
If you don't remove the event handler, the object whose event you're handling will not be able to be finalised as long as the object handling the event exists.
 
Thanks again jm

I'll most likely bug you again in this post when i get to that section, the C# fundamentals are way different to what i'm used too.
 
Hi JM

Thank you for the suggestion on using RadioButtons, its far slicker than my previous method. i have no problem showing the form but i just can get it to close , as shown below.

C#:
        private void CmdSetupExchanges_CheckedChanged(object sender, EventArgs e)
        {
            switch (CmdSetupExchanges.Checked)
            {
                case true:
                    PicSetup.Visible = true;

                    Form frmSetup = new FrmSetupExchanges
                    {
                        TopLevel = false,
                        ControlBox = false,
                        Dock = DockStyle.Fill
                    };
                    PnlContainer.Controls.Add(frmSetup);
                    frmSetup.Show();
                    break;
                case false:
                    PicSetup.Visible = false;
                    Form frmSetupOpen = new FrmSetupExchanges();
                    frmSetupOpen.Close();
                    break;
                default:
                    break;
            }

        }

I've also tried clearing out the panel but again the form stays open and i cant figure out what i'm doing wrong.

Thanks again
AJ
 
The issue is that you are not closing the form you displayed but, rather, a new form that you just created. If I blew up a balloon and gave it to you, then grabbed a new balloon and blew it up and then stuck a pin in it, would you expect your balloon to pop? Of course not. That would be magic. Why, then would you expect that to happen here? If you create form and display it, then create a new form and close that, why would you expect the first form to close? You need to be able to access the form object you created earlier so that you can close it. As your code stands, the way to do that would be to get it from the Controls collection of the Panel. The alternative would be to have a single frmSetup variable at the class level instead of multiple local variables. That field can be accessed from anywhere in your code.
 
Thanks Jm

I only realized my mistake of re-initializing a new form and then closing that one after i posted it. If i'm understanding you correctly, i should declare my form (frmSetup) on frmMain and use that variable to open and close my form ? I'm going to experiment with that now. I'll also change "switch" to "if" statement, i've always been a fan of case blocks but i agree, unnecessary for only two conditions.
 
Hi Jm

I'm making progress here, but have created a new issue. The below code works perfectly but only once, if i try and open the form again i get a "Cannot access a disposed object" exception.

C#:
    public partial class FrmMain : Form
    {
        private Form frmSetup = new FrmSetupExchanges();

        public FrmMain()
        {;
            InitializeComponent();
        }
        
                private void CmdSetupExchanges_CheckedChanged(object sender, EventArgs e)
        {
            switch (CmdSetupExchanges.Checked)
            {
                case true:
                    PicSetup.Visible = true;
                    frmSetup.TopLevel = false;
                    frmSetup.ControlBox = false;
                    frmSetup.Dock = DockStyle.Fill;
                    PnlContainer.Controls.Add(frmSetup);
                    frmSetup.Show();
                    break; 
                case false:
                    PicSetup.Visible = false;
                    PnlContainer.Controls.Remove(frmSetup);
                    frmSetup.Close();
                    break;
                default:
                    break;
            }

        }

i think i understand why, I'm initializing the form when i declare it, so when i try and show it again the form has been disposed and not re-initialized. But then i tried just declaring the form and initializing it when i show the form, but then i just get "unused local variable" errors.

C#:
public Form frmSetup = null;

       private void CmdSetupExchanges_CheckedChanged(object sender, EventArgs e)
        {
            switch (CmdSetupExchanges.Checked)
            {
                case true:
                    Form frmSetup = new FrmSetupExchanges
                    {
                        TopLevel = false,
                        ControlBox = false,
                        Dock = DockStyle.Fill
                    };
                    PnlContainer.Controls.Add(frmSetup);
                    frmSetup.Show();
                    break; 
                case false:
                    PicSetup.Visible = false;
                    PnlContainer.Controls.Remove(frmSetup);
                    frmSetup.Close();
                    break;
                default:
                    break;
            }

        }

Aaargg, pulling my hair out here.
 
Sorry Jm, i'm not understanding, the local variable in the case is "frmSetup"and i get the "unassigned variable" error in the false case. i cant replace "frmSetup" with "frmsetupExchanges' in the false case, i cant see what i'm missing.
Please put me out of my misery. :)
 
Back
Top Bottom