0

I need to make windows forms program, that:

a) shows 2 forms with one textbox and one button each

b) when you press the button on one form, program copies text from that form to second form

c) when you press the button on the second form, program copies text from that form to first form

I've tried several different aproaches and got bogged down in encapsulation problems, since both forms has to be in separate instances, right? I've managed to make it work, so it creates new instance of form with new text in textbox every time you click, but after several steps I ended up with screen full of new windows and I need it to show only 2 windows through whole runtime.

Ennoia
  • 3
  • 2
  • Just keep a reference to the first time you create a second window and keep using that. – Abion47 Jan 19 '17 at 21:14
  • [Interaction between forms — How to change a control of a form from another form?](http://stackoverflow.com/a/38769212/3110834) – Reza Aghaei Jan 19 '17 at 22:36

3 Answers3

0

Create the windows in your Main method, but don't show them immediately, then access them through the static properties:

public static class Program {

    public static Form1 Form1 { get; private set; }
    public static Form2 Form2 { get; private set; }

    public static Int32 Main(String[] args) {

        using( Program.Form1 = new Form1() )
        using( Program.Form2 = new Form2() ) {

            Application.Run( Program.Form1 ); // Form1's `Load` method would then show `Form2`
        }
        Program.Form1 = Program.Form2 = null;

        return 0;
    }
}

Form1 (is responsible for showing Form2 because Application.Run only shows a single form itself):

public class Form1 : Form {

    protected override void OnLoad(...) {

        Program.Form2.Show();

    }

    private void Button1_Click(...) {

        Program.Form2.TextBox1.Text = this.textBox1.Text;
    }
}

Form2 (you need to expose its TextBox via a public property):

public class Form2 : Form {

    public TextBox TextBox1 { get { return this.textBox1; } }
}
Dai
  • 141,631
  • 28
  • 261
  • 374
  • I had to fit your descriptions into default Visual Studio generated code, but after few changes it worked as intended. – Ennoia Jan 19 '17 at 22:50
  • @Ennoia Don't put your code in `.designer.cs` files because they'll be overwritten. Is there a reason you can't put it in the non-designer file? – Dai Jan 19 '17 at 23:22
  • What if the use closes Form2, then hits the button on Form1 to send text? – Idle_Mind Jan 20 '17 at 01:00
  • @Idle_Mind If `Form2` is disposed after it's closed then you'll get an `ObjectDisposedException` - you will need to instead hide `Form2` instead of closing it, so it won't be disposed. – Dai Jan 20 '17 at 01:14
  • ...or you can check to see if it has been disposed and recreate it as in my example. Just wanted the user to be aware of that caveat... – Idle_Mind Jan 20 '17 at 01:21
0

Here's an example that shows how to pass a reference to the first form, into the second form using its Constructor. That reference is stored at class level so it can be used later. The exact same code/form is being used for both instances:

public partial class Form1 : Form
{

    private Form1 target = null;

    public Form1()
    {
        InitializeComponent();
        this.Text = "Instance #1";
        this.target = new Form1(this);
        this.target.Text = "Instance #2";
        this.target.Show();
    }

    public Form1(Form1 target)
    {
        InitializeComponent();
        this.target = target;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (this.target == null || this.target.IsDisposed)
        {
            this.target = new Form1(this);
            this.target.Show();
        }
        this.target.textBox1.Text = this.textBox1.Text;
    }

}
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
0

got bogged down in encapsulation problems, since both forms has to be in separate instances, right?

"encapsulation" immediately made me think of nested classes. The quintessential use case is for a class that is not/should not be used anywhere except in the containing class.

The idea is to allow clients to instantiate Form1 but have no access to Form2 or any of its members. If you need to expose anything from Form2 I suggest you write Form1 properties so that the client sees everything coming from Form1 only.

public class Form1 : Form {
   protected Form Sibling { get; set; }

   public Form1() {
      Sibling = new Form2(this);
   }

   protected override void OnLoad(...) {
      Sibling.Show();
   }

    private void Button1_Click(...) {
       Sibling.TextBox1.Text = this.textBox1.Text;
    }

   protected class Form2 : Form {
      protected Form Sibling { get; set; }

      public Form1 ( Form mySibling ) {
         Sibling = mySibling;
      }

       private void Button1_Click(...) {
          Sibling.TextBox1.Text = this.textBox1.Text;
       }
   } // Form2
} // Form1
radarbob
  • 4,964
  • 2
  • 23
  • 36