Let's review your criteria: "I only want 1 form open in my main form at anytime."
It appears to me you are hitting a nail with a sledge hammer. If your criteria to only have 1 child form (MDI) open at a single time within the parent form, then the solution seems pretty simple to me. Just store a reference to the child form in the parent form.
Code:
Class <ParentForm>
Private _childForm As System.Windows.Forms.Form
...
End Class
When an action happens on the parent form (button clicked, menu item clicked, etc.) you check the variable holding the child form reference. So the code inside some action handler would be:
Code:
If Not _childForm Is Nothing Then
'child form is open, do something here
End If
If the rules are to have only 1 child open at a time you then need to decide how to handle this action. I imagine you would want to check the type of the requested and open form to determine if we need to open a new one at all. E.g. In your example, if the user wants to open frm_Dokter and that's already open there's no need to continue with the close/open process. You can perform this check like this:
Code:
If TypeOf _childForm Is frm_Dokter Then
'form requested is already open, handle accordingly
Else
'form requested is NOT already open, handle accordingly
End If
When you have a form already open and the user is requesting a different one you need to take further action aside from opening the new form. Possible options I can think of are:
A) Close the open form and open the new one requested.
B) Inform the user that they must close the open form before they can open another. This would be a good place to implement a child form super class from which all child forms are derived or an interface implemented by all child forms that provides the child form's check behavior. Use this to determine if a child form can be closed (operations completed, data saved, etc.). This is a bit more of an advanced topic but something worth thinking about.
C) Simply tell the user they can't open another form until they've closed the open one. From a usability standpoint I'd avoid this one. Better to use approach B. If the use CAN switch forms with no repercussions, then it should happen. Otherwise, tell the user what they need to complete or just give them the option. Again, if you implement some common interfaces (using a literal interface or a super class for child forms) then you can centralize the check operation.
So when you get to the point in your code where you are going to open the new form, you do something like this:
Code:
Dim blnOpenForm As Boolean = False
If _childForm.CanClose() Then
blnOpenForm = True
Else
If _childForm.CanSave() Then
Dim msgResult As DialogResult
msgResult = MessageBox.Show(_childForm.GetCanSaveMessage())
If msgResult = DialogResult.OK
_childForm.Save()
blnOpenForm = True
End If
Else
MessageBox.Show(_childForm.GetCannotSaveMessage())
End If
End If
If blnOpenForm Then
'open the requested form
End If
The above example is a little crude, but the general idea is there. What's happening here is that there are several methods that all child forms would implement (through either super class "MustOverride" methods or implemented interface methods). The methods are:
- CanClose() - Tests the state of the child form to determine if it can be closed as-is (does data need to be saved, etc.)
- CanSave() - Tests whether the data in the form can be saved in the current state. (E.g. The user may need to finish entering critical data first.)
- GetCanSaveMessage() - Returns a message telling the user that the form can be saved in it's current state. (E.g. "Data for patient x will be saved.")
- GetCannotSaveMessage() - Returns a message telling the user that the form can NOT be saved in it's current state. ("You must finish filling in x and y for patient z.")
- Save() - Performs the child forms save actions.
Another possible and potentially useful addition to the list would be an Undo() method. Then you provide the user the ability to close the task they started on the current open form without saving it (by undoing it). (In some or many cases, the Undo() method simply doesn't do anything because a save to a database is just ignored which essentially is an Undo operation).
The end result of all of this is that when the user goes to open a new form, they either get the new form immediate, they get a message like this (message from GetCannotSaveMessage method):
Code:
+-----------------------------------------------------------------------+
| The current view cannot be closed without completing the following: |
| You must finish filling in x and y for patient z. |
| |
| +-------------+ |
| | OK | |
| +-------------+ |
+-----------------------------------------------------------------------+
or they get a prompt such as:
Code:
+--------------------------------------------------------------------------+
| The current view cannot be closed without taking the following action: |
| Data for patient x will be saved. |
| Would you like to save changes and continue? |
| |
| +-------------+ +-------------+ +-------------+ |
| | OK | | Ignore | | Cancel | |
| +-------------+ +-------------+ +-------------+ |
+--------------------------------------------------------------------------+
Line 2 in the first message comes from the child form's GetCannotSaveMessage method. The rest comes from the parent form generic code.
Lines 1 and 3 of the prompt come from the generic code in the parent form. The 2nd line is what comes from the GetCanSaveMessage() that is implemented by each child form. Actions for the dialog buttons are:
OK - the child form's Save() method is called and switching forms continues
Ignore - child form's Undo() method is called and switching forms continues
Cancel - No child form action happens and switching forms stops.
I'm sure I've provided you with far more than you expected, but I'm feeling strangely inspired by the new year and a haze of insomnia.
Hope you can understand and make some use of my suggestions.
-Peter