C# C win窗体上用户控件之间的事件驱动

C# C win窗体上用户控件之间的事件驱动,c#,winforms,events,C#,Winforms,Events,我有一个主窗体1,它有一个面板1-参见图 Panel1加载两个不同的用户控件中的一个,基于按下哪个按钮来模拟屏幕变化。我在用户控件1上有一个按钮,它需要在用户控件2上更改文本 我遇到的问题是,用户控件是通过按下表单1上的按钮动态创建的,请参见下面的代码,这导致我在尝试链接事件时出现问题- public partial class Form1 : Form { public Form1() { InitializeComponent(); panel

我有一个主窗体1,它有一个面板1-参见图

Panel1加载两个不同的用户控件中的一个,基于按下哪个按钮来模拟屏幕变化。我在用户控件1上有一个按钮,它需要在用户控件2上更改文本

我遇到的问题是,用户控件是通过按下表单1上的按钮动态创建的,请参见下面的代码,这导致我在尝试链接事件时出现问题-

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        panel1.Controls.Add(new Screens.UC1());

    }

    private void button1_Click(object sender, EventArgs e)
    {
        foreach (Control ctrl in panel1.Controls)
        {
            ctrl.Dispose();
        }
        panel1.Controls.Add(new Screens.UC1());
    }

    private void button2_Click(object sender, EventArgs e)
    {
        foreach (Control ctrl in panel1.Controls)
        {
            ctrl.Dispose();
        }
        panel1.Controls.Add(new Screens.UC2());
    }
}
当动态创建对象实例时,处理将这些类型的项与事件链接的最佳方法是什么。我还尝试创建屏幕实例,然后引用这些实例,但遇到了范围问题

UC1用户控件1的代码

public partial class UC1 : UserControl
{
    public UC1()
    {
        InitializeComponent();

    }

    private void button1_Click(object sender, EventArgs e)
    {
        //Event to change text on UC2
    }
}
UC2用户控件2的代码

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

    public void WriteText(object sender, EventArgs e)
    {
        label2.Text = "Text Changed...";
    }
}

非常感谢您的帮助。

我不确定您想要完成什么,但看起来您正在尝试从其他对象更改对象的状态,这些对象无法引用它们试图更改的对象

在本例中,我将创建一个类型,作为订阅所有这些控件的事件的某种管理器。您可以在UC类中创建自己的事件,也可以像现在一样使用Windows窗体单击事件

因为事件的处理程序是在管理器中定义的,所以只要管理器有对其他用户控件的引用,您就可以轻松地编写将在其他用户控件上工作的逻辑

像这样:

public class ClickTrafficer {
    private UC target;

    public void HandleClick(object sender, UCClickHandlerEventArgs ea) {
        target.WriteText(ea.TextToWrite);
    }
}

public Form1()
{
    InitializeComponent();
    var trafficer = new ClickTrafficer();
    var screen1 = new Screens.UC1();
    screen1.Click += trafficer.HandleClick;
    panel1.Controls.Add(screen1);
}
这是一个关于你能做什么的粗略想法。这里缺少设置目标字段必须设置为什么的逻辑。您需要创建逻辑,告诉流量器哪个控件设置哪个控件的文本


此外,我创建的ClickTraffice使用带有自定义eventargs的自定义事件,您需要定义这些事件或找到通过内置事件传递必要信息的方法。创建事件非常简单,因此您可以在线查找。

为什么在操作员按下按钮时处理并创建所有这些控件

更好的方法是创建两个UserControls。一个包含操作员按下按钮1时要显示的所有控件,另一个包含操作员按下按钮2时要显示的所有控件

要创建用户控件,请使用菜单“项目-添加用户控件”,或在项目的解决方案资源管理器中单击鼠标右键,然后选择“添加新项”

使用要显示的所有控件布局用户控件。添加事件处理程序等

然后以您的形式:

private readonly UserControl userControl!;
private readonly UserControl userControl2;

public MyForm()
{
    InitializeComponent()
    this.userControl1 = new UserControlA(...);
    this.userControl2 = new UserControlB(...);

    // make sure that the user controls are Disposed when this form is Disposed:
    this.Components.Add(this.userControl1);
    this.Components.Add(this.userControl2);
}

void OnButton1Clicked(object sender, ...)
{
    // remove userControl2 from the panel
    this.Panel1.Controls.Remove(this.userControl2);
    // add userControl1 to the panel
    this.Panel1.Controls.Add(this.userControl1);        
} 

这样,创建/添加/定位/添加事件处理程序的所有开销以及所有清理只需执行一次:在构建表单期间。切换用户控件将在一瞬间完成

谢谢。你在参考资料问题上是对的。。我会试试你的建议。谢谢你的回复。此代码表示的程序有大约120个用户控制屏幕,可以从较大的菜单中选择。当时的问题是两个屏幕不能同时打开。你的建议解决了我的问题。。。有没有更好的方法来处理实际程序中可用的屏幕数量?我认为您的用户控件有很多相似之处。使用设计器将子用户控件放置在其他用户控件上。例如,若在所有120个用户控件的右下角都有“确定/取消”按钮,那个么创建一个具有正确处理的“确定/取消”用户控件,并将其放置在所有需要这些按钮的用户控件上。