switch usercontrols in mainform within a usercontrol click event

梦想的初衷 提交于 2019-12-20 01:15:44

问题


This may sound stupid, But I am having hard time to figure this out; any help would be appreciated:

I have two user controls called “Safety_Check” and “OEE_Track”. In my MainForm I have a panel called “pnl_main_controller” this is where I am displaying both my user controls. I have two buttons on my main form and I am dynamically switching between both without any issue.

Safety_Check User control;

public partial class Safety_Check : UserControl
    {
        private static Safety_Check _instance;

        public static Safety_Check instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Safety_Check();
                return _instance;
            }
        }

        public Safety_Check()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ///////------------------------
        }

    }

OEE_Track User control

public partial class OEE_Track : UserControl
    {

        private static OEE_Track _instance;

        public static OEE_Track instance
        {
            get
            {
                if (_instance == null)
                    _instance = new OEE_Track();
                return _instance;
            }
        }

        public OEE_Track()
        {
            InitializeComponent();
        }
    }

MainForm:

public partial class MainForm : Form
    {
     private void btn_reg_Click(object sender, EventArgs e)
        {
            if (!pnl_main_controller.Contains(Safety_Check.instance))
            {
                pnl_main_controller.Controls.Add(Safety_Check.instance);
                Safety_Check.instance.Dock = DockStyle.Fill;
                Safety_Check.instance.BringToFront();
            }
            else
            {
                Safety_Check.instance.BringToFront();
            }        }

       private void btn_OEE_Click(object sender, EventArgs e)
        {
            if (!pnl_main_controller.Contains(OEE_Track.instance))
            {
                pnl_main_controller.Controls.Add(OEE_Track.instance);
                OEE_Track.instance.Dock = DockStyle.Fill;
                OEE_Track.instance.BringToFront();
            }
            else
            {
                OEE_Track.instance.BringToFront();
            }
     }

What I am trying to do is I have a button called “Button1” on my “Safety_Check” Usercontrol, whenever I press this , I want “Safety_Check” to be disappear on “pnl_main_controller” and bring “OEE_Track” to the panel


回答1:


There are several solutions for interaction between controls. Controls are classes and like any other class they can interact with each other using their public properties and methods or using some mediator.

In this case, your controls don't need to know each other and don't need to interact to each other directly:

  • They can ask another object which knows both controls, to do the job for them.
  • Or they can raise their request notification and the one who subscribed to that notification, will serve it.

To ask another object to do the job for them you have multiple solutions. As an example you can implement a specific interface in the parent form and in the child controls, cast the parent to that specific interface and call a specific method which do the job for you.

For raising the request notification, an easy solution is relying on events. You can create an event in the child control and raise it when you need the parent do something for you. Then in the parent subscribe to that event and do the job.

Example - Using event

I assume you have UserControl1 having Button1 inside and you have handled Click event of Button1. Then you can create Button1Clicked event and raise it when Button1 clicked:

public event EventHandler Button1Clicked;
private void Button1_Click(object sender, EventArgs e)
{
    Button1Clicked?.Invoke(this, e);
}

Then in the parent form, subscribe for the event and do whatever you want:

private void userControl11_Button1Clicked(object sender, EventArgs e)
{
    //Hide userControl11 and show userControl21 
}

Example - Using interface

I assume, you have an interface having a few standard methods:

public interface IDoSomething
{
    void DoSomething();
    void DoSomethingElse();
}

And you have implemented the interface in your parent form:

public class Form1: Form, IDoSomething
{
    // ...

    public void DoSomething()
    {
        //Hide userControl11 and show userControl21 
    }
    public void DoSomethingElse()
    {
        // ...
    }
}

Then in you user control:

private void Button1_Click(object sender, EventArgs e)
{
    var f = FindForm() as IDoSomething;
    if(f!=null)
        f.DoSomething();
}



回答2:


I want to expand on Reza Aghaei's answer a bit. I think it could get even better than it is now.

First way to do this

If I were you I would have some interface ICheckedView which has at least 1 method to implement like so:

ICheckedView
{
    void Continue();
}

Now, we're able to apply this interface to any class in our solution, most likely to views, though. Next, I would make your main form implement this interface and implement the required method. The in this case we want our main form to remove the control from the panel and add a new control. Frankly, our Safety check control doesn't need to (and maybe shouldn't) know about other controls or what happens next. It's just used for flow of control.

Finally, you need to add either a public property, or maybe even a parameter to the constructor for Safety_Check which includes an ICheckedView in it. When your safety check control gets clicked it can tell whoever has been passed into it (we'll say the client) that it must continue.

Second way to do this

It can be done with an action delegate.

If you add an Action delegate to your safety check, you could just pop in any method whose signature matches that delegate (void methodName()). The constructor for your Safety_Check control should include an Action and that Action would get assigned to a private field of the class. Then when it's time to invoke, that action can be invoked directly.

Notes on this method

Because we're probably invoking from the UI thread in the first place, we're probably alright, but you need to think about thread safety here. The invoke required pattern can help you around this.



来源:https://stackoverflow.com/questions/55053527/switch-usercontrols-in-mainform-within-a-usercontrol-click-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!