【问题标题】:C# Event driving between user controls on win formsWinforms中用户控件之间的C#事件驱动
【发布时间】:2018-08-20 12:44:07
【问题描述】:

我有一个主窗体 (form1),它有一个面板 (panel1) -- 见图。

Form1 pic

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...";
    }
}

非常感谢任何帮助。

【问题讨论】:

    标签: c# winforms events


    【解决方案1】:

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

    更好的是创建两个用户控件。一个包含您想要在操作员按下按钮 1 时显示的所有控件,另一个包含您想要在操作员按下按钮 2 时显示的所有控件。

    要创建用户控件,请使用菜单项目 - 添加用户控件,或右键单击项目的解决方案资源管理器并选择 add new item

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

    然后以你的形式:

    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 个用户控制“屏幕”,可以从更大的菜单中选择。当时的担忧是不能同时打开两个屏幕。您的建议解决了我遇到的问题...有没有更好的方法来处理实际程序中可用的屏幕数量?
    • 我认为你的 UserControls 有很多相似之处。使用设计器将子用户控件放在其他用户控件上。例如,如果您在所有 120 个用户控件的右下角都有 OK/Cancel 按钮,请创建一个 OK/Cancel 用户控件,并进行适当的处​​理,并将其放在需要这些按钮的所有用户控件上。
    【解决方案2】:

    我不确定您要完成什么,但您似乎正在尝试从其他对象更改对象的状态,而其他对象不能引用它们尝试更改的对象。

    在这种情况下,我将创建一个类型,它充当某种管理器,订阅所有这些控件的事件。您可以在 UC 课程中创建自己的事件,或者像您已经在做的那样使用 Windows 窗体 click 事件。

    由于事件的处理程序是在管理器中定义的,因此您可以轻松编写适用于其他用户控件的逻辑,只要管理器具有对它们的引用。

    像这样:

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

    这是您可以做什么的粗略想法。这里缺少设置 target 字段必须设置为的逻辑。您需要创建逻辑来告诉流量人员哪个控件设置哪个控件的文本。

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

    【讨论】:

    • 谢谢。你在参考问题上的钱是对的。我会试试你的建议。
    猜你喜欢
    • 2023-03-22
    • 2011-01-12
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多