I need your help to clarify whether form work exactly like object?
If I create an object,obj2, from another object,obj1. the obj2 will be disposed on obj1 dispose.
However it is not so with forms. check out the case & pseudo code give below.
I have three forms; form1, form2 & form2.
form1 is the startup form. form1 will create &s how a form2 and from2 will create & show form3 using a button in each form.
if I close form2, after opening all the 3 forms, I am able to work in form1 and form3.
my question is even though form3 is created from form2, why it is not disposed on form2 close?
Form1
Public Class Form1
Private Sub cmdOpenForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm2.Click
Dim frm As New Form2
With frm
''/.MdiParent = frmMain
.Show()
.BringToFront()
End With
End Sub
Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
''//frmMain.tsStatus.Text = "Form1 disposed"
End Sub
End Class
Form2
Public Class Form2
Private Sub cmdRandomColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRandomColor.Click
Randomize()
Label1.ForeColor = Color.FromArgb(Rnd() * 255, Rnd() * 255, Rnd() * 255, Rnd() * 255)
End Sub
Private Sub Form2_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
frmMain.tsStatus.Text = "Form2 disposed"
End Sub
Private Sub cmdOpenForm3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm3.Click
Dim frm As New Form3
With frm
''//.MdiParent = frmMain
.Show()
.BringToFront()
End With
End Sub
End Class
Form3
Public Class Form3
Private Sub cmdRandomColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRandomColor.Click
Randomize()
Label1.ForeColor = Color.FromArgb(Rnd() * 255, Rnd() * 255, Rnd() * 255, Rnd() * 255)
End Sub
Private Sub Form3_Dis开发者_C百科posed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
frmMain.tsStatus.Text = "Form3 disposed"
End Sub
End Class
Any Help will be greatly appreciated.
EDIT thank you all for the solution
Sorry to mention, I am not looking for a solution how to do dispose form3 on form2 close.
my interest is what is happening behind... Is there any possibility that form3 instance created from2 get GC collect and i get a memory error.
since i am getting protect memory access exception in my real application, which is not properly designed, and it too big to refactor now.
my question is where the form3 instance created? Is it in Form2 instance or somewhere else. since i can able to access form3 instance after form2 disposed. i doubt it is created in somewhere else
There's nothing automatic happening in Dispose calls on forms related to new forms you create yourselves.
If you want a form to automatically dispose of a form it creates, you have to add code yourself to do this. Either find the .Dispose method added by the designer, and add it there, or implement the FormClosed event on the form.
That form2 "creates" form1 does not make any kind of relationship between the two.
Automatic disposal is available as an option. The form must be an "owned" form. The easiest way to do this is to use the Form.Show(owner) overload:
private void button1_Click(object sender, EventArgs e) {
new Form3().Show(this);
}
Or you can do it afterwards with the Form.AddOwnedForm() method. Beware that this has side-effects, an owned form is always shown in front of the owner. And it will get minimized and restored along with the owner. If you don't want this, you can keep explicit track of the lifetime of the form and dispose it yourself:
private Form3 mForm3;
private void button1_Click(object sender, EventArgs e) {
if (mForm3 == null) {
mForm3 = new Form3();
mForm3.FormClosed += (s, ea) => mForm3 = null;
mForm3.Show();
}
else {
mForm3.WindowState = FormWindowState.Normal;
mForm3.Focus();
}
}
protected override void OnFormClosed(FormClosedEventArgs e) {
if (mForm3 != null) mForm3.Dispose();
}
The framework is still holding on to your form object, until it gets closed. You can get a reference to it using My.Application.OpenForms.
If i create an object,obj2, from another object,obj1. the obj2 will be disposed on obj1 dispose.
Not necessarily. If some other object, say obj3
has a reference to obj2
, then obj2
will stick around even after obj1
has been garbage collected.
In this case, the window manager has a reference to form3
, so it won't be garbage collected even when form2
is.
You have to use the Form-Constructor that takes a Win32-Window-Handle as a parameter. You can pass a reference of form2 to form3 then and it works as you expected.
Private Sub cmdOpenForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm2.Click
Dim frm As New Form2(Me)
With frm
.Show()
.BringToFront()
End With
End Sub
If you change the form variables to instance variables, and include this in the Show method, it will work
Code for Form1
public partial class Form1 : Form
{
Form2 f;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
f = new Form2();
f.Show(this);
}
private void button2_Click(object sender, EventArgs e)
{
f.Close();
f = null;
}
}
Code for Form2
public partial class Form2 : Form
{
Form3 f;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
f = new Form3();
f.Show(this);
}
}
精彩评论