Reopen a closed Form that was shown using ShowDialog() - c#

I am making one application in which there is one main Form FormMain and one helper Form FormHelper.
For understanding, take an example that in FormMain the user is typing in the orders and frequently the user wants to open the FormHelper and fill some values in it.
When the order is saved, the values in FormMain is saved as well as FormHelper.
What I did was make the FormHelper a field in the definition of FormMain :
public partial class FormMain : Form
{
FormHelper BillsForm;
}
And, in the constructor :
public FormReceiptNew(string ReceiptNo)
{
InitializeComponent();
BillsForm = new BillsForm();//just once
}
Now suppose that the user, while filling the FormMain, wants to enter some values in FormHelper, he/she can press ALT+H and the Form will be shown using ShowDialog() and when it's done, the user will close the FormHelper, and the same process will happen for as many times the FormHelper is required.
The reason why I want the same Form to open multiple times, is that the user is filling certain values in it and I want to persist the values the next time the FormHelper is shown again and when the user is done completely with the FormMain, the values in the FormMain will be saved along with the values in FormHelper.So when the user presses ALT+H each time, the following code will not work:
BillsForm= new FormHelper();
BillsForm.ShowDialog();
as it is creating a new form and all the old values will be deleted.

In your main form, store a reference to the helper form.
You instantiate the helper form once (onLoad for example) and keep calling showDialog() on that same object. All the fields should be retained between calls.

If you were to store those values in the main form after closing, you could send those values back to the FormHelper upon creation either through the constructor or setters. From your question it already sounds like you're going to be storing those values that you want to persist inside the main form, so setting them upon creation shouldn't be an issue.

Related

Task update on Windows Forms

I am trying to design an application which creates a new employee data for an organization. My requirement is when a new employee record is being created by any existing user there is a main form of the application on which I need to show that an existing user has created a new user. For example, if the existing user is A and new user is B then the message on the main form should be as mentioned below:
A has created a new User B.
I am stuck in the place where I am not able to understand how to display this message on my main form.
For this do I need to keep listening to the database and in case any new row is created, then display the message accordingly or there is some other way as well as I do not want the application to keep hitting the database unnecessarily.
I am new to C# and so stuck here and need help.
Regards
Vineet More
If you want only pass data from one form to another, you can either:
1) Use dependency injection to pass MainForm to CreateForm and then populate MainForm from that CreateForm (not that good idea).
2) Show CreateForm as Dialog form and return DialogResult when closing CreateForm.

Windows Form Launching Another Form

I am quite new to Visual Studio (Express) and C#. I have made a windows form that accepts some user input then displays that input in a Message Box (that automatically comes with an "OK" button that closes the Message Box when clicked).
Instead I would like the user input collected by the first form to be displayed in a new form that displays a message (label), shows the input, and offers a choice of two buttons: one to accept and one to go back and change the input.
I have NO idea how to do this and any advice is appreciated.
Sounds like you need a confirm Message or something similar.
The MessageBox class offers this functionality.
DialogResult btn = MessageBox.Show("your message",
"your title",
MessageBoxButtons.OKCancel,
MessageBoxIcons.Question);
if(btn == DialogResult.Cancel)
// User canceled, return to the string editor
else
// User confirmed, do you work
If you prefer there is also an enum for MessageBoxButtons.YesNo with corresponding DialogResult.Yes and DialogResult.No
See here for a reference on MessageBoxButtons
See here for a reference on MessageBoxIcons
What you need is to somehow pass the information from the first form to the second. This can be done by setting properties on the child form, either through individual properties (strings, ints, etc.) or by a complete data structure (object). The input form collects the information, creates the sub child form, sets properties on it, then displays the form. Many other ways to do this, but start with the simple and then build up to the complex.
If you need to pass some data to your second form, create property/properties on that form, or provide data via constructor parameters. Also assign DialogResult property for two buttons on second form. Set DialogResult.OK to button which will accept input. Verify value returned by second form, when you show it as dialog and do appropriate actions:
using(SecondForm secondForm = new SecondForm()
{
secondForm.Data = yourData;
if (secondForm.ShowDialog() != DialogResult.OK)
{
// go back and change input
return
}
// accept input
}
So your Form2 needs to have some value, provided by whatever creates it, for it to exist. There should never be an instance of Form2 without that information. That tells you that it should be in that form's constructor (as opposed to a property on that form).
This means that in Form1 you will have something like this:
string someData; //populate based off of user input
Form2 childForm = new Form2(someData);
//then hide current form and show child form
In Form2 you probably already have a constructor, you just need to modify it to something like:
public Form2(string someData) //TODO give better parameter name
{
someLabel.Text = someData;
}
Next we need to deal with the child form going back to the parent form. I feel the preferable way to deal with this is using events. The form has a FormClosing event that you can attach to; this will allow your parent form to run some code when the child form is closed.
string someData; //populate based off of user input
Form2 childForm = new Form2(someData);
childForm.FormClosing += (sendingForm, args) =>
{
this.Show();
bool result = childForm.DidUserAccept;
}
Here I used a property on the child form DidUserAccept, for whether the user accepted or declined the value. We'll need to define that in Form2:
public bool DidUserAccept {get; private set;}
In the button click handlers for accept/cancel you can set the result accordingly and then close the form (closing will trigger the closed event and runt he relevant code in Form1.

How to pass a value selected on an initial form to the main form?

I want to do something like the answer here:
How can I close a login form and show the main form without my application closing?
...but I want to pass a value selected on the initial form to the next (main) form. If I call an overridden constructor on the main form, where do I store the value in the meantime (between the initial form being dismissed and the main form being called)?
OTOH, if, instead of using the program.cs file to do this, I create the "initial form" inside the main form's Load() event (is there a better place), I could do something like this, but admittedly it seems rather kludgy:
0) Set the main form's size to 0,0 to hide it
1) Show the "initial" form/modal dialog, and store the value the user selects (in a button click event) in a form-global variable
2) Once the initial form/modal dialog closes, set the main form's size back to what it should be (unless modal result <> OK, in which case I close the main form and the app)
I know there's a better way to do this...
You don't have to pass a value to the main form. Just like your link explains, open your main form first. Then your main form can open the other form. This other form can place the information in a public property that the main form can access. Since the main form controls the lifetime of this other form, the main form gets the information held in the other form's public property, then closes the other form.
string myVariable;
using (OtherForm otherForm = new OtherForm())
{
otherForm.ShowDialog();
myVariable = otherForm.OtherVariable;
}
Try using ApplicationContext (System.Windows.Forms.ApplicationContext). You can show multiple forms as shown in the example in the following MSDN thread. And regarding data,you can have a common data object which is created once and the forms are instantiated with the data object passed to them before showing them.
http://msdn.microsoft.com/en-us/library/system.windows.forms.applicationcontext%28v=vs.100%29.aspx

