Solved

Removing form object from a 'collection' when closed

Posted on 2004-08-11
25
331 Views
Last Modified: 2008-03-10
Hi,

Im having a little problem with forms :)

Basicly, I have a listview of records and when a user dbl click's a record it opens a new instance of the displayrecord form.  The user can open multiple records but if a use tries to open record for which they already have the form open it will just brings the existing open form to focus (I store he record ID in the .TAG so I know which form is for which record)

Now everything works great inc bring the already existing form to focus, apart from when I close a form it dosnt get removed from the collection object that stored all the forms so I cant reopen a record after its closed.

I've inc'd some code to hopfully make it clear how im doing it.

[Main Form (frmMain) With Listview on it]
Friend Shared oFormCollection as New Collection

[In Listview dblClick Code]
'// Before loading form lets make sure it isnt already open
Dim iRecordToOpen As Integer

iRecordToOpen = '// Code Here

Dim oForm As Form
Dim bLoadNewForm As Boolean = True

For Each oForm In frmMain.oFormCollection
      If oForm.Tag = iRecordToOpen Then
           oForm.BringToFront()
           oForm.Focus()
           bLoadNewForm = False
           Exit For
      End If
Next

'// If form isnt open then create a instance of the record form and display it
If bLoadNewForm Then
      Dim oNewForm As New frmDisplayRecord(iRecordToOpen)
      oNewForm.StartPosition = FormStartPosition.CenterScreen
      oNewForm.TopMost = True
      oNewForm.Focus()
      frmMain.oFormCollection.Add(oNewForm)
End If

[END]

It apears when I close the form, the instance of the form object stays in the oFormCollection, which mean if I wish to reopen the record it already thinks is open.  Am I going about this the wrong way?

Regards

=Daniel=
0
Comment
Question by:emub
  • 12
  • 8
  • 5
25 Comments
 
LVL 25

Expert Comment

by:RonaldBiemans
Comment Utility

change

If bLoadForm Then
      Dim oNewForm As New frmDisplayRecord(iRecordToOpen)
      oNewForm.StartPosition = FormStartPosition.CenterScreen
      oNewform.owner = me
      oNewForm.TopMost = True
      oNewForm.Focus()
      frmMain.oFormCollection.Add(oNewForm,oNewform.Name)
End If

in the closed event of your frmdisplayRecord add this

    Private Sub frmDisplayRecord_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
        CType(Me.Owner, Form1).oform.Remove(Me.Name)
    End Sub

0
 
LVL 25

Expert Comment

by:RonaldBiemans
Comment Utility
sorry this should be

 CType(Me.Owner, Frmmain).oform.Remove(Me.Name)
0
 
LVL 25

Expert Comment

by:RonaldBiemans
Comment Utility
Djees, whats wrong with my typing

CType(Me.Owner, Frmmain).oFormCollection.Remove(Me.Name)

0
 
LVL 4

Expert Comment

by:Daniellus83
Comment Utility
If I am understanding it all well:

you forgot to add this code

      bLoadNewForm = True

You should add this code inside the "Closing" (or something) event/handle of the opened Form. Thats why it thinks that its still open. So, as soon as that form is closed, its putting the boolean var bLoadNewForm back to value True.

0
 

Author Comment

by:emub
Comment Utility
bLoadNewForm is Declared everytime the

"Private Sub listmenu_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.DoubleClick"

is called.
0
 

Author Comment

by:emub
Comment Utility
Ok sorry, I forgot to add that  

Dim oNewForm As New frmDisplayRecord(iRecordToOpen)

frmDisplayRecord(ByVal RecordID As Integer) Is a function that reutrns a form from another DLL.  So effectivly the form DisplayRecord isnt in the same project

( Sorry I should have mentioned that )

So If couldnt put

    Private Sub frmDisplayRecord_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Closed
        CType(Me.Owner, frmMain).oFormCollection.Remove(Me.Name)
    End Sub

As I would get the following message "Type 'frmMain' is not defined."

0
 
LVL 4

Expert Comment

by:Daniellus83
Comment Utility

Ow, I understood that you have multiple forms open. Don't you need also multiple var bLoadNewForm. Like an array of bLoadNewForm(1 to Max Number of possible WindowWith_Record Open)?

Then you should get rid of this:


       bLoadNewForm is Declared everytime the

       "Private Sub listmenu_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.DoubleClick"

       is called.


And add
     
      bLoadNewForm(Form_Record_Open_ID) = True

       You should add this code inside the "Closing" (or something) event/handle of the opened Form. Thats why it thinks that its still open.
       So, as soon as that form is closed, its putting the boolean var bLoadNewForm back to value True.

