Simple Problem....again...same...

  • Thread starter Thread starter Sender
  • Start date Start date
S

Sender

Yesterday there was a very long thread on this query. (You can search on
this by post by 'sender' with subject 'Simple Problem' post date Oct 7 time
1:43p)

And in the end the following code was decided to open a new form:

---Code in the click event of a button: button1
if frm is nothing then
frm = new form2()
frm.show
endif

---Code outside any procedure
dim frm as form2

Now when first time we click on this button (button1) it shows form2. Now we
close this form2. Now when we again click button1 ........NOTHING
HAPPENS.........it doesn't open form2 again..................WHY ?
 
Sender said:
Yesterday there was a very long thread on this query. (You can search
on this by post by 'sender' with subject 'Simple Problem' post date
Oct 7 time 1:43p)

And in the end the following code was decided to open a new form:

---Code in the click event of a button: button1
if frm is nothing then
frm = new form2()
frm.show
endif

---Code outside any procedure
dim frm as form2

Now when first time we click on this button (button1) it shows form2.
Now we close this form2. Now when we again click button1
........NOTHING HAPPENS.........it doesn't open form2
again..................WHY ?

Because you don't set frm to Nothing when form2 is closed. Handle the closed
event of frm, there set frm = Nothing. Of course, frm mustn't be declared
locally.
 
Hi Sender,

You declare frm outside any procedures. Do you use this variable in any
other way or is it just to create and show a form2 from within button1_click ?

If you don't use it for anything else put it in click:
sub click
Dim frm As New Form2
frm.Show

If you use it for other purposes it's more tricky. Tell me which.

Regards,
Fergus

ps. There's another reply to you in the other query.(context menu & left
mouse).
 
Hi Sender, the object is disposed, but it's not dereferenced, so Is Nothing
will always evaluate to False.

To use it again, you'll have to reinstantiate... Try the following

' /// Put this code in your button click

' This creates an instance of the form, if none exists
If frm Is Nothing Then
frm = New Form2()
End If

' This will show the form if it is invisible.
If Not frm.Visible Then
frm.Show()
End If

--
HTH,
-- Tom Spink, Über Geek

Please respond to the newsgroup,
so all can benefit

" System.Reflection Master "

==== Converting to 2002 ====
Remove inline declarations
 
Hi Tom,

There may still be a problem after Form2.Close - because frm (in Form1,
presumably) will reference a disposed Form. In good old VB6 it would work ok
because frm.Visible would reload Form2. Not so, with our young .NET

'Tis trickier than at first it seems.

Regards,
Fergus
 
Hi Armin,

And if it's declared inside Form1, Form2 needs a reference to Form1.

Regards,
Fergus
 
If I declare frm in the click event of button then every time I click on
button1 it will open new copy of form2. That means every time it will open a
new form. Three times click means three form2. I know I am missing
something...but I don't know what. Please help.
 
If I declare frm in the click event of button then every time I click on
button1 it will open new copy of form2. That means every time it will open a
new form. Three times click means three form2. I know I am missing
something...but I don't know what. Please help.
 
Sender said:
If I declare frm in the click event of button then every time I click
on button1 it will open new copy of form2. That means every time it
will open a new form. Three times click means three form2. I know I
am missing something...but I don't know what. Please help.


"frm mustn't be declared locally". In other words: Declare it at class
level.
 
Hi Sender,

Ah yes, multiple invocations.

The thing is,
You think it's a simple problem.
We think it's a simple problem.
It <should be> a simple problem.
In VB6 it <is> a simple problem.

But in .NET it's not!!

LOL.
Here we are - the 'Experts' - and between us we've given you
Nothing
Duplicates
Exceptions.
!!


[VB.NET designers take note - too many people, including us!,]
[are having great difficulty with what used to be a no-brainer.]

There are a number of solutions, fairly straightforward, but I can't
decide which is best. Moreover I'm immensely tired so I can't think too
clearly.

But here's a simple and nasty (from a pure OOP point of view) solution.
It's tested and it works [fingers crossed, lol!]

In Form1
Public oForm2 As Form2 'Outside any procedures.

Sub Clicky_Click
If oForm2 Is Nothing Then
oForm2 = New Form2 (Me)
End If
If Not oForm2.Visible Then
oForm2.Show
oForm2.Activate
End If
End Sub

In Form2
Private oForm1 As Form1 'Outside any procedures.

Sub New (oThisForm1 As Form1)
MyBase.New()
InitializeComponent()
oForm1 = oThisForm1
End Sub