Why calling Hide in a child form's FormClosing event handler hides the parent form?

When Form2 is closed, via it's X button, the Main form is sometimes hidden as well, but not always. Often times the Main form is hidden after initial 'newForm' button click and other times many open-close operations are required before the Main form gets hidden on Form2's closing. Why is this happening? Why is it irregular?
This is a small test code for a larger application I'm working on. In that application a thread continuously reads the network stream and when a particular message is encountered a modal form is displayed. The user can close that modal form or it can be told to close itself by a different network message. In this event, to give the user some time to view the data that the form is displaying I implemented a delayed form closing for that form. When the form is running its delay closing code, another message can come in over the network that will open up a new instance of this form in which case, I observed, that once the timer of the original form runs out, the original form is left displayed until the new instance is closed. Calling Hide in the FormClosing event handler closes the original form if more than one instances of it are running, but it has this side effect of hiding the entire application (the Main form) when the last instance of this form is closed, either by the user or by the delayed closing code. And again, the entire application is not always hidden, but it does happen.
//Main form's 'newForm' button
private void btn_newForm_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.ShowDialog();
}
public partial class Form2 : Form
{
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
Hide();
}
}
Update (from the application I'm working on):
The problem is shown visually below. The top part of the picture, labeled "A", represents the situation where the first modal dialog (greyed out) was instantiated and it is in the process of being auto closed after 4 seconds have elapsed. The second instance (blue window heading) is active and awaiting input. In the lower part of the picture, labeled "B", the counter to closing of the first instance has completed, yet the first instance remains visible. Adding Hide does not change picture "A" but picture "B" would only be showing the active modal dialog, which is what I want. If Hide is not used and we have the case shown in "B", once the active modal dialog is closed the inactive dialog will disappear together with the active one, but no sooner. At this time my main form will be hidden as well, sometimes.
Your main form doesn't get hidden, it disappears behind another window. The flaw in your code is that for a brief moment none of your windows can get the focus. Your main window can't get the focus, it got disabled by your dialog and won't get re-enabled until the dialog is fully closed. Your dialog can't get the focus, you hide it. So Windows goes looking for another window to give the focus to and can only pick a window owned by another application. Like Visual Studio, nice and big so your main window is well covered by it.
Not sure what you are trying to do, it doesn't make sense to call Hide() since the dialog will close a couple of microseconds later. Just delete the statement.
I am not sure if I am right but maybe you forgot to add e.Cancel = true; to your closing event.
Second, I think using a modal form is only usefull when you expect an action like OK or CANCEL from user, that is where DialogResults comes handy. It sounds strange if this happens time to time not all the time! maybe you can try like this:
//Main form's 'newForm' button
//Define form in your mainform
private Form2 f;
private void btn_newForm_Click(object sender, EventArgs e)
{
if(f != null) { f.Show(); return; }
f = new Form2()
f.FormClosing += delegate { f.Hide(); };
f.Show();
}
I know the topic is quite old, but I recently had to look for answers for this precise question.
Why hiding the (child modal) form instead of closing it ?
I may be wrong, but I think that in some cases, hidding the modal child form instead of closing it is sometimes useful.
For example, I'm using a class that is a custom tree of grids. Think of something like an Excel Document with multiples tables (sheets) and each table can have child tables. A very powerful manner to store datas that can be used by multiple objects and multiple forms at a time.
Now, this "TreeTable_Class" object has an inbuilt custom form that actually shows the content of one of its tables at a time in a GridView, and you can select which table to show by selecting it in a Treeview. You can see here that the "Database Editor" is actually and MDI Form that can load the Form from any TreeTable_Class.
And this is the Form I use to edit the content of a Cell for a given (selected) Table (I've chosen another cell with long text content from another table in this database)
Now, when you choose to close the custom form instead of hiding it, that form will be unaccessible, you can't show it anymore, and you get an exception (no instance of the object) Somewhat, it isn't disposed yet (so the check If MyForm Is Nothing Then... is useless) I know I have to implement the GarbageCollector and dispose the Child Form manually, but it's outside the scope of this topic.
Anyway, my class could use a large amount of memory, of datas, and if I had to rebuilt ALL the contents each time I want to show a new instance of that form, that would be a large amount of workload in my application. That's why I have chosen to hide the form instead of closing it until the main application exits or when a specific CloseFormAndDispose() method is explicitly called, either by the program, or if I make this option available for the user via an user interface.
Workaround try :
This is the workaround I've found to override the "form replaced by another because none of the parent/child ones could be retrieved" :
Sorry, I'm in VB.. but you can use a tool to convert this to C#, or do it manually, it's pretty simple..
// This is the child, a Cell Editor that can edit the content of a Cell.
Protected WithEvents _CellEditor As CellEditor_Form = Nothing
This Editor form is a member of TreeTable_Form, a form that can actually show and edit the content of the whole Database File (a single file)
And this TreeTable_Form class contains a routine that handles CellEditor closing event
Public Partial Class TreeTable_Form
// Sorry. The "WithEvents" in C# is a litte bit complex to me... So, in VB :
Protected WithEvents _CellEditor As CellEditor_Form = Nothing
// ...
// CellEditor handling method (I used a Code converter...) :
// The original VB declaration is :
// Protected Sub RecallFormAfterCellEditorHidden() Handles _CellEditor.Closed
// You'll have to write specific Event handler for _CellEditor object declared above...
protected void RecallFocusAfterCellEditorHidden()
{
Application.DoEvents();
this.Focus();
}
End Class
This tiny protected void RecallFormAfterCellEditorHidden() method in your Class (if you are using a class that contains Forms) or in your Main From, assuming that your main form contains the child forms (dialogs) will try to force the focus on your Application or MainForm...
By the way, TreeTable_Form is actually a component of TreeTable_Class. The later is an object that can be used anywhere you want. In a Main Form Application, in another Class, in a dialog, anywhere... and could be passed by reference to share its contents between several items. And this TreeTable_Class contains a RecallFocusAfterTreeViewerHidden() method that handles the closing of that form. That means, the Form or Application that actually uses the class will get the focus each time you close the its child Form. I've made it that way to get an object that could be used anywhere
We still get problems !
However, this method will make your application flicker a bit each time you close your child dialog, and doesn't succeed at 100% ! Sometimes, my parent form still disappear from screen and gets struck behind another window. Alt+TAB wont helt either. But this happens less than without this method trick. I don't have any better answer at this time, still searching... I'll come back here if I find out how. I'm using this custom made application in my work to write memos during meetings for example, and produce PV (procès verbal - french sorry) in PDF or DOCx on the fly...
And I'm sorry, I'm in VB, not C#. Hope this helps a little, until we find a better workaround for this...

Design apllication with muliple forms within one main form

I want to make an application that have one main form that have one functionality = Add new form.
I dont know how forms will be created, they are created dynamically by the user (AddForm methos from the main form).
All the subs forms are the same but some of thier prop receive differnce parameters (it can be in the ctor or later).
I want to be able to close all the forms when I close the main form.
Before new form will displayed I want to display setting form (to take the form parameters) maybe with ShowDialog method and do validating check on the form and just if the form validate the new form will displayed, if not (or if the user prees cancel) the form will disposed.
I know aboout MDI but I really perfer other way
Any ideas?
Thanks!
Closing all forms when main form is closed is somewhat easy, you just pass the main form reference in Show() method of the "child" forms; e.g. if you show child from main, you do:
child.Show(this);
This needs to be done if the your main form is not the real "main form of the program", but you want to close all "child" forms.
However, wiring all this together would preferably be done in some special class for this purpose, maybe called ScreenRepository. In this class, you would have a collection of open forms at any moment, you would deffer form creation to this class (so that this class automatically injects form parent) etc... Having this class would be easy to re-activate (give focus) the form if it is behind other forms, create new form if needed etc...
Idea is simple create a application that open a main form a the beginning and then open open other forms if needed if you close main form rest of forms are also closed. Like in GIMP.

Categories

Resources