Link to home
Start Free TrialLog in
Avatar of AndyAelbrecht
AndyAelbrecht

asked on

How to know what MDI Child Form just closed ?

VS2005

Situation:
MDI Parent with several child forms. All forms can only be instantiated once (already have the code for this).
There is a childform which opens another childform.
without MDI, i could call this other form with ShowDialog, and use the DialogResult as a trigger in the calling form to know when the form is closed, so I can trigger a reaction.


Now, since I moved the app. to an MDI app, I can not use the ShowDialog anymore since I want all the forms INSIDE the MDI application. I don't want to work around that.

The events of the MDIParentForm include an MdiChildActivate event, but it does not include an MdiChildClose event.

So, the question boils down to the title: how can I know know what MDI Child Form just closed ? Is there an event for it, somewhere ? Can I attach an event to something ?

Or do I have to revert to writing a function in my MDIParent which I call from all the FormClosed() events of the child form ?
As a last thing, I really don't want to use a timer for this, unless it is the best solution proposed by the Experts.

thx in advance,

cheers,
Andy
Avatar of Manish Chhetia
Manish Chhetia
Flag of India image


Add handler of the Child Form Closed Event (on the MDI Form)

Open the child form as
Dim mobjFrm as ChildForm withevents

In Mdi Form (or other child Form use)
mobjFrm.Show

write the sub on the MDI Form

    Private Sub MDIChild_Closed(ByVal sender As Object, ByVal e As System.EventArgs) _
                Handles mobjFrm.Closed
        '------------------------------------------------------------------------
        'Subroutine Name    :   MDIChild_Deactivate
        'Purpose            :   This Event Receives closed Event of all MDI children   forms
        'Created By         :   Hemant Patidar
        '------------------------------------------------------------------------

        'Removing the Form Memory Space
        SetNothing(CType(sender, Form))

    End Sub

Avatar of AndyAelbrecht
AndyAelbrecht

ASKER

yes, I see this working.

but there are several forms being opened by several other forms (all MDI children).
so I have to expand this code to work for all of them, right ?

another thing: Dim myform as New frmOfferteNieuw withevents doesn't work for me; I was already using this approach without the withevents behind it.
but if I add it, it breaks :( (says end of statement expected) (even when i remove the New keyword)
Dim WithEvents myform as New frmOfferteNieuw does work, however.

Ok, now that this is out of the way:


Your MDIChild_Closed function looks cool, but it depends on 1 specific form; I need to be able to capture the close event of any MDI Child form that I open.
damn i'm sorry for this mistake:
Dim Withevents does not work as "WithEvents is not valid on a local variable declaration".

Which means I have to publicly declare all my possible Child forms in my MDIParent form, right ?
You can create a delegate.

on your child form, add the following:

#Region "Delegates"
        Private m_DelegateObject As Object    ' This is the object that will store the function it's supposed to call.
        Public Property DelegateObject() As Object    ' A property to get and set the delegate object
            Get
                Return m_DelegateObject
            End Get
            Set(ByVal value As Object)
                m_DelegateObject = value
            End Set
        End Property
#End Region


Now, in your child form closing event, add this:

If Not DelegateObject Is Nothing Then DelegateObject.Invoke(Me)




Now, on your parent form, create a sub or functin that you want to be the routine that is called when a child form is closed:

    Private Sub MDIChildClosing(ByVal Child As Form)
        MsgBox("Form " & Child.Name & " is closing")

        ' IF you need to access a unique variable or property in the form that
        ' is not a member of the generic "form" object, you can do a type convertion
        ' to the form itself to access them.

        Select Case Child.Name
            Case "ChildForm1" : MsgBox("My customer property value is " & CType(Child, ChildForm1).MyCustomProperty)
        End Select
    End Sub




Now, on your parent when ever you open your child form, you need to give the form the address of your sub. To do this, you do the following

ChildForm1.DelegateObject = AddressOf MDIChildClosing

Now, when your child form closes, it will call the sub MDIChildClosing on the parent, thus allowing the parent to to process the fact the the child is closing.


This is how you "pass" a function or sub from one object to another, and have it "run" on the parent. Just make sure that if you change the parameters of your sub that you change them in your child's call too.

I am using the form itself as the variable that I am passing, but you can use anything...
if DelegateObject.Invoke(Me) doesn't work (which may not because you are passing the object that is closing) then just do a me.name instead and change the MDIChildClosing paramters to "Name as string" instead of "Child as form" and process however you are comfortable.

Mystify, thank you very much for this info.

While trying to implement it I'm running into some small problem(s) here.

First thing is that it's not my parent form which is opening new MDI child forms, it's other MDI children opening them.
So, I've put the Delegate in my MDI children that need to notify the parent that they're down.
I've put the Child form code in the child form.

but now, the last missing link, is the delegateobject. I have setup the another MDI child with this code:

        If Not IsChildInMemory("frmKlantNieuw") Then
            Dim myform As New frmKlantNieuw
            myform.DelegateObject = AddressOf MDIStartForm.MDIChildClosing
            myform.MdiParent = Me.MdiParent
            myform.Show()
        End If

this code worked, but when i added the delegateobject line, it gives me this: 'AddressOf' expression cannot be converted to 'Object' because 'Object' is not a delegate type. Thus, it's not working just yet.
Also, as a sidenode, I didnt get intellisense on the DelegateObject.Invoke(Me) (as in: it didnt know the invoke function. it isnt complaining either though)
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Idle_Mind, you have always been my hero in VB.net :)

i didnt need all the enabling or disabling, i just needed to be able to know what form has been closed so I can act on it (ie: refresh my datasets in other forms)

but the rest of your code is working 100% fine.

thank all 3 of you for your help, but i will move all points to Idle_Mind, as he perfectly answered my Q :)

now, if one of you would be so kind as to answer my other question aswell (Cut/Copy/Paste and basic undo in MDI children), I would be the happiest dude alive :-D

cheers,
Andy
I have been looking for this solution for a long time....thank you so much...worked great!