Sub Form2_Closed (ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Closed
oForm1.oForm2 = Nothing
End Sub

The reason it's 'nasty' is that Form1 and Form2 both know (too much) about
each other (jargon - they are tightly-coupled). And what do you do if you add
a third form, and a fourth. And, oh it gets messy.

Perhaps the other guys will come up with some clean, elegant OOP solutions
in the morning.

Me? I'm off to bed. G'night!

Regards,
Fergus
 
Sender said:
Yesterday there was a very long thread on this query. (You can search on
this by post by 'sender' with subject 'Simple Problem' post date Oct 7 time
1:43p)

And in the end the following code was decided to open a new form:

---Code in the click event of a button: button1
if frm is nothing then
frm = new form2()
frm.show
endif

---Code outside any procedure
dim frm as form2

Now when first time we click on this button (button1) it shows form2. Now we
close this form2. Now when we again click button1 ........NOTHING
HAPPENS.........it doesn't open form2 again..................WHY ?

Basically, as Armin said - the variable holding the form2 instance never gets
set to nothing. So, the second time the code runs - it is not created. Here is
one possible solution - hook the child forms closed event. That way, you know
it has shutdown and set the instance to nothing... Here's the code:

' Form1 Code....
Option Explicit On
Option Strict On

Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(108, 40)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 105)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private frm As Form2

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
If frm Is Nothing Then
frm = New Form2
AddHandler frm.Closed, AddressOf Me.ChildClosed
frm.Show()
End If
End Sub

Private Sub ChildClosed(ByVal sender As Object, ByVal e As System.EventArgs)
frm = Nothing
End Sub

End Class

' Form2 Code
Public Class Form2
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Label1 As System.Windows.Forms.Label
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Label1 = New System.Windows.Forms.Label
Me.SuspendLayout()
'
'Label1
'
Me.Label1.Dock = System.Windows.Forms.DockStyle.Fill
Me.Label1.Font = New System.Drawing.Font("Microsoft Sans Serif", 36.0!,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0,
Byte))
Me.Label1.ForeColor = System.Drawing.Color.Blue
Me.Label1.Location = New System.Drawing.Point(0, 0)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(292, 97)
Me.Label1.TabIndex = 0
Me.Label1.Text = "Form2"
Me.Label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
'
'Form2
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 97)
Me.Controls.Add(Me.Label1)
Me.Name = "Form2"
Me.Text = "Form2"
Me.ResumeLayout(False)

End Sub

#End Region

End Class

HTH,
Tom Shelton
 
Tom Shelton said:
Basically, as Armin said - the variable holding the form2 instance never gets
set to nothing. So, the second time the code runs - it is not created. Here is
one possible solution - hook the child forms closed event. That way, you know
it has shutdown and set the instance to nothing... Here's the code:


Ouch, there is a small bug in the following code - I forgot to call
RemoveHandler :) So, see below for the changes...
' Form1 Code....
Option Explicit On
Option Strict On

Public Class Form1
Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()

'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(108, 40)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 105)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private frm As Form2

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
If frm Is Nothing Then
frm = New Form2
AddHandler frm.Closed, AddressOf Me.ChildClosed
frm.Show()
End If
End Sub

Private Sub ChildClosed(ByVal sender As Object, ByVal e As
System.EventArgs)

'*************************************************
' HERES THE CHANGE
'*************************************************
RemoveHandler frm.Closed, AddressOf Me.ChildClosed
frm.Dispose()
'*************************************************
 
Oh of course, silly me, I forgot the most important part...

Changet this:
to this:

If frm Is Nothing OrElse Not frm.Visible Then
frm = New Form2()
End If

Note: OrElse is very important, as it's a short-circuited Or

--
HTH,
-- Tom Spink, Über Geek

Please respond to the newsgroup,
so all can benefit

" System.Reflection Master "

==== Converting to 2002 ====
Remove inline declarations
 
Hi Tom,

Lol, and when Form2 is closed and disposed, frm still has a reference?

Regards,
Fergus
 
Hi Tom,

Somewhere in there, I'm <sure> it's raising the ChldClosed but I just
can't see it. Maybe I should have a cup of tea and wake up properly before
looking again?. ;-))

Regards,
Fergus
 
Hi Tom,

Somewhere in there, I'm <sure> it's raising the ChldClosed but I just
can't see it. Maybe I should have a cup of tea and wake up properly before
looking again?. ;-))

Regards,
Fergus

No need to raise it. It is raised automatically when you close Form2.
There is no rule that the form itself has to handle it's events :) The
callback is made to the parent. And it's no problem to have Form2
handle it's closed event as well - multicasting in action :)

Tom Shelton
 
Hi Tom,

|| It is raised automatically when you close Form2.

Thanks for that - learning something new every day. :-)

Regards,
Fergus
 
Back
Top