Return Values From Form?

J

joey.powell

Hello,

I have a windows forms application (VS2005) where I need to do the
following...

1. Startup with a main form.
2. Have the user to select a file and then bring up a second form
modally (Form1.ShowDialog()) so that the user can make custom
selections.
3. I can store the selections from the second form in many different
ways, but I have to get them back to the main form once the modal form
is closed. The selections are column header names, and right now I am
choosing to store them in a Generic List<string>.

I am doing fine so far, but now I need to figure out the best way to
get the selections back to the main form, once the user clicks
"Continue" and I call this.Close() on the second form.

I thought about creating the list and then passing a reference to the
modal form's constructor: "ref List<string> MyList". But this doesn't
work because the list is not scoped outside of the modal form's
constructor. And so I cannot interact with it when other events occur
on the form, like for example, a button click.

Another way would be create and modify the list within the second form
and then simply "return" it, but as far as I know one cannot do that
when using forms (would not be a problem with plain old functions).
There is not a return(MyList) that will work when closing a form,
right?

What would be a good way to tackle this?
 
N

Nicholas Paldino [.NET/C# MVP]

Joey,

Why not just expose a property on your form that will expose the
selections in a format that is easy for you to work with? The form
reference is still valid, and you can still access the properties exposed on
your form.

Hope this helps.
 
J

joey.powell

Could you explain a little more?
Joey,

Why not just expose a property on your form that will expose the
selections in a format that is easy for you to work with? The form
reference is still valid, and you can still access the properties exposed on
your form.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hello,

I have a windows forms application (VS2005) where I need to do the
following...

1. Startup with a main form.
2. Have the user to select a file and then bring up a second form
modally (Form1.ShowDialog()) so that the user can make custom
selections.
3. I can store the selections from the second form in many different
ways, but I have to get them back to the main form once the modal form
is closed. The selections are column header names, and right now I am
choosing to store them in a Generic List<string>.

I am doing fine so far, but now I need to figure out the best way to
get the selections back to the main form, once the user clicks
"Continue" and I call this.Close() on the second form.

I thought about creating the list and then passing a reference to the
modal form's constructor: "ref List<string> MyList". But this doesn't
work because the list is not scoped outside of the modal form's
constructor. And so I cannot interact with it when other events occur
on the form, like for example, a button click.

Another way would be create and modify the list within the second form
and then simply "return" it, but as far as I know one cannot do that
when using forms (would not be a problem with plain old functions).
There is not a return(MyList) that will work when closing a form,
right?

What would be a good way to tackle this?
 
N

Nicholas Paldino [.NET/C# MVP]

Joey,

A form is an object, like anything else. Just define your type to
expose a property/method that you can call after ShowDialog returns which
will give you the values from the dialog.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Could you explain a little more?
Joey,

Why not just expose a property on your form that will expose the
selections in a format that is easy for you to work with? The form
reference is still valid, and you can still access the properties exposed
on
your form.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hello,

I have a windows forms application (VS2005) where I need to do the
following...

1. Startup with a main form.
2. Have the user to select a file and then bring up a second form
modally (Form1.ShowDialog()) so that the user can make custom
selections.
3. I can store the selections from the second form in many different
ways, but I have to get them back to the main form once the modal form
is closed. The selections are column header names, and right now I am
choosing to store them in a Generic List<string>.

I am doing fine so far, but now I need to figure out the best way to
get the selections back to the main form, once the user clicks
"Continue" and I call this.Close() on the second form.

I thought about creating the list and then passing a reference to the
modal form's constructor: "ref List<string> MyList". But this doesn't
work because the list is not scoped outside of the modal form's
constructor. And so I cannot interact with it when other events occur
on the form, like for example, a button click.

Another way would be create and modify the list within the second form
and then simply "return" it, but as far as I know one cannot do that
when using forms (would not be a problem with plain old functions).
There is not a return(MyList) that will work when closing a form,
right?

What would be a good way to tackle this?
 
B

Bruce Wood

public ModalForm : Form
{
...
public List<string> UserChoices
{
get
{
... build list of strings and return it ...
}
}
}

public Form : MainForm
{
...
private void Button_Click(object sender, System.EventArgs e)
{
ModalForm modal = new ModalForm();
if (modal.ShowDialog() == DialogResult.OK)
{
List<string> userChoices = modal.UserChoices;
...
}
modal.Dispose();
}
}
 
J

joey.powell

Okay, I got it. I was thinking that once you called this.Close(), the
form went out of scope. Now I see. Thanks a lot.
Joey,

A form is an object, like anything else. Just define your type to
expose a property/method that you can call after ShowDialog returns which
will give you the values from the dialog.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Could you explain a little more?
Joey,

Why not just expose a property on your form that will expose the
selections in a format that is easy for you to work with? The form
reference is still valid, and you can still access the properties exposed
on
your form.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hello,

I have a windows forms application (VS2005) where I need to do the
following...

1. Startup with a main form.
2. Have the user to select a file and then bring up a second form
modally (Form1.ShowDialog()) so that the user can make custom
selections.
3. I can store the selections from the second form in many different
ways, but I have to get them back to the main form once the modal form
is closed. The selections are column header names, and right now I am
choosing to store them in a Generic List<string>.

I am doing fine so far, but now I need to figure out the best way to
get the selections back to the main form, once the user clicks
"Continue" and I call this.Close() on the second form.

I thought about creating the list and then passing a reference to the
modal form's constructor: "ref List<string> MyList". But this doesn't
work because the list is not scoped outside of the modal form's
constructor. And so I cannot interact with it when other events occur
on the form, like for example, a button click.

Another way would be create and modify the list within the second form
and then simply "return" it, but as far as I know one cannot do that
when using forms (would not be a problem with plain old functions).
There is not a return(MyList) that will work when closing a form,
right?

What would be a good way to tackle this?
 
C

Chris Dunaway

Okay, I got it. I was thinking that once you called this.Close(), the
form went out of scope. Now I see. Thanks a lot.

Be careful though. If the form is opened using just .Show, then when
..Close is called, it is disposed automatically. When opened using
..ShowDialog, then you must dispose it yourself after it is closed. In
that case you can access its properties before you dispose it.
 
J

joey.powell

Good to know. So, I guess the GC will dispose of it when it goes out of
scope, so I don't have to call Dispose(), right?
 
B

Bruce Wood

If you show it using .Show(), that is correct.

If you show it using .ShowDialog() then you should dispose of it
yourself.
 
S

sloan

Joey,

I'd suggest a different route.

I'd have a backend object, used to hold items. And implement the Singleton
design pattern.

If you go to my blog:
http://sholliday.spaces.msn.com/
10/24/2005

I have a "Web Session Object Holder".

You can read about the concept there.


Here is a "winforms" version of that same code:

You can find the code to use it at the blog.

But basically, .. like in your Form2 ... cmdClose button, you can do
something like this:

MemoryDataStore mds = MemoryDataStore.GetInstance();
object testO = new object();
mds.Add ("mykeyname", testO );


Ok.. then after you get back from the form2 you do this

MemoryDataStore mds = MemoryDataStore.GetInstance();
object oFromStore = mds.Remove("mykeyname") as object;
if(null!=oFromStore)
{
//do something with o//
}

of course, change "object" to whatever object you're interested in.



Put your "mykeyname" in a constant somewhere..... to be consistent.

The object was written with 1.1 in mind. I haven't thought about rewriting
it with 2.0 Generics in mind.



public class MemoryDataStore //: IDataStore
{
private static MemoryDataStore singletonInstance = null;
private HybridDictionary m_memoryStore = null;
//private Hashtable m_memoryStore = null;

private MemoryDataStore( )
{
m_memoryStore = new HybridDictionary(); // Implements IDictionary by
using a ListDictionary while the collection is small, and then switching to
a Hashtable when the collection gets large.
//m_memoryStore = new Hashtable(); // Implements IDictionary by using a
ListDictionary while the collection is small, and then switching to a
Hashtable when the collection gets large.
}


public static MemoryDataStore GetInstance( )
{
if( null == singletonInstance )
{
singletonInstance = new MemoryDataStore( );
}
return singletonInstance;
}


public void Clear( )
{
m_memoryStore.Clear( );
}

public void Add( string key, object value )
{

if( m_memoryStore.Contains( key ) )
{
m_memoryStore.Remove( key );
}

m_memoryStore.Add( key, value );
}



public object Remove( string key )
{

// see
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Hashtable.html#remove(java.lang.Object)
// for java method, which returns the object you removed, in case
// you want to do something with it

object returnObject = null;
if (null != this.m_memoryStore)
{
if( m_memoryStore.Contains( key ) )
{
returnObject = this.m_memoryStore[key];
m_memoryStore.Remove( key );
}

}
return returnObject;

}

public object this[ string key ]
{
get
{
if( null != m_memoryStore[ key ] )
{
return m_memoryStore[ key ];
}
return null;
}
}

public int Size
{
get
{
if( null != m_memoryStore )
{
return m_memoryStore.Count ;
}
return 0;
}
}

}
 
B

Bruce Wood

sloan said:
Joey,

I'd suggest a different route.

I'd have a backend object, used to hold items. And implement the Singleton
design pattern.

If you go to my blog:
http://sholliday.spaces.msn.com/
10/24/2005

I have a "Web Session Object Holder".

You can read about the concept there.


Here is a "winforms" version of that same code:

You can find the code to use it at the blog.

But basically, .. like in your Form2 ... cmdClose button, you can do
something like this:

MemoryDataStore mds = MemoryDataStore.GetInstance();
object testO = new object();
mds.Add ("mykeyname", testO );


Ok.. then after you get back from the form2 you do this

MemoryDataStore mds = MemoryDataStore.GetInstance();
object oFromStore = mds.Remove("mykeyname") as object;
if(null!=oFromStore)
{
//do something with o//
}

of course, change "object" to whatever object you're interested in.



Put your "mykeyname" in a constant somewhere..... to be consistent.

The object was written with 1.1 in mind. I haven't thought about rewriting
it with 2.0 Generics in mind.



public class MemoryDataStore //: IDataStore
{
private static MemoryDataStore singletonInstance = null;
private HybridDictionary m_memoryStore = null;
//private Hashtable m_memoryStore = null;

private MemoryDataStore( )
{
m_memoryStore = new HybridDictionary(); // Implements IDictionary by
using a ListDictionary while the collection is small, and then switching to
a Hashtable when the collection gets large.
//m_memoryStore = new Hashtable(); // Implements IDictionary by using a
ListDictionary while the collection is small, and then switching to a
Hashtable when the collection gets large.
}


public static MemoryDataStore GetInstance( )
{
if( null == singletonInstance )
{
singletonInstance = new MemoryDataStore( );
}
return singletonInstance;
}


public void Clear( )
{
m_memoryStore.Clear( );
}

public void Add( string key, object value )
{

if( m_memoryStore.Contains( key ) )
{
m_memoryStore.Remove( key );
}

m_memoryStore.Add( key, value );
}



public object Remove( string key )
{

// see
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Hashtable.html#remove(java.lang.Object)
// for java method, which returns the object you removed, in case
// you want to do something with it

object returnObject = null;
if (null != this.m_memoryStore)
{
if( m_memoryStore.Contains( key ) )
{
returnObject = this.m_memoryStore[key];
m_memoryStore.Remove( key );
}

}
return returnObject;

}

public object this[ string key ]
{
get
{
if( null != m_memoryStore[ key ] )
{
return m_memoryStore[ key ];
}
return null;
}
}

public int Size
{
get
{
if( null != m_memoryStore )
{
return m_memoryStore.Count ;
}
return 0;
}
}

}

Not that I want to be combative, but what is the difference between
what you proposed and this:

public class BigBadGlobalStorage
{
public static Form2ResultObjectType Form2Result = null;
public static Form2OtherResultObjectType Form2OtherResult = null;
}

etc. ?

Then in Form2, just say:

BigBadGlobalStorage.Form2Result = myResult;
BigBadGlobalStorage.Form2OtherResult = myOtherResult;

Isn't this basically the same idiom? One which is generally regarded as
a bad idea? The only difference is that in your proposed "common hash
table" solution there is no need to alter / recompile the library
containing the MemoryDataStore whenever you want to add a new "global
variable." Nonetheless, it still looks like global variables to me...
albeit in a different guise.
 
B

Bruce Wood

Bruce said:
Isn't this basically the same idiom? One which is generally regarded as
a bad idea? The only difference is that in your proposed "common hash
table" solution there is no need to alter / recompile the library
containing the MemoryDataStore whenever you want to add a new "global
variable." Nonetheless, it still looks like global variables to me...
albeit in a different guise.

I should temper these comments by saying that they apply to the
WinForms world, not necessarily to the WebForms world. I realize that
WebForms is a different beast and that persisting information from one
Web form to another is trickier than it is in WinForms.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top