0

I am new with C# and this question must be a common question but it really takes my time. With this scenario i cannot go further with my project.

What I need is, I just want to pass the value from form2 listview to form1 textboxes by calling the method in form1 in button_Click event. Whereas, when I click the button that will trigger my code I get nothing .

Problems Encountered:

1: When I declare Form1 f1 = New Form1(), The compiler still compile the code wherein my method is to be called in Button_Click Event in Form2. But When I Clicked the button there's nothing changes happened in my textboxes.

2: When I declare Form1 as Public Form1 f1;, and Clicked the button I'm getting a NullReferenceException .

3: I need my Form2 to be showed as ShowDialog();

Any help will be appreciated.

My code in Form1

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Threading;

namespace Practice_CS
{
    public partial class Form1 : Form
    {  

        public Form1()
        {
            InitializeComponent();
        }

        private void btnViewList_Click(object sender, EventArgs e)
        {
            Form2 f2 = new Form2();
            f2.ShowDialog();
        }

        public void setFields(string sName,string sAge,string sGender) {
            txtName.Text  = sName;
            txtAge.Text  = sAge;
            txtGender.Text  = sGender;        
        }



    }
}

My code in Form2

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Practice_CS
{
    public partial class Form2 : System.Windows.Forms.Form
    {        

        public Form2()
        {
            InitializeComponent();            
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            lvlist.Items.Add("Juli");
            lvlist.Items[0].SubItems.Add("20");
            lvlist.Items[0].SubItems.Add("Male");

            lvlist.Items.Add("Mark");
            lvlist.Items[1].SubItems.Add("21");
            lvlist.Items[1].SubItems.Add("Male");

            lvlist.Items.Add("Shiela");
            lvlist.Items[2].SubItems.Add("18");
            lvlist.Items[2].SubItems.Add("Female");

        }

        private void btnSelect_Click(object sender, EventArgs e)
        {
            if (lvlist.Items.Count < 1) { return; }

            Form1 f1 = new Form1();
            f1.setFields(lvlist.FocusedItem.Text, lvlist.FocusedItem.SubItems[1].Text,     lvlist.FocusedItem.SubItems[2].Text);
            this.Close();
        }

        private void lvlist_DoubleClick(object sender, EventArgs e)
        {
            btnSelect_Click(btnSelect, e); 
        }

    }
}
Push Back
  • 11
  • 4
  • 1
    What is the problem? What error are you seeing? An exception is thrown? It won't compile? Data is not what you expect? You should give more detail of where exactly your problem is. – Chris Jun 04 '13 at 12:54
  • see http://stackoverflow.com/questions/16638265/trouble-calling-a-method-in-form-2-from-a-button-click-on-form-1-vb-net/16641180#16641180 – qwr Jun 04 '13 at 12:55
  • Thanks for a quick reply and sorry for my inconvenience, When I declared Form1 as New Form1, the compiler still compiles the code but when i clicked the button wherein my method is to be called. There's nothing changes in my textboxes. – Push Back Jun 04 '13 at 13:05
  • Yes, this has been asked/answered many times with similar context. Here are a few I've offered in the past... [Pass objects between forms](http://stackoverflow.com/questions/4887820/how-do-you-pass-an-object-from-form1-to-form2-and-back-to-form1/4887906#4887906) [Another that links to step-by-step samples too](http://stackoverflow.com/questions/10514050/how-to-get-variable-from-form1-to-form2-with-get-set/10516884#10516884) – DRapp Jun 04 '13 at 12:57

6 Answers6

3

in Form2 add a private field

private Form1 form1_;

change constructor

public Form2(Form1 form1) {
   form1_ = form1;
   InitializeComponent(); 
}

in Form1

Form2 f2 = new Form2(this);
f2.ShowDialog();

Now you can use form1_.setFields in Form2 (and not use a new Form1, which has nothing to do with the "calling" Form1)

EDIT

