Solved

How do I return a string value back to the main program from another form?

Posted on 2006-07-19
20
334 Views
Last Modified: 2007-12-19
Hi, From the main program, I have a pop up menu that certain selection would bring up a form from which I would like to return a user selected string value back to the main program.  How can I do that?  Thanks.  Below is the code of the form that I would like to return the "tvDomains.SelectedNode.Name"

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


namespace ppGlobal
{
    public partial class frmDomains : Form
    {
        public frmDomains()
        {
            InitializeComponent();
        }

        private void frmDomains_Load(object sender, EventArgs e)
        {
            // get the current forest
            Forest forest;

            try
            {
                forest = Forest.GetCurrentForest();
            }
            catch (ActiveDirectoryObjectNotFoundException ex)
            {
                // current context is not associated with domain/forest
                MessageBox.Show(ex.Message);
                return;
            }

            tvDomains.Nodes.Add(forest.Name, "Forest: " + forest.Name, 0);

            // all domains with this forest
            //Console.WriteLine("Domains in the forest:");
            foreach (Domain domain in forest.Domains)
            {
                tvDomains.Nodes.Add(domain.Name, domain.Name, 1);
            }
        }

        private void tvDomains_AfterSelect(object sender, TreeViewEventArgs e)
        {
            string domainName = e.Node.Name;        
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            string domainName = tvDomains.SelectedNode.Name;
            this.Close();
        }
    }
}
0
Comment
Question by:lapucca
  • 7
  • 5
  • 4
  • +1
20 Comments
 
LVL 13

Expert Comment

by:devsolns
ID: 17143005
I perhaps did this as well when i first began.  Dont treat forms like anything special.  Treat them like any other object.  How would you pass data from one object to another?  Take a look at MVC design pattern.  You should create an event in the form that is "sending" the data.  That way anyone can subsribe to that event and retrieve the data and it keeps the form sending back the data from having to be aware of the data reciepient.  Do you need help creating an event?
0
 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 17143014
The task is not stated clearly enough...

If you want to pass something to another form (program) from this form,

1. When you construct current form, pass a reference to the main form like below:

private mainForm Form;

        public frmDomains(Form mainForm)
        {
            InitializeComponent();
            this.mainForm = mainForm;
        }

then, to pass you info back to main form you need (e.g.) some method in the main form accepting you string

public void MainFormDoSomething(string data)
{
// do whatever you want to do with this string

}


and eventually how you pass data to main form from this form:

        private void btnOK_Click(object sender, EventArgs e)
        {
            string domainName = tvDomains.SelectedNode.Name;
            mainForm.MainFormDoSomething(domainNam);
            this.Close();
        }

0
 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 17143027
sorry, "private Form mainForm ;", not "private mainForm Form;"
This is just a class variable.
0
 
LVL 13

Expert Comment

by:devsolns
ID: 17143050
Here is a crued example.


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

        private void button1_Click(object sender, EventArgs e)
        {
            ChildForm childForm = new ChildForm();
            childForm.ChildFormUpdateEvent += new ChildForm.ChildFormUpdateDelegate(childForm_ChildFormUpdateEvent);
            childForm.ShowDialog();
        }

        void childForm_ChildFormUpdateEvent(object sender, ChildFormEventArgs args)
        {
            label1.Text = args.Value;
        }
    }









    public partial class ChildForm : Form
    {
        public delegate void ChildFormUpdateDelegate(object sender, ChildFormEventArgs args);

        public ChildForm()
        {
            InitializeComponent();
        }

        public event ChildFormUpdateDelegate ChildFormUpdateEvent = null;

        protected void ChildFormUpdateInvoke(string data)
        {
            ChildFormUpdateDelegate ev = ChildFormUpdateEvent;
            if (ev != null) ev(this, new ChildFormEventArgs(data));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ChildFormUpdateInvoke("my data to send");
        }

    }


    public class ChildFormEventArgs : EventArgs
    {
        public readonly string Value;

        public ChildFormEventArgs(string data)
        {
            Value = data;
        }
    }
0
 

Author Comment

by:lapucca
ID: 17143091
Thanks Anaki, but this all seems a bit complicated.   Is this the only way?  I guess no simple "return" when they are 2 different forms.