For every possible open form!
0
 
LVL 25

Expert Comment

by:RonaldBiemans
Comment Utility
if you reference that project in your dll you could
0
 

Author Comment

by:emub
Comment Utility
Is there anyway to go though the forms objects in the collection and test if they have been closed or not?
0
 

Author Comment

by:emub
Comment Utility
The frmMain is in the Main EXE,   frmDisplayRecord is in a seperate DLL, I presumed in the DLL you can only reference to other DLL not EXE's?
0
 
LVL 4

Expert Comment

by:Daniellus83
Comment Utility
Okay,.. you need to find first out if this form is open (after the user clicked a record on the listview):

use this code:

dim boolean iRecordToOpen(iRecordToOpen)   'I assume this var has number 1 to 100 or so...


For Each oForm In frmMain.oFormCollection
      If oForm.Tag = iRecordToOpen Then
           oForm.BringToFront()
           oForm.Focus()
           bLoadNewForm = False
           Exit For
      End If
      '
      'If the user gets here, the form isn't open (yet)!
      'Set Boolean to True
     bLoadNewForm (iRecordToOpen) = True
Next


Now execute the following code:


If bLoadNewForm (iRecordToOpen) Then
      Dim oNewForm As New frmDisplayRecord(iRecordToOpen)
      oNewForm.StartPosition = FormStartPosition.CenterScreen
      oNewForm.TopMost = True
      oNewForm.Focus()
      frmMain.oFormCollection.Add(oNewForm)
End If


0
 
LVL 25

Accepted Solution

by:
RonaldBiemans earned 400 total points
Comment Utility
you could do this ofcourse

        For Each oForm2 In oform
            Try
                oForm2.Select()
            Catch EX As Exception
                oform.Remove(oForm2.Name)
            End Try
        Next

0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 

Author Comment

by:emub
Comment Utility
:) I thinks there has been some crossed wires with the var bLoadNewForm, this was tempoary var I was using that was onyl referenced during the dbl_click process (my fault its was poorly written)

I restructurd the code to make it clear (even though the problem still exists) :) hehe

[on the main form]

Dim oFormCollection As New Collection     '// This hold a collection of all the forms that are open

[on the doubleclick part of the list view]

Private Sub listmenu_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.DoubleClick
      Dim iRecordToOpen As Integer
     
      iRecordToOpen =  '// Code to get ID of record from listviewitem

      If Not IsFormAlreadyOpen(iRecordToOpen) Then    'If the form isnt already open then open it and add it to the form collection
            Dim oNewForm As New frmDisplayRecord(iRecordToOpen)
            oNewForm.StartPosition = FormStartPosition.CenterScreen
            oNewForm.TopMost = True
            oNewForm.Focus()
            frmMain.oFormCollection.Add(oNewForm)
      End If
End Sub

[function within the listview]

Private Function IsFormAlreadyOpen(byVal RecordID As Integer) As Boolean
      Dim oForm As Form

      For Each oForm In frmMain.oFormCollection
            If oForm.Tag = RecordID Then
                 oForm.BringToFront()
                 oForm.Focus()
                 Return True
            End If
      Next

     '// If code should reach here then the record isnt already open
     Return False
End Function


[END]

Now when I close a record form, the instace of the object is still in the oFormCollection so when the function IsFormAlreadyOpen() is call it find the relevant form and tries to bring it to focus then returns True. How ever the user as already closed this form.
0
 
LVL 4

Expert Comment

by:Daniellus83
Comment Utility
Sorry I posted my code not quite correct:

use these codes:

> Define this var 'global' (outside a sub):

-----------------------------------------------------------------------------------------------------------------------------------------

dim boolean iRecordToOpen(iRecordToOpen)   'I assume this var has number 1 to 100 or so...

-----------------------------------------------------------------------------------------------------------------------------------------

You need a boolean var for each possible form with record information.



> Put this piece of code in the Event thats called (OnDoubleClick?) of your ListView:

-----------------------------------------------------------------------------------------------------------------------------------------
'First we need to check if this form with clicked record is already open:

For Each oForm In frmMain.oFormCollection
      If oForm.Tag = iRecordToOpen Then
           oForm.BringToFront()
           oForm.Focus()
           bLoadNewForm = False
           Exit For
      End If
      '
      'If the user gets here, the form isn't open (yet)!
      'Set Boolean to True
     bLoadNewForm (iRecordToOpen) = True

