如何从另一个用户控件向表单上的面板添加控件

5

我有一个form1.cs文件,在该文件中有一个panel1,我在form1.cs的load事件中向panel1添加了一个控件。现在我的问题是,我有一个名为Numbers.cs的控件,我需要从该控件中的按钮事件向该panel1添加另一个控件。我该如何做?

public partial class Number : UserControl
{
    public Number()
    {
        InitializeComponent();
    }

    private void btnAcceptWelcome_Click(object sender, EventArgs e)
    {
          //HERE I NEED TO PASS A CONTROL TO THE PANEL1 IN FORM1.CS
          //NOT SURE HOW TO DO THIS.
    }
}

更多信息

基本上我有一个名为UserControls的文件夹,该文件夹中包含以下内容:

Numbers.cs
Letters.cs
Welcome.cs

所有这些都是用户控件,然后我有一个表单。
Form1.cs

Form1.cs实例化Welcome并将其添加到Panel1中。在窗体加载时,将其添加到Form1.cs上。然后Welcome.cs有一个按钮,当我单击此按钮时,需要切换到Numbers.cs。但是我不知道如何从Welcome.cs实现这一点。


Numbers.cs 是否被托管在 Form1 中,控件是否在 Numbers.cs 或 Form1 中创建并添加到您的面板中? - Mark Hall
我现在的做法是,我有一个表单 form1.cs,然后在一个文件夹中创建用户控件,但有时候..其中一个用户控件需要将另一个用户控件添加到 form1.cs 中..很难解释。 - user710502
可能是如何处理.NET Winforms中的堆叠控件?的重复问题。 - Hans Passant
虽然存在重复响应,但是没有比下面展示的更简洁的方法,因此我认为这对于需要学习正确方法的人来说是更好的答案。 - user710502
4个回答

2
另一种方法是使用由 Numbers 触发并由 Form1 处理的 自定义事件,以传递控件并将其添加到面板的控件集合中。
这是一个向UserControl1添加自定义事件的示例。
Form1
public partial class Form1 : Form
{
    UserControl2 mySecondControl = new UserControl2();
    public Form1()
    {
        InitializeComponent();
        userControl11.AddControl+=new EventHandler(SwapControls);

    }

    private void SwapControls(object sender, EventArgs e)
    {
        panel1.Controls.Remove(userControl11);
        userControl11.AddControl -= new EventHandler(SwapControls);
        panel1.Controls.Add(mySecondControl);
    }
}

用户控件
public partial class UserControl1 : UserControl
{
    public event EventHandler AddControl;
    public UserControl1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        this.AddControl(this, new EventArgs());
    }
}

1
能否提供一个小例子?我是一个 Windows Forms 的初学者,不知道是否太过分了。 - user710502
@user710502 你需要交换UserControls还是添加额外的? - Mark Hall
我需要清除当前表单上的一个控件并放置新的控件。在form1.cs中,我有一个Panel1用于放置该控件。 - user710502
@IAbstract,你可能已经注意到了,我划掉了有问题的代码,并添加了使用我的第一个语句的代码。当时我只放置了第一个选项,因为它看起来像是第一个用户控件正在创建第二个。我将从我的答案中完全删除这段代码。 - Mark Hall
为什么这个 userControl11.AddControl+=new EventHandler(SwapControls); 给我返回一个“需要对象引用”的错误,而不是静态字段、方法或属性? - user710502
显示剩余4条评论

2

注意:

  1. 未经测试的代码
  2. 假设Form1有(或可以获取)对Number的引用

Number添加事件处理程序:

public partial class Number : UserControl
{
    //  event handler Form1 will subscribe to
    public EventHandler<EventArgs> OnWelcomeAccepted = (o, e) => { };

    public Number()
    {
        InitializeComponent();
    }

    private void btnAcceptWelcome_Click(object sender, EventArgs e)
    {
          //  raise the event
          OnWelcomeAccepted(sender, e);
    }
}

InitializeComponent()之后,Form1将会有一个订阅;请注意,还有一个额外的订阅ControlAdded

public partial class Form1 : Form {
    public Form1()
    {
        InitializeComponent();

        this.ControlAdded += Control_Added;
        //  subscribe to the event and provide the implementation
        Number.OnWelcomAccepted += (o, e) => { Controls.Add(GetControl( )); }
    }

    private void Control_Added(object sender, System.Windows.Forms.ControlEventArgs e)
    {
        //  process size and placement and show
    }

}

没有其他控件应该直接向 Form1 添加任何内容。让 Form1 控制它的子控件。


0

从您的描述中并不是很清楚,但您可以在构造函数或属性中传递所需的控件。由于在C#中对象始终是按引用传递的,因此您将在Button事件中对同一控件进行操作。您始终可以编写自己的事件,并让面板注册该事件。更完整的代码示例会更好。

我仍然有点不确定您到底在做什么,但没关系。我认为最灵活的方法是创建自己的自定义事件。在任何类之外创建一个委托:

public delegate void WelcomeClick(object sender, EventArgs e);

在 Welcome 内部,您需要创建事件处理程序,它可以是静态的或实例的一部分。
public event WelcomeClick OnClick;

在欢迎页面的按钮点击事件中,您可以使用相同的参数直接调用该事件:
if (OnClick != null)
                OnClick(sender, e);

0
一种方法是在numbers中引用panel1,因为它们都是在form1中创建的,你可以将一个作为参数传递给另一个的构造函数。

我该如何在 Numbers.cs 中引用这样的面板?我有一个名为 UserControls 的文件夹,在其中我现在有三个用户控件。但其中一个需要更改 form1.cs 中的 panel1(切换到另一个用户控件)。 - user710502
你提出的责任链只会增加调试和维护的复杂度。 - IAbstract

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接