0

Form1 has a richtextbox1 and UserControl1 has a button1
Form1 loads and adds an instance of UserControl1.
I click the button and the richtextbox prints "hello"

//UserControl1.cs
public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var parent = Parent as Form1;
        parent.somemethod("hello");
    }
}


//Form1.cs
public Form1()
    {
        InitializeComponent();
    }

    public void somemethod(string message)
    {
        richTextBox1.Text = message;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        UserControl1 uc = new UserControl1();
        //flowLayoutPanel1.Controls.Add(uc);
        Controls.Add(uc);
    }

The problem:
I added a flowlayoutpanel to form1 and replaced Controls.Add(uc); with flowLayoutPanel1.Controls.Add(uc);

Exception raised when i click the button:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
parent was null.

Edit: the flowlayout panel is my parent right? that's the problem?

Edit1: @Eric, if i did what you suggested, it won't work. anyways this is the full code for each file

  • Form1 x = new Form1() didn't help. passing the message via form1 construtor (overloaded) didnt work either. mind writing it down? – user1242840 Jul 18 '19 at 16:26
  • Passing in a new Form1() won't help because you need the instance of Form1 that is being displayed. See edit to my answer for a solution. – Eric J. Jul 18 '19 at 16:56

2 Answers2

0

Your code

var parent = Parent as Form1;

gets the button's parent and casts it to Form1.

I added a flowlayoutpanel to form1 and replaced Controls.Add(uc); with flowLayoutPanel1.Controls.Add(uc);

The button's parent is no longer of type Form1, but a flow layout panel. At this point, you need the buttons parent's parent.

There is a convenient function you can use to find the form a control is on even if it is held in containers. Appropriately, it's called FindForm().

Replace

parent.somemethod("hello");

with

button1.FindForm().somemethod("hello");
Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • ok so the edit i made was true and i was going in the right direction. Sorry i still don't know how to do that. The complete app (the above is just a demo) has form1 and in it a tabcontrol and in that a tabpage and in that my usercontrol. there's a button in form1 outside the tabcontrol. if i click on that button, i know how to reach any control in my uc. `Control[] x = Controls.Find("txtmessage", true);` but what you're asking me to do is go backwards ie up the tree and i honestly don't know how to do that – user1242840 Jul 18 '19 at 16:49
  • Added an easy way to find the form. – Eric J. Jul 18 '19 at 16:56
  • sorry but how will `button1.findForm()somemethod("hello");` work if button1 in this scenario belongs to usercontrol1 not form1. usercontrol1 and form1 are in two seperate files. i edited my question to clarify. sorry! – user1242840 Jul 18 '19 at 17:07
  • FindForm() recursively travels up all parents until it finds a form. Did you try making the code change? – Eric J. Jul 18 '19 at 20:44
  • yes i did but i couldn't get it to work but if you check the answer i wrote below, i fixed my actual code thanks to your tip about FindForm. If you could check it and tell me if i did it properly or not thank you again! – user1242840 Jul 20 '19 at 15:53
0

UserControl has one button called button1
Form1 flowLayoutPanel1 and richTextBox1

Form1 loads and adds the usercontrol to the flowlayoutpanel located in form1
i click on button1 and richtextbox1 prints hello

//UserControl1
public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var a = Parent as FlowLayoutPanel;
        Form f = a.FindForm();
        Control[] s = f.Controls.Find("richTextBox1", true);
        s[0].Text = "hello";
    }
}

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

    private void Form1_Load(object sender, EventArgs e)
    {
        UserControl1 uc = new UserControl1();
        flowLayoutPanel1.Controls.Add(uc);
    }
}


this works! I hope there's no exception scenario to this logic. Thanks to @Eric J for telling me about FindForm. Now someone please confirm that this is the way it's supposed to work so that I can give the man a vote