Next

'If this Form is not found, the For-loop finish with the bLoadNewForm (iRecordToOpen)  set to  TRUE.
'If that is so, we have to generate the form and open it:

If bLoadNewForm (iRecordToOpen) Then
      Dim oNewForm As New frmDisplayRecord(iRecordToOpen)
      oNewForm.StartPosition = FormStartPosition.CenterScreen
      oNewForm.TopMost = True
      oNewForm.Focus()
      frmMain.oFormCollection.Add(oNewForm)
End If

-----------------------------------------------------------------------------------------------------------------------------------------


Try it and maybe you like it!
0
 

Author Comment

by:emub
Comment Utility
RonaldBiemans: I tried that but get the following error when trying to remove the "closed" form from the collection

"Additional information: Argument 'Key' is not a valid value."


 Daniellus83: With using an array, I would need to know how many record would be in the listview so I can declarer it? (I think)
0
 
LVL 4

Expert Comment

by:Daniellus83
Comment Utility
Why not try to remove the form first?!

In the case the window is already open: the user wouldn't see it if it was already open:

Change this code:

-------------------------------

Private Sub listmenu_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.DoubleClick
      Dim iRecordToOpen As Integer
     
      iRecordToOpen =  '// Code to get ID of record from listviewitem

      If Not IsFormAlreadyOpen(iRecordToOpen) Then    'If the form isnt already open then open it and add it to the form collection

           'Try first to close the form: even when its not open:

             Try
                frmMain.oFormCollection.Remove( THE_FORM_iRecordToOpen)
             Catch EX As Exception
                'The code here would be called if the form couldn't be closed,.. just don't put here any code!
            End Try
     
            Dim oNewForm As New frmDisplayRecord(iRecordToOpen)
            oNewForm.StartPosition = FormStartPosition.CenterScreen
            oNewForm.TopMost = True
            oNewForm.Focus()
            frmMain.oFormCollection.Add(oNewForm)
      End If
End Sub

-------------------------------

   
0
 

Author Comment

by:emub
Comment Utility
RonaldBiemans:  

That idea seems to be along the right path, as the form object once its is closed still remains the the oFromCollection in a "disposed" state, hance its closed but its instance is still there in the collection.
Trying the .Select does cause an error

"System.ObjectDisposedException: Cannot access a disposed object named "UserDetails". Object name: "UserDetails"."

This is trapped, but the problem now lies with trying to find and remove that closed FORM from collection.
0
 

Author Comment

by:emub
Comment Utility
Daniellus83: that would work but the problem im having is using the "frmMain.oFromCollection.Remove(key as string)" function.

I need to locate the correct form in the collection and remove it, but as far as im aware they are all called the same thing?
0
 

Author Comment

by:emub
Comment Utility
ik this was fixed by


When adding an item to the collection I changed the code to

frmMain.oFormCollection.Add(oNewForm, RecordID)

and when removing the "closed" form I used

frmMain.oFormCollection.Remove(RecordID)



0
 

Author Comment

by:emub
Comment Utility
Ok 1 last question regarding Exceptions

I tested this and I get the follow behaviour

Open Record Number 1, For shows
Close Record Number 1 form
Reopen Record Number 1,  there is a very long pause while its at the exception part, then form opens
Close Record Number 1 form
reopen Recrd Number 1, opens instantly

open and close and records repeatly and they open close without delay?

It would seem that when the program runs the first time it encounters the exception its does something (maybe searchs and loads somthing) then once its done it for the first time, after that its runs really smooth.
0
 
LVL 4

Expert Comment

by:Daniellus83
Comment Utility
Yes,...

thats it!... I was just reproducing the problem with some buttons,.. it worked and mine is not neccesary any more.

:-\
0
 
LVL 4

Assisted Solution

by:Daniellus83
Daniellus83 earned 100 total points
Comment Utility
I had the same problem,.. that must be it ("the learning process..." ;-) ) I cannot really explain why.. thats something 'deeper'.
0
 
LVL 4

Expert Comment

by:Daniellus83
Comment Utility
Anyway, I have one (hopefully good suggestion) since the try statement is not the finest to have...

> Why not keep a (global defined) array with opened ID wich are opened. Everytime one is closed, you search this array, if you find it, delete it in the Collection (and delete it in the array)

This way you have taken proper care of the window-management!
0
 

Author Comment

by:emub
Comment Utility
hehe Wish it would "learn" alittle quicker :)
0
 

Author Comment

by:emub
Comment Utility
An Array of all RecordID's open?
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now