Home > OS >  How do I reference and act on parent and child containers
How do I reference and act on parent and child containers

Time:09-24

Say what you want about JavaScript, but navigating hierarchy is a breeze. Maybe C# is too, but I don't know how. I have a program with a series of controls where the control is repeated over and over:

form buttons example pic

The buttons all operate the same so I'm repeating a lot of code and it seems inefficient:

        // There's a function just like this for EVERY button
        private void FixedF1(bool isFixed)
        {
            if (isFixed)
            {
                F1FixerBtnDot.ForeColor = Color.FromArgb(80, 214, 0);
                F1FixerBtnDot.TextAlign = ContentAlignment.TopLeft;
                F1FixerBtnArea.BackgroundImage = Properties.Resources.green_btn_bk_sm;
                F1FixerBtnBox.Text = "Fixed!";
                PrefMatch("KillF1Help", "yes", F1FixerBtnDot);
            }
            else
            {
                F1FixerBtnDot.ForeColor = Color.FromArgb(244, 180, 0);
                F1FixerBtnDot.TextAlign = ContentAlignment.TopRight;
                F1FixerBtnArea.BackgroundImage = Properties.Resources.yellow_btn_bk_sm;
                F1FixerBtnBox.Text = "Fix it!";
                PrefMatch("KillF1Help", "no", F1FixerBtnDot);
            }

        }

        private void F1FixerBtnDot_Click(object sender, EventArgs e)
        {
            if (regStuff.F1HelpActive())
            {
                // Save the new setting
                prefs.SetPref("KillF1Help", "no");
                // Toggle it
                regStuff.RestoreF1();
                FixedF1(false);
            }
            else
            {
                prefs.SetPref("KillF1Help", "yes");
                regStuff.KillF1();
                FixedF1(true);
            }
        }

In the first function, I have code that turns the button "on" and "off". The operation is basically repeated for each of these buttons and I might have 30 or more. I'm trying to recode it something like this (based on how I would do this in JS):

        private void ToggleFixedButton(GroupBox which, bool isFixed, string prefName)
        {
            which.child(islabel).ForeColor = isFixed ? Color.FromArgb(80, 214, 0) : Color.FromArgb(244, 180, 0);
            which.child(islabel).TextAlign = isFixed ? ContentAlignment.TopLeft : ContentAlignment.TopRight;
            which.child(isPanel).BackgroundImage = isFixed ? Properties.Resources.green_btn_bk_sm : Properties.Resources.yellow_btn_bk_sm;
            which.Text = isFixed ? "Fixed!" : "Fix it!";
            PrefMatch("KillF1Help", isFixed ? "yes" : "no", which.child(islabel));
        }

        private void F1FixerBtnDot_Click(object sender, EventArgs e)
        {
            if (regStuff.F1HelpActive())
            {
                prefs.SetPref("KillF1Help", "no");
                regStuff.RestoreF1();
                ToggleFixedButton(sender.Parent, false, "KillF1Help");
            }
            else
            {
                prefs.SetPref("KillF1Help", "yes");
                regStuff.KillF1();
                ToggleFixedButton(sender.Parent, true, "KillF1Help");
            }
        }

Bottom line, it doesn't seem smart to have a separate function that does the same thing for 30 controls when I should be able to do it with ONE assuming I can figure out how to send it the information it needs to access the form elements involved.

CodePudding user response:

I'm going to assume you're just working with Buttons and Panels.

Look at the Properties tab of the designer for your controls and notice the Tag property. You can populate these with your keys F1, F2, F3 etc. Do this for both the Buttons and the Panels to associate them.

Then handle all the Click events of the Buttons with a single method and use code such as this to get the associated panel for the event;

var panelOfInterest = Parent.Controls.OfType<Panel>().Single(c => c.Tag == sender.Tag);

If the associated controls do not share an immediate Parent then you will need to specify some other control to search through.

CodePudding user response:

The typical c# way would be to create a custom control for your custom button.

That way you can put whatever custom logic to change the color and other properties in your custom control.

It might be possible to use a combination of is operator, .Controls, and .OfType() to traverse the tree of controls and do what you desire. But I would not recommend it since it makes your button much harder to reuse in other controls.

  • Related