0

I have a program with two forms. The second form, Form2 in which I want a few labels initialized with values from the main form.

The code:

public Form2()
        {
            InitializeComponent();
            Form1 mainForm = (Form1)this.Owner;
            lblName.Text = mainForm.gvRow.Cells[2].Value.ToString();
            lblItemType.Text = mainForm.gvRow.Cells[1].Value.ToString();
            lblLocation.Text = mainForm.gvRow.Cells[3].Value.ToString();
        }

For some reason this does not work in the Form2() section, this.Owner is null. But if I was to place the code in an event method it works just fine.

How can I fix that?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
sd_dracula
  • 3,796
  • 28
  • 87
  • 158
  • 1
    Use the `Load` Event. The `Owner` is only initialized after you Show the form, which then in return raises the Load Event. – LunicLynx Apr 01 '14 at 13:58
  • How do you show Form2? Anyway it's not a good practice doing it this way, You should use a better mechanism. – VahidNaderi Apr 01 '14 at 14:01
  • 1
    It doesn't get an Owner until the Show(owner) call. That happens *after* the constructor runs. The Load event would be the first place you can start poking for it. Passing it as a constructor argument would be wise. – Hans Passant Apr 01 '14 at 14:01

7 Answers7

4

The second form shouldn't need to even know about your main form in the first place. Even if it did, it's an extremely bad idea to be reading into its internal controls.

Instead your second form should have public properties through which it can accept the data that your main form wants to provide to it, without exposing any of its internal controls, and the main form can set those properties using the data from its controls. You could also potentially use parameters to the constructor instead, if you have just a bit of data, and that is the only time you need to provide it.

public class Form2
{
    public string Name
    {
        get { return lblName.Text; }
        set { lblName.Text = value; }
    }
}

public class MainForm
{
    public void Foo()
    {
        Form2 child = new Form2();
        child.Name = mainForm.gvRow.Cells[2].Value.ToString();
        child.Show();
    }
}
Servy
  • 202,030
  • 26
  • 332
  • 449
2

This code is executed when the Form2 form is created. The Owner isn't set yet (and, presumably, the data isn't present yet). If you put it in the VisibleChanged event handler - it will be executed when the Owner and data are (presumably) present.

ispiro
  • 26,556
  • 38
  • 136
  • 291
1

Use the Load Event. The Owner is only initialized after you Show the form, which then in return raises the Load Event.

LunicLynx
  • 939
  • 1
  • 8
  • 16
1

Owner isn't set until the form is shown - i.e. in ShowDialog, not during the constructor. You should pass the parent as a parameter in the constructor:

public Form2(Form1 mainForm)
{
    InitializeComponent();
    lblName.Text = mainForm.gvRow.Cells[2].Value.ToString();
    lblItemType.Text = mainForm.gvRow.Cells[1].Value.ToString();
    lblLocation.Text = mainForm.gvRow.Cells[3].Value.ToString();
}
mike1952
  • 493
  • 5
  • 12
1

That's because the Owner is not initialized yet in the Form2 constructor, set your code in your Form2_Load event

Karim AG
  • 2,166
  • 15
  • 29
0

Use the Form.Show(IWin32Window) overload to pass the owner to the child form.

http://msdn.microsoft.com/en-us/library/szcefbbd(v=vs.110).aspx

sotn0r
  • 109
  • 6
-1

You need to set the Owner property yourself

As an alternative you could pass a reference to Form1 to the Form2 constructor. In the code that opens Form2 you probably have something like this:

var form2 = new Form2();
form2.Show();

You could replace that with:

var form2 = new Form2(this);
form2.Show();

In Form2 you'd add a constructor overload:

public Form2(Form1 owningForm)
{
     InitializeComponent();
     Form1 mainForm = owningForm;
     lblName.Text = mainForm.gvRow.Cells[2].Value.ToString();
     lblItemType.Text = mainForm.gvRow.Cells[1].Value.ToString();
     lblLocation.Text = mainForm.gvRow.Cells[3].Value.ToString();
}

If different "owning forms" are possible you may need to define an interface instead of passing Form2.

Laoujin
  • 9,962
  • 7
  • 42
  • 69
  • Constructor Parameters in Windows Forms are against best practices. For every thing derived from `Control`. – LunicLynx Apr 01 '14 at 14:04
  • If you have dependencies, injecting them with the constructor is clean . I don't really see why this would be different for a Form? – Laoujin Apr 01 '14 at 14:06
  • Have a look at this: http://stackoverflow.com/questions/1784303/usercontrol-constructor-with-parameters-in-c-sharp – LunicLynx Apr 01 '14 at 14:09