public Form2() {
   InitializeComponent();
}
public Form2(Form1 form1) : this() {
   form1_ = form1;
}
Raphaël Althaus
  • 59,727
  • 6
  • 96
  • 122
  • I'm not into windows forms anymore, but wouldn't this break the designer? – L-Four Jun 04 '13 at 13:19
  • @L-Three Maybe maybe, didn't work much with the designer during my (far away) windows forms time... – Raphaël Althaus Jun 04 '13 at 13:21
  • It seems it is the case for user controls (http://stackoverflow.com/questions/1784303/c-sharp-usercontrol-constructor-with-parameters), so I guess it's the same for forms. Anyway, as you said, it's all legacy now ;) – L-Four Jun 04 '13 at 13:31
  • @RaphaëlAlthaus: Thank you for your reply. Your code and explanation comes into my mind pretty well. As I do what you have showed above it works perfectly. But what are the consequences by changing the constructor of From2 if I have multiple forms that would call it? – Push Back Jun 04 '13 at 13:40
  • @PushBack Well, instead of changing constructor, you can add a new one, and keep the existing unchanged. – Raphaël Althaus Jun 04 '13 at 13:42
  • @RaphaëlAlthaus I see, is there more efficient way to use the methods in form1 without changing or adding the form2 constructor? – Push Back Jun 04 '13 at 14:47
  • @RaphaëlAlthaus, Thanks for your answers, don't mind my last question. I'm okay with your samples. Now, I can continue with my project. again Thanks. – Push Back Jun 04 '13 at 15:27
1

The natural approach at this problem (when you call a form as a modal dialog) is to save the values to be passed back to form1 through public properties on form2.

So in form2 declare these properties and set them internally when you close the form

public string Name {get; private set;}
public string Age {get; private set;}
public string Gender {get; private set;}

private void btnSelect_Click(object sender, EventArgs e)
{
    if (lvlist.Items.Count < 1) { this.DialogResult = DialogResult.None; return; }
    this.Name = lvlist.FocusedItem.Text;
    this.Age = lvlist.FocusedItem.SubItems[1].Text;
    this.Gender = lvlist.FocusedItem.SubItems[2].Text;
    this.DialogResult = DialogResult.OK;  
}

Now in your form1

private void btnViewList_Click(object sender, EventArgs e)
{
    using(Form2 f2 = new Form2())
    {
        if(DialogResult.OK == f2.ShowDialog())
        {
            // At this point f2 is still in memory but it is hidden
            // You could read the public properties exposed by the Form2
            string name = f2.Name;
            string age = f2.Age;
            string gender = f2.Gender;
        }
    } // <- At this point the f2 instance is closed and ready for GC 
}

This method has the advantage of detaching the functionality of Form2 from the presence of Form1.
No need to change the Form2 constructor or add another one and then test inside the code of Form2 to discover which is the current client that requires the functionality of Form2.

In this way instances of Form2 could be created wherever you need without binding it to an instance of Form1

Steve
  • 213,761
  • 22
  • 232
  • 286
  • Thanks for the reply and for the idea. But, Is there more efficient way to do the storing and retrieving the variables data without changing or adding the constructor of form2 nor declaring those properties in form2? – Push Back Jun 04 '13 at 14:44
  • You could make Form2 declare an event and then fire the event when needed. The form1 subscribe to the event and receive the notification, but honestly I think that this a bit complex for a simple DialogBox scenario. – Steve Jun 04 '13 at 14:48
  • By the way, the word 'Efficient' is difficult to understand in this context. What do you mean for efficiency? Maintanability, Speed, Memory ? – Steve Jun 04 '13 at 14:51
  • Now I realized that I have to study more before jumping to difficult way of coding I need to understand the fundamentals of C# first, hehe. For today I'm contended with your explanation and it works pretty well also. Thanks @Steve – Push Back Jun 04 '13 at 15:17
  • I mean, another way of coding/Different line of code :), But as for now I'm okay with this coz i can now continue with my project. again, thanks. – Push Back Jun 04 '13 at 15:24
0

You need a reference to Form1 in Form2. Otherwise, each form doesn't ever know about the existence of the other. Suggestion: add a reference to Form1 as an instance variable of Form2. Like this:

public partial class Form2
{
    // ... snip
    public Form1 otherForm;
}

That way Form2 can access Form1's members. You could then use this.otherForm.someMethod() in Form2's code.

A few things to take into account:

  • You'll still have to set the value for that variable, otherwise it'll be null.
  • Most people will suggest you to make that variable private, and set it in Form2's constructor. That's sound advice as well.
Geeky Guy
  • 9,229
  • 4
  • 42
  • 62
  • Thanks for your reply, Yes, that what was really happen when i don't change the constructor of form2, I'm getting the NullReferrenceException. – Push Back Jun 04 '13 at 13:47
0

Your problem is that you are creating a new instance of Form1 in the code of Form2. When you do this.Close() on Form2, you will return to the already existing instance of Form1.

A simple solution in your case would to pass the Form1 instance into the Form2 contructor like so:

new Form2(this);

However, a more appropriate solution is to expose properties on Form2 that represents the values Form1 is supposed to read. Then, your code in Form1 could look like:

var form2 = new Form2();
form2.ShowDialog();
this.FieldToSet = form2.SomeProperty;
0

The easiest thing to do would be to pass the instance of Form1 to Form2:

Form2 f2 = new Form2();
f2.Form1 = form1;
f2.ShowDialog();

In Form2, create a property like:

public partial class Form2 : System.Windows.Forms.Form
{
    public Form1 Form1 { get; set; }        
}

and then in Form2 you can use this instance to call the operation setFields:

private void btnSelect_Click(object sender, EventArgs e)
{
    if (lvlist.Items.Count < 1) { return; }   
    Form1.setFields(lvlist.FocusedItem.Text, lvlist.FocusedItem.SubItems[1].Text,     lvlist.FocusedItem.SubItems[2].Text);
    this.Close();
 }
L-Four
  • 13,345
  • 9
  • 65
  • 109
  • Thanks for your reply, I'm getting a NullReferenceException in button_click event. How can i get rid with this? – Push Back Jun 04 '13 at 14:57
0

You should send refference to the instance of the Form1 into Form2 instance to achive it.

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

    private void btnViewList_Click(object sender, EventArgs e)
    {
        Form2 f2 = new Form2(**this**);
        f2.ShowDialog();
    }


public partial class Form2 : System.Windows.Forms.Form
{        
    private Form1 form1;

    public Form2(Form1 form1)
    {
        InitializeComponent();       

        this.form1 = form1;
    }

    ....
    private void btnSelect_Click(object sender, EventArgs e)
    {
        if (lvlist.Items.Count < 1) { return; }

        **form1**.setFields(lvlist.FocusedItem.Text, lvlist.FocusedItem.SubItems[1].Text, lvlist.FocusedItem.SubItems[2].Text);
        this.Close();
    }
Viacheslav Smityukh
  • 5,652
  • 4
  • 24
  • 42
  • Thanks For the Help, my code now works fine. but, is there any option about referencing the instance of form1? – Push Back Jun 04 '13 at 13:44