Resolved Accessing Form Methods from Other Forms

NotVerySharp

Member
Joined
Sep 7, 2021
Messages
6
Programming Experience
Beginner
Hey, I'm super new to C# and I need some help. I couldn't really find what I needed exactly.

I have three forms, Main menu (Form 1), another form with just one button (Form 2) and another one with Adobe PDF Reader (Form 3).
I'd like to click the button in Form 2, call a method (OpenChildForm) in Form 1 that switches the form to Form 3, then inside Form 3 load a PDF (call method loadPDF()).
Source code.

Thanks for help!
 
Generally speaking, objects' knowledge of other objects should only flow one way. In your case, form 1 is creating form 2 so form 1 knows about form 2 but form 2 should not know about form 1. As such, form 2 would not be able to directly affect form 1. The reason for this is to maintain loose coupling, i.e. form 2 can always do what it does whether it was created by form 1 or in a completely different manner and place.

The way to accomplish your aim while maintaining loose coupling is for form 2 to raise an event to indicate that something should happen. Form 2 then leaves it up to whoever is listening to make that something happen in whatever way it sees fit. This is much like a Button raises a Click event and then whoever is handling that event can do whatever they want to in response. In your case, form 1 would handle the event and it would then call its own OpenChildForm method. Your form 2 might look like this:
C#:
public event EventHandler DoSomething;

protected void OnDoSomething(EventArgs e)
{
    DoSomething?.Invoke(this, e);
}

private void button1_Click(object sender, EventArgs e)
{
    OnDoSomething(EventArgs.Empty);
}
and your form 1 might look like this:
C#:
private void OpenForm2()
{
    var f2 = new Form2();

    f2.DoSomething += Form2_DoSomething;
    f2.FormClosed += Form2_FormClosed;

    f2.Show();
}

private void OpenForm3()
{
    // ...
}

private void Form2_DoSomething(object sender, EventArgs e)
{
    OpenForm2();
}

private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
    var f2 = (Form2)sender;

    f2.DoSomething -= Form2_DoSomething;
    f2.FormClosed -= Form2_FormClosed;
}
You may find it beneficial to read my blog post about custom events.
 
Hey,

thanks a lot for your reply, it's really helpful. However, I just tried copy-pasting it for now and adding a message box, and it seems that the event doesn't get fired after clicking the button in Form2.
I tried going through your blog post, thanks a lot for that as well, although for now, it's a little bit too advanced for me.

Any ideas what I could be doing wrong?

Thanks!
 
Are you sure that the event handler button1_Click was hooked up to the button in Form2?
 
Please show us your code.
 
It should be, yes. I included another message box that appears after clicking the button.
The fact that you used a message box indicates that you don't know how to debug, so you should stop what you're doing and learn that now. Don't worry; that's what I used to do when first started with VS as well, but you need to learn how to debug properly so now's the time to do so. What you should have done is set a breakpoint on the method and then see if execution breaks at that point when you click the Button. Of course, you should also actually look to see whether the event handler is registered first, which means selecting the Button in the designer, opening the Properties window, clicking the Events button and then checking to see whether that method is selected for that event.
 
I tried messing with the debugging a bit, clicking the button doesn't break the execution. For now, I'd just like to figure out what I'm doing wrong when subscribing to the event in the first form. So here's the code.

Form 2:
using System;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form2 : Form
    {
        public event EventHandler DoSomething;
        public Form2()
        {
            InitializeComponent();
            Subscribe2();
        }

        //Check if the event fires in Form 2
        private void Subscribe2()
        {
            DoSomething += Message2;
        }

        private void Message2(object sender, EventArgs e)
        {
            MessageBox.Show("Form 2");
        }

        protected void OnDoSomething(EventArgs e)
        {
            DoSomething?.Invoke(this, e);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            OnDoSomething(EventArgs.Empty);
        }
    }
}

Form 1:
using System;
using System.Windows.Forms;

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

        private void Subscribe1()
        {
            var f2 = new Form2();
            f2.DoSomething += Message1;
        }

        private void Message1(object sender, EventArgs e)
        {
            MessageBox.Show("Form 1");
        }

        private void openForm_Click(object sender, EventArgs e)
        {
            var f2 = new Form2();
            f2.Show();
        }
    }
}
 
If you put a breakpoint on the method and it's not hit when the event is raised what you're doing wrong is not subscribing to the event at all. Did you look in the Properties window? If no handler is selected for that event then select the one you want. All methods with the appropriate signature will be listed in the corresponding drop-down.
 
Yes, the handler for the button is assigned correctly to button1_Click. Clicking the button fires the event DoSomething, Form 2 receives it and shows the message box with text "Form 2". But I get no response from Form 1, a message saying "Form 1" should appear. The codes in both forms are pretty much identical, so I guess something must be missing in Form 1.
 
You're not handling the event of the form you're showing. Here:
C#:
private void Subscribe1()
{
    var f2 = new Form2();
    f2.DoSomething += Message1;
}
you create an instance and handle its event, then here:
C#:
private void openForm_Click(object sender, EventArgs e)
{
    var f2 = new Form2();
    f2.Show();
}
you create a different instance and show it. You're not handling the event of that second instance so, when it raises the event, you won't be notified. The solution is to not create two different instances. Create one instance, handle its event and then show it:
C#:
private void openForm_Click(object sender, EventArgs e)
{
    var f2 = new Form2();
    f2.DoSomething += Message1;
    f2.Show();
}
 
Back
Top Bottom