Also, I'm a bit confused with your following code.  Shouldn't it be "public mainForm Form;" ?  Also, What does this statement do, "this.mainForm = mainForm;" ?  Also, my mainform is named as FormMain.  Thank you.

private mainForm Form;

        public frmDomains(Form mainForm)
        {
            InitializeComponent();
            this.mainForm = mainForm;
        }

0
 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 17143259
OK, let's try to think logically (OOP lesson :)) If you and me want to send messages (or call) directly to each other we need our e-mails or phone numbers etc. So we need to give this information to each other, yes? As simple as that. If you don't know my phone number you can't call me.

In the same way, when we have two forms and want them to "talk" (exchange information) they need to know about each other.

How do you display your frmDomains? Probably, in your main form  (lets call the class for it as MainForm) you have a button somethin like:

private void btnShowDomainsForm(....) // button event handler in main form
{
     frmDomains f = new frmDomains();
     f.show();
}

OK, your main form creates child form f. So the main form "knows" about it's child!
However, form f has no idea about "parent". Therefore you need to give it somehow the reference to the main form. One way (not only)
is to pass the reference through constructor:

private void btnShowDomainsForm(....)
{
     frmDomains f = new frmDomains(this);
     f.show();
}

Keyword this means the reference to the object itself, in this case it is the reference to the main form (computer is clever to understand that :)).


Try to clarify you questions now:

    public partial class frmDomains : Form
    {
        private MainForm myReferenceToMainForm; // is empty yet, before constructor is called. Kinda your notebook :) And commonly it is private
// yould you like to make your notebook public :) !?

        public frmDomains(MainForm referenceSentByMainForm) // constructor
        {
            InitializeComponent();
            myReferenceToMainForm = referenceSentByMainForm; // Ah-ha, we know how to call to the main form! Kinda MainForm phone number :)
        }
....


And now when you have selected a node you wanted - call to the main form as I showed before:

        private void btnOK_Click(object sender, EventArgs e)
        {
            string domainName = tvDomains.SelectedNode.Name; // information you want to pass to main form
            mainForm.MainFormDoSomething(domainNam); // your phone call!
            this.Close();
        }

 as a response to your "phone call" the main form will do something. if you think a bit you will see that's very simple and easy.


Note to devsolns. You may trust me I know how to rise events and so on. And your code is better than mine, no doubts. Is that what you wanted to show here? :)

However, one can't understand delegates before understanding simple OOP principles. Too confusing.
0
 

Author Comment

by:lapucca
ID: 17143266
Thank you devslon,

I copy and paste you code to my project, compiled it, ran it and set break points but nothing happens when it reaches the code "  ChildFormUpdateInvoke("my data to send");"  Can you see what I'm doing wrong?  My code is as follow:

namespace ppGlobal
{
    public partial class frmDomains : Form
    {
        public delegate void ChildFormUpdateDelegate(object sender, ChildFormEventArgs args);

        public frmDomains()
        {
            InitializeComponent();
        }

        public event ChildFormUpdateDelegate ChildFormUpdateEvent = null;

        protected void ChildFormUpdateInvoke(string data)
        {
            ChildFormUpdateDelegate ev = ChildFormUpdateEvent;
            if (ev != null) ev(this, new ChildFormEventArgs(data));
        }


        private void frmDomains_Load(object sender, EventArgs e)
        {
            // get the current forest
            Forest forest;

            try
            {
                forest = Forest.GetCurrentForest();
            }
            catch (ActiveDirectoryObjectNotFoundException ex)
            {
                // current context is not associated with domain/forest
                MessageBox.Show(ex.Message);
                return;
            }

            tvDomains.Nodes.Add(forest.Name, "Forest: " + forest.Name, 0);

            // all domains with this forest
            //Console.WriteLine("Domains in the forest:");
            foreach (Domain domain in forest.Domains)
            {
                tvDomains.Nodes.Add(domain.Name, domain.Name, 1);
            }
        }

        private void tvDomains_AfterSelect(object sender, TreeViewEventArgs e)
        {
            string domainName = e.Node.Name;        
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            string domainName = tvDomains.SelectedNode.Name;
            ChildFormUpdateInvoke(domainName);
            this.Close();
        }
    }
}


