【问题标题】:switch usercontrols in mainform within a usercontrol click event在用户控件单击事件中切换主窗体中的用户控件
【发布时间】:2019-03-07 22:04:10
【问题描述】:

这听起来可能很愚蠢,但我很难弄清楚这一点;任何帮助将不胜感激:

我有两个名为“Safety_Check”和“OEE_Track”的用户控件。在我的 MainForm 中,我有一个名为“pnl_main_controller”的面板,用于显示我的两个用户控件。我的主窗体上有两个按钮,我可以在两者之间动态切换,没有任何问题。

Safety_Check 用户控制;

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 用户控制

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

主窗体:

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

我想要做的是我的“Safety_Check上有一个名为“Button1”的按钮” 用户控件,每当我按下此按钮时,我希望“Safety_Check”在“pnl_main_controller”上消失并带来“OEE_Track”到面板

【问题讨论】:

  • 如果你只是想让它消失,那么你可以使用可见属性并将其设置为false,将pnl_main_control可见属性设置为true并在其上调用brigtofront
  • 我试过了,Safety_Check.instance.Hide(); main.pnl_main_controller.Controls.Add(OEE_Track.instance); OEE_Track.instance.Dock = DockStyle.Fill; OEE_Track.instance.BringToFront(); Safety_Check 实例将消失,但不会将 OEE_Track 带入面板..

标签: c# .net winforms instance


【解决方案1】:

控件之间的交互有多种解决方案。控件是类,并且与任何其他类一样,它们可以使用其公共属性和方法或使用某些中介来相互交互。

在这种情况下,您的控件不需要相互了解,也不需要直接相互交互:

  • 他们可以请求另一个知道这两个控件的对象来为他们完成这项工作。
  • 或者他们可以提出他们的请求通知,订阅该通知的人将提供该通知。

要让另一个对象为他们完成这项工作,您有多种解决方案。例如,您可以在父窗体和子控件中实现特定接口,将父级强制转换为该特定接口并调用为您完成工作的特定方法。

对于提出请求通知,一个简单的解决方案是依赖事件。您可以在子控件中创建一个事件,并在您需要父控件为您做某事时引发它。然后在父母中订阅该事件并完成工作。

示例 - 使用事件

我假设你有UserControl1 里面有Button1 并且你已经处理了Button1Click 事件。然后您可以创建Button1Clicked 事件并在Button1 点击时引发它:

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

然后在父表单中,订阅事件并做任何你想做的事情:

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

示例 - 使用界面

我假设,您有一个包含一些标准方法的接口:

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

并且你已经在你的父表单中实现了接口:

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

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

然后在你的用户控制中:

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

【讨论】:

    【解决方案2】:

    我想稍微扩展一下 Reza Aghaei 的回答。我认为它可以变得比现在更好。

    第一种方法

    如果我是你,我会有一些接口ICheckedView,它至少有一种方法可以像这样实现:

    ICheckedView
    {
        void Continue();
    }
    

    现在,我们可以将此接口应用于解决方案中的任何类,但最有可能应用于视图。接下来,我会让你的主窗体实现这个接口并实现所需的方法。在 this 的情况下,我们希望我们的主窗体从面板中删除控件并添加一个新控件。坦率地说,我们的安全检查控件不需要(也许不应该)知道其他控件或接下来会发生什么。它只是用于控制流。

    最后,您需要为 Safety_Check 添加公共属性,或者甚至可能是构造函数的参数,其中包含ICheckedView。当您的安全检查控件被点击时,它可以告诉任何进入它的人(我们会说客户端)它必须继续。

    第二种方法

    可以通过action delegate 完成。

    如果您将Action 委托添加到您的安全检查中,您可以直接弹出签名与该委托匹配的任何方法 (void methodName())。您的 Safety_Check 控件的构造函数应包含一个 Action,并且该 Action 将被分配给该类的私有字段。然后当需要调用时,可以直接调用该操作。

    此方法的注意事项

    因为我们可能首先从 UI 线程调用,所以我们可能没问题,但您需要在这里考虑线程安全。调用所需模式可以帮助您解决这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多