Open last form if application starts

A

Andrus

I have WinForms MDI application.
MDI child forms are created by menustrip click enent handler

AppDesktop.FormMgr.Show(new ChildForm1("param1", "param2") );

Every MDI child form "childform1" may have separate class with different
name and different number of parameters.
When application in opened, last MDI child form must be opened
automatically.
I think I must store last opened form name to isolated storage and call

AppDesktop.FormMgr.Show(new LastOpenedForm(lastParam1, lastParam2) );
Reflection should probably used to make this call.

I think I can add some code to form base class constructor for this which
stores child form name in isolated storage.

Switch statement is too big for this and so it is ugly.

I think about the following approach:

1. Retrieve actual calling class name from base class constructor and store
it in isolated storage (application can be run form web browser also).

2. At startup retrieve form name and create mdi child from it using
reflection.


Any idea or sample code how to implement this ?
 
B

Bruce Wood

I have WinForms MDI application.
MDI child forms are created by menustrip click enent handler

AppDesktop.FormMgr.Show(new ChildForm1("param1", "param2") );

Every MDI child form "childform1" may have separate class with different
name and different number of parameters.
When application in opened, last MDI child form must be opened
automatically.
I think I must store last opened form name to isolated storage and call

AppDesktop.FormMgr.Show(new LastOpenedForm(lastParam1, lastParam2) );
Reflection should probably used to make this call.

I think I can add some code to form base class constructor for this which
stores child form name in isolated storage.

Switch statement is too big for this and so it is ugly.

I think about the following approach:

1. Retrieve actual calling class name from base class constructor and store
it in isolated storage (application can be run form web browser also).

2. At startup retrieve form name and create mdi child from it using
reflection.

Any idea or sample code how to implement this ?

Here's a different idea.

First, Forms shouldn't have parameters for their constructors. It
makes it very difficult / impossible to design them using Visual
Studio Designer. You're better off making the MDI child forms have
constructors that take no arguments, and then give them settable
properties / setup methods you can call to configure them.

If you do that, then what you have becomes not a construction problem,
but a serialization / deserialization problem. Have each MDI child
form implement ISerializable, and teach it to serialize / deserialize
itself.

In isolated storage, you store the class of the MDI child form and its
serialized state. When your application restarts, it instantiates the
last MDI child form from its class name (using Reflection), and then
hands it the stored serialized state. The child form then deserializes
the information and configures itself appropriately.
 
A

Andrus

First, Forms shouldn't have parameters for their constructors. It
makes it very difficult / impossible to design them using Visual
Studio Designer. You're better off making the MDI child forms have
constructors that take no arguments, and then give them settable
properties / setup methods you can call to configure them.

Thank you.
Currently I have parameterless constructor also for designer only.

I use parametherized constructurs since some forms require mandatory
parameters which are used in form constructor.
Using your recommendation I must change calls from

AppDesktop.FormMgr.Show(new ChildForm1("param1", "param2") );

to

myForm frm = new ChildForm1();
frm.param1 = "param1";
frm.param2 = "param2";
frm.Configure();
AppDesktop.FormMgr.Show(frm);

In this case, somebody may forget to set param1 and param2 properties or
call Configure() method.
This is also 5 lines of code insted of single line for every of my 100 form
call, so 400 lines more code.
Using parametherized constructors forces to pass mandatory parameters
always.

Are parametherized form constructors bad practice?
If so I can remove them.
If you do that, then what you have becomes not a construction problem,
but a serialization / deserialization problem. Have each MDI child
form implement ISerializable, and teach it to serialize / deserialize
itself.
In isolated storage, you store the class of the MDI child form and its
serialized state. When your application restarts, it instantiates the
last MDI child form from its class name (using Reflection), and then
hands it the stored serialized state. The child form then deserializes
the information and configures itself appropriately.

I'm new to C#. Do you have any sample or link about this ?

Currently I'm thinking about storing class name and poperties to isolated
storage and use reflection to invoke the code:

myForm frm = new ChildForm1();
frm.param1 = "param1";
frm.param2 = "param2";
AppDesktop.FormMgr.Show(frm);

but I have no idea how reflection allows to run this code.

Andrus.
 
A

Andrus

I have also one more idea.

Every form has corresponding item in MenuStrip.

How to force MenuStrip to remember last issued form opening command ?
How to re-execeute last command in application startup using SendKeys() or
something similar ?

This avoids using reflection.

Andrus.
 
B

Bruce Wood

Thank you.
Currently I have parameterless constructor also for designer only.

I use parametherized constructurs since some forms require mandatory
parameters which are used in form constructor.
Using your recommendation I must change calls from

AppDesktop.FormMgr.Show(new ChildForm1("param1", "param2") );

to

myForm frm = new ChildForm1();
frm.param1 = "param1";
frm.param2 = "param2";
frm.Configure();
AppDesktop.FormMgr.Show(frm);

No, not necessarily. You could set it up like this:

myForm frm = new ChildForm1();
frm.Configure("param1", "param2");
In this case, somebody may forget to set param1 and param2 properties or
call Configure() method.

Yes, someone could still forget to call the Configure method.
This is also 5 lines of code insted of single line for every of my 100 form
call, so 400 lines more code.

Well, two lines instead of one, which means 200 lines instead of 100
lines, but that's only a significant factor if you can get your
persistence problem solved using parameterized constructors. If you
can't, then those extra 100 lines of code don't look so bad any
more. :)
I'm new to C#. Do you have any sample or link about this ?

Currently I'm thinking about storing class name and poperties to isolated
storage and use reflection to invoke the code:

myForm frm = new ChildForm1();
frm.param1 = "param1";
frm.param2 = "param2";
AppDesktop.FormMgr.Show(frm);

but I have no idea how reflection allows to run this code.

I took a quick look at the documentation for ISerializable:

http://msdn2.microsoft.com/en-us/library/system.runtime.serialization.iserializable(vs.71).aspx

It looks rather complicated to me. It may be worth learning, but if
you want something simple and home-grown, then consider the following.

public interface ISerializeMDIChild
{
string SerializedState { get; set; }
}

Have each form implement this interface. Basically, each child form is
given the job of gathering all of its internal state that it thinks is
worth saving, and turning that into a string somehow. And, conversely,
taking a correctly formatted string and (the form) setting its
internal state based on what the string says.

The string can be anything at all. Its format is really private to the
child form, so it can be very machine-friendly. For example, say that
a child form needs to save the number of rows and columns of some grid
it is showing, and on which column the grid is sorted, and in what
sort order. The form could decide to emit a serialized string like
"10,5,3,ascending": 10 rows, 5 columns, sorted on column 3 ascending.
Then the SerializedState property might look like this:

public string SerializedState
{
get { return String.Format("{0},{1},{2},{3}",
this.grid.Rows.Count, this.grid.Columns.Count, this.gridSortColumn,
this.gridSortAscending ? "ascending" : "descending"); }
set
{
string[] parms = String.Split(",", value);
... write code to parse bits of string and set up form ...
}
}

Now your persistence / serialization problem becomes easier. You just
need to instantiate the form using Reflection (simply call no-argument
constructor), then set the SerializedState property from the string
you saved. You save only two things: the class name, and the
serialized string that came from the form when it was last active.

You can even use your constructors with arguments, so long as you
leave a no-argument constructor for Reflection to call. If you do it
that way, then there are two ways to create your child form:

1. Call the constructor with arguments.
2. Call the constructor with no arguments and set the SerializedState
property.
 

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