public class ChildFormEventArgs : EventArgs
{
    public readonly string Value;

    public ChildFormEventArgs(string data)
    {
        Value = data;
    }
}


///The main progarm
        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmDomains domainsBrowser = new frmDomains();
            domainsBrowser.ShowDialog();
            InitTree(curDomain);
        }

        void childForm_ChildFormUpdateEvent(object sender, ChildFormEventArgs args)
        {
            curDomain = args.Value;
        }
0
 
LVL 29

Assisted Solution

by:anarki_jimbel
anarki_jimbel earned 150 total points
ID: 17143363
Just another qlue:

In the main form you may do something like that

        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmDomains domainsBrowser = new frmDomains();
            domainsBrowser.ShowDialog();
            //InitTree(curDomain);
        }

        public void MainFormDoSomething(string curDomain)
        {
              // do whatever you want to do with this string
            InitTree(curDomain);
        }

When domainsBrowser is closed (closing...) it calls MainFormDoSomething method and passes info to it.
And main form uses that info to call InitTree() method.

=========================  OR alternatively=============================

If you have "curDomain" variable as a field in your program (main form)

        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmDomains domainsBrowser = new frmDomains();
            domainsBrowser.ShowDialog();
            InitTree(curDomain);
        }

        public void MainFormDoSomething(string dataFromDialog)
        {
              // do whatever you want to do with this string
            curDomain = dataFromDialog;
        }

befor closing your dialog form sets curDomain variable and exits.
After that InitTree is called and curDomain is ready for it!
0
 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 17143485
Hey, lapucca, I have very simple and stupid solution you may like. No any references, delegates and other rubbish :)

I have two forms, main has label and button, child has textbox and button btnClose.
Code is below:

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

        private void button1_Click(object sender, EventArgs e)
        {
            ChildForm frm = new ChildForm();
            label1.Text = frm.GetTextFromTextBox();
        }
    }


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

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        public string GetTextFromTextBox()
        {
            this.ShowDialog();
            return textBox1.Text;
        }
    }
0
 
LVL 6

Accepted Solution

by:
mogun earned 350 total points
ID: 17143599
Hi,

You don't have to do anything complex for your scenario.

Let me first put down what i infer from your problem description.

1. You have a main form.
2. You are popping up a dialog ( another form) on which user will select some option or options
3. And when the dialog is closed you want these value(s) available to the main form.

The following is the solution for you:

Step 1. Declare property or properties or public member(s) in your dialog form to set the values. So your dialog form code will look like this:

namespace ppGlobal
{
    public partial class frmDomains : Form
    {
        public frmDomains()
        {
            InitializeComponent();
        }

       //This is the new property that needs to be added.
      // Note that there is only a get . this will make the property readonly. If you add a set, then you can pass values to the popup dialog from the main form.
       public string SelectedDomain
        {
            get { return tvDomains.SelectedNode.Name; }
        }

        private void frmDomains_Load(object sender, EventArgs e)
        {
            // get the current forest
           //do whatever you need to do for form loading
        }

        private void tvDomains_AfterSelect(object sender, TreeViewEventArgs e)
        {
            string domainName = e.Node.Name;        
        }

      }
}

Please note that i have removed the events for OK button and Cancel buttons.

Step 2: I removed the OK and cancel button events since all that you want is to close the form after the ok or cancel button is pressed. You can accompolish this by doing the following:
a) Select the OK button in the form designer. Open the property window. Look for the property called "DialogResult". Set the value for this to "OK"
b) Select the Cancel button in the form designer. Set the DialogResult property to "Cancel"
c) Select the Form. Look for properties called "AcceptButton" and "CancelButton" . Set them appropriately..

Now your Dialog is ready.

Step 3: In the main form you should have code similar to the following to popup the dialog:

            frmDomains f2 = new frmDomains();
            DialogResult dresult=f2.ShowDialog();
            if (dresult == DialogResult.OK)
                MessageBox.Show(f2.SelectedDomain);
 

If you have to return several different options from the dialog then use different properties. This is a fairly standard way to build Dialogs and access selections from them.

Hope this makes it easier for you..

Cheers
Mohan
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 17143755
Mine last solution basicly is same but less confusing :)
0
 
LVL 6

Expert Comment

by:mogun
ID: 17143908
I guess we were typing our solutions at the same time and i posted it later than you..

The solution i show here is the standard way to design Dialogs and obtain value from them..The solution is quite simple. It looks large because I just posted it elaborately so that there is no need for further clarifications.
0
 
LVL 13

Expert Comment

by:devsolns
ID: 17145434
The code I posted def. works.  Run it and dont worry about break points.  Some of the solutions I'm seeing here work ok for this simple example but they scale horribly.  Stick with my approach and eventually grow into a MVC pattern.
0
 
LVL 6

Expert Comment

by:mogun
ID: 17145617
Do they scale horribly ?  :) I guess the poor guy just wants to get his small Dialogwindow working.. Why make him frustrated with big names like patterns, delegates and what ever.. :) I can't even see the relevance of a MVC pattern here.. Anyway Good luck and God speed.

Cheers
Mohan
0
 

Author Comment

by:lapucca
ID: 17147611
Hi Devsonlns,

I removed the break points and ran it and still nothing happens.  Sorry, but I can't get it to work.  I mean, there isn't any compilation error but it's not returning my string.  
0
 

Author Comment

by:lapucca
ID: 17147863
Hi Mohan,

Your example was clear and concise and it works.  Thank you very much.  I've learned a lot from your posting.  Thanks. to everyone else too.  Maybe your solution is just advanced for me to follow but I appreicate everyone's input.
0
 
LVL 13

Expert Comment

by:devsolns
ID: 17148496
mogun if your going to learn something why not learn it right the first time.  yes your solution scales horribly.  your speaking to a simple dialog box.  your model doesnt work for simple form to form sharing.  big names and delegates?  boss i am pointing him down the right path.  if your afraid of delegates and patterns then thats on you.

let me point you to some "relevance."  lapucca is obviosuly new to this and instead of pointing him to a solution in which you'll not find in a single software shop solutions lets give him the concepts and insight as to where he needs to grow as a developer.  throw MVC at him and hopefully he'll take the time to research it and will learn how gui apps are appropriatly built.  your advice um, allows him to get data from a dialog, yipee!

take care guys
0
 
LVL 6

Expert Comment

by:mogun
ID: 17148653
hi devsolns,

This is Mohan. I love a good argument when i see it. Would you care to exchange notes over email?

I am not afraid of delegates or patterns. I am a solutions guy. I would rather give solutions for a given problem then beat around the bush. I really don't see the relevance of  MVC pattern here.

In your solution tell me what part corresponds to the Model, which one corresponds to the View and which one correpsonds to the Controller ?

Yes. There are delegates. There is MVC pattern. There are Generics and Page Controller patterns too. And there are so many other things out there. The point is how best we use them for the appropriate situations.

"Scales horribly" . That's another key word that's misused every where. Whenever you don't like something just point and and say..oh it dosn't have "Scalability"..And you can walk away. Tell me which part of the solution doesn't scale?

Cheers
Mohan
0
 
LVL 6

Expert Comment

by:mogun
ID: 17148700
Lapucca,

And it necessary to have understanding of MVC and other patterns. They help you to design better solutions. But i have never seen an implementation of an MVC pattern in a manner that i saw here..

The best example of a MVC pattern is the ASP.NET page. Whenever you create an ASP.NET web forms page it follows a MVC pattern internally. In addition it uses PageController and FrontController patterns too in..

Cheers
Mohan
0
 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 17150412
I don't mind any of solutions showed here. However, what scalability is required for custom dialogs!?
Mine "stupid" example is most stupid solution (I was even surprised it worked :)) but it does what was asked: just "returns a value".
My first solution is not MVC, it's more basic implementation of publisher-subscriber (isn't it used in MVC?)
Concerning patterns - no doubts. However it's not possible to understand patterns without basic understanding of OOP. If one doesn't know how to pass references between objects delegates are just uncomprehensible. I'd suggest learning OOP basics --> patterns --> delegates, in this sequence (it comes from my teaching experience in past :))
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Article by: Najam
Having new technologies does not mean they will completely replace old components.  Recently I had to create WCF that will be called by VB6 component.  Here I will describe what steps one should follow while doing so, please feel free to post any qu…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now