Home > front end >  C# WinForms - Cannot access a control in a handler method
C# WinForms - Cannot access a control in a handler method

Time:01-29

I have a form containing two flow layout panels (FLP), which dynamically have buttons added to them. These buttons are actually a class called tagButton which inherits from Button and I have added a handler in the constructor for the click() method. On click, I want to remove the button from the FLP it is currently in then add it to the other FLP.

Below is a trimmed down version of my code for the tagButton class. Note that the tagButton class is defined inside the of the form class both FLPs are in:

    class tagButton : Button
    {
        public string tag = "";
        public bool useTag = false; //tells you which FLP the button is in

        public tagButton(String tag, Boolean useTag)
        {
            this.tag = tag;
            this.Text = tag;
            this.useTag = useTag;

            this.Click  = TagButton_Click;
        }


        private void TagButton_Click(object sender, EventArgs e)
        {
            tagButton tagButton = (tagButton)sender;
            tagButton.useTag = !tagButton.useTag;

            if (tagButton.useTag)
            {
                flowLayoutPanel.Controls.Remove(tagButton);
            }
        }
    }

I'm having problems with the last line:

flowLayoutPanel.Controls.Remove(tagButton);

I can switch it to the following and it works, however there is no way for me to add it to the other FLP. Or at least, not without doing Parent.Parent.Parent.Controls[1]... etc which is clearly a bad idea.

tagButton.Parent.Controls.Remove(tagButton);

I've tried switching different classes and methods to static but nothing I tried worked, the this keyword doesn't seem to work either.

CodePudding user response:

I would recommend having a separate class overriding a parent control that's aware of both FlowLayoutPanels. Then, when your button wants to switch, it can find that custom control in its parents and invoke a custom "switch" function that would move the invoking button from the list it's in to the list it wasn't in.

CodePudding user response:

One of many ways to achieve this outcome is to have MainForm expose a static array of the FlowLayoutPanel candidates as Panels property:

public partial class MainForm : Form
{
    public static Control[] Panels { get; private set; }
    char _id = (char)64;
    public MainForm()
    {
        InitializeComponent();
        Panels = new Control[]{ flowLayoutPanelLeft, flowLayoutPanelRight, };
        buttonAddLeft.Click  = (sender, e) =>
        {
            flowLayoutPanelLeft.Controls.Add(new tagButton
            {
                Height= 50, Width=150,
                Name = $"tagButton{  _id}",
                Text = $"Button {_id}",
            });
        };
        buttonAddRight.Click  = (sender, e) =>
        {
            flowLayoutPanelRight.Controls.Add(new tagButton
            {
                Height= 50, Width=150,
                Name = $"tagButton{  _id}",
                Text = $"Button {_id}",
            });
        };
    }
}

Then, suppose you want to swap between panels when a tagButton gets a right-click (for example).

class tagButton : Button 
{
    protected override void onm ouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);

        if (MouseButtons.Equals(MouseButtons.Right))
        {
            Control dest;                if(Parent.Name.Contains("Left"))
            {
                dest = MainForm.Panels.First(_=>_.Name.Contains("Right"));
            }
            else
            {
                dest = MainForm.Panels.First(_ => _.Name.Contains("Left"));
            }
            Parent.Controls.Remove(this);
            dest.Controls.Add(this);
        }
    }
}

screenshot

  • Related