c# - Winforms 事件架构

标签 c# winforms

尝试在 winforms 中构建一个简单的应用程序,但我注意到我对 winforms 模型中的事件的理解存在差距。我知道我已经很接近解决方案了,但是有些事情我不知道如何使用“winforms 方式”

这是我要完成的 UI 布局。 Form1 是通过 VS2019 模板生成的,但是 LeftSide 和 RightSide 是我构建的两个独立的类。

*****Form1************************
|                                |
| **LeftSide***   **RightSide**  |
| |           |   |           |  |
| | _TextBox  |   | _TextBox  |  |
| | _Button   |   | _Button   |  |
| |           |   |           |  |
| |           |   |           |  |
| *************   *************  |
|                                |
**********************************

左侧和右侧:

  • 返回一个带有文本框和按钮的面板
  • 具有未公开的“子”控件(即类本身负责 UI 布局和数据验证)
  • 需要互相交流和Form1交流
  • 没有继承任何东西;它们通过命名空间在 Form1 中使用
  • 在 Form1 中实例化

这是(一个不完整的)Form1,不知道要在这里添加什么

namespace myapp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}

这是 LeftSide 和 RightSide 类(请注意,它们是相同的,只是将“左”一词替换为“右”)

namespace myapp.LeftSide
{
     class LeftSide
     {
            private Panel LeftSide_Panel = new Panel();
            private Textbox LeftSide_TextBox = new Textbox();
            
            private Button LeftSide_Button = new Button();

            private string LeftSide_Data; //store TextBox.text here

            public ReturnPanel()
            {
             //return a Panel that Form1 can use
             LeftSide_Panel.Controls.Add(LeftSide_Button);
             LeftSide_Panel.Controls.Add(LeftSide_TextBox);
             return this.LeftSide_Panel;
            }
      }
}

我知道我可以通过在 LeftSide 中创建一个函数来为 LeftSide_Button 创建一个自定义事件处理程序,如下所示:

private void LeftSide_Button_Click(object sender, EventArgs e)
{
 //read the textbox, assume it is valid and store the string in our LeftSide_Data
 this.LeftSide_Data = this.LeftSide_TextBox.Text;
}

如果我想将数据保留在类的本地,则上述方法可行,但我不知道如何将 LeftSide_Button_Click 主要暴露给 Form1,有时暴露给 RightSide。

我的问题是:

  • 如果 LeftSide 拥有其文本框内的数据(并存储在 LeftSide_Data 中)并且 LeftSide_Button_Click 是我的自定义验证事件(为简化起见,上面未显示验证)Form1 如何不仅成为通知按钮已被点击但也发送了 LeftSide_Data 中的字符串?
  • 如何向任何想要订阅的人公开 LeftSide 事件?是使用“delegate”关键字还是“event”关键字?或者是其他东西?基于事件的关键字太多,因此是混淆的主要来源。
  • 是否应该将 private void LeftSide_Button_Click(object sender, EventArgs e) 从返回 void 更改为 private Eventhandler LeftSide_Button_Click(object sender, EventArgs e) 如果是这样,是什么我回来了……EventHandler 是由什么“制成”的?

编辑:我找到了下图,即使它没有随事件一起传递数据,实现它是否是朝着正确方向迈出的一步? enter image description here

最佳答案

您可以声明一个代表您的自定义事件的签名 的委托(delegate),提供您希望传递的任意数量的参数。然后您只需声明该委托(delegate)类型的事件。任何人都可以订阅您的自定义事件,以便在事件发生时收到通知。

这是一个简单的示例,其中委托(delegate)名为 dlgLeftSideData,事件名为 LeftSideData。它传递发送者(LeftSide 产生事件的实例)以及字符串数据。还有一个公共(public)只读属性,您可以根据需要通过发件人访问该属性。我已经连接了按钮的点击事件以进行“验证”,然后如果有任何订阅者它会引发自定义事件:

class LeftSide
{

    public event dlgLeftSideData LeftSideData;
    public delegate void dlgLeftSideData(LeftSide sender, string data);
    
    private Panel LeftSide_Panel = new Panel();
    private TextBox LeftSide_TextBox = new TextBox();
    private Button LeftSide_Button = new Button();

    public LeftSide()
    {
        LeftSide_TextBox.Location = new Point(5, 5);
        LeftSide_Button.Location = new Point(5, 25);            
        LeftSide_Panel.Controls.Add(LeftSide_TextBox);
        LeftSide_Panel.Controls.Add(LeftSide_Button);

        LeftSide_Button.Click += LeftSide_Button_Click;
    }

    private void LeftSide_Button_Click(object sender, EventArgs e)
    {
        if (true) // some kind of validation
        {
            LeftSideData?.Invoke(this, this.Data); // raise the event if there are any subscribers
        }
    }

    public string Data
    {
        get
        {
            return LeftSide_TextBox.Text;
        }
    }
    
    public Panel LeftSidePanel
    {
        get {
            return this.LeftSide_Panel;
        }                        
    }

}

下面是 Form1 中的示例代码,它订阅自定义事件并对接收到的数据执行某些操作:

public partial class Form1 : Form
{

    LeftSide ls = new LeftSide();

    public Form1()
    {
        InitializeComponent();
        this.Controls.Add(ls.LeftSidePanel);
        ls.LeftSideData += Ls_LeftSideData;
    }

    private void Ls_LeftSideData(LeftSide sender, string data)
    {
        label1.Text = data;
        // or we could use "sender" somehow as well
        label1.Text = sender.Data; // get value from the read-only property
    }

}

您可以在您的类中创建一个属性或方法来接收对另一个 LeftSide/RightSide 的引用并在内部订阅事件。

关于c# - Winforms 事件架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62866364/

相关文章:

c# - 标签 MVVM 中显示的 WPF 百分比状态

c# - 如何检查字符串变量是否包含数组中字符串元素的子字符串 - C#

c# - 停止模拟 IFormFile 创建 FileCopy

c# - Control.Invoke 展开外部异常并传播内部异常

c# - 如何使用 LockBits 将位图中非黑色的像素着色为黄色?

c# - 移动当前可执行文件c#

c# - ASP.net c#,采用不同参数类型的同名方法

c# - 从 Visual Studio-2012 降级到 Visual Studio-2010

c# - 使用 Process.Start() 时 Windows 窗体 MouseUp 触发两次

c# - 打印导致视觉样式异常