mynameisausten
mynameisausten

Reputation: 57

Winforms Events Architecture

Trying to build a simple app in winforms but I'm noticing a gap in my understanding of events inside the winforms model. I know I'm fairly close to the solution but there are a few things that I dont know how to do the "winforms way"

Here is the UI layout of what I am trying to accomplish. Form1 is generated via the VS2019 template, but both LeftSide and RightSide are two separate classes that I have built.

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

Both LeftSide and RightSide:

Here is (an incomplete) Form1, idk what to add here

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

Here is both LeftSide and RightSide classes (note that they are the same, except substitute the word "left" with "right")

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

I understand that I can make a custom event handler for LeftSide_Button by creating a function inside LeftSide like such:

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

The above works if I wanted to keep the data local to the class, but I'm at a loss of how to expose LeftSide_Button_Click to, primarily, Form1 and sometimes to RightSide.

My issues are:

EDIT: I found the following diagram, and even though it does not pass data along with the event, is implementing this a step in the right direction? enter image description here

Upvotes: 3

Views: 213

Answers (1)

Idle_Mind
Idle_Mind

Reputation: 39122

You can declare a delegate that represents the signature of your custom event, providing any number of parameters that you desire to pass out. Then you simply declare an event of that delegate type. Anyone can subscribe to your custom event to be notified when it occurs.

Here's a simple example with the delegate called dlgLeftSideData, and the event called LeftSideData. It passes out the sender (instance of LeftSide producing the event) as well as the string data. There is also a public read-only property that you could access via the sender if you wanted to. I've wired up the click event of the button to do "validation" and then it raises the custom event if there are any subscribers:

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

}

Here is example code in Form1 that subscribes to the custom event and does something with the received data:

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
    }

}

You can make a property or method in your classes that receives a reference to the other LeftSide/RightSide and subscribes to the events internally.

Upvotes: 1

Related Questions