VB.NET: How to close and re-open a dialog in this case? - vb.net

I'm developing a WinForms app in VB.NET, that handles sets of style data, and when the user clicks on another set's label, it prompts through a dialog "You are leaving this style preset to edit another one. keep changes on this one? [Yes] [No]"
But, I'm facing the problem that, when the user clicks either option, and the dialog closes, everything has to be refreshed, and loading the form again seems a good option.
I've tried putting a public sub on a module, that does this:
Public Sub CloseOpenStyleDlg()
KeepOrDiscardPrompt.Close()
StylesDlg.Close()
StylesDlg.ShowDialog()
End Sub
But as soon as that sub is called from the prompt, it crashes the application. (doesn't show an error in debug, simply crashes) How should I, from a given dialog, close the dialog, it's parent, and re-open it's parent? (which triggers all the Dialog_Load() code of the parent)
Thanks in advance! :)

You need to instantiate the dialog again. If I take your code for example:
Public Sub CloseOpenStyleDlg()
KeepOrDiscardPrompt.Close()
StylesDlg.Close()
StylesDlg = new StylesDlg()
StylesDlg.ShowDialog()
End Sub

When a form is closed, all resources created within the object are closed and the form is disposed.
If you want to reuse the Window instance use StylesDialog.Hide() function instead.

Related

What Is the Correct Way to Close and Reopen a Form Declared as Public?

My problem pertains to a COM add-in for Microsoft Excel. The use case is as follows: 1. User clicks the add-in's button on the ribbon. 2. A form window appears. 3. User interacts with the form window and clicks an OK button. 4. Various reports are generated, while a progress bar on the form window shows progress. 5. At the end of the process, the form window closes.
The process works as designed on the first run, but after the form window has been closed there is no way to start a new "session." From the user's perspective the add-in button becomes non-responsive. When run in debug mode from Visual Studio, clicking the add-in button a second time generates an error message: "Cannot access a disposed object."
Clearly something is wrong with the way I have hooked everything up, but I haven't been able to find a simple description of how to do it correctly. Here is what I have:
In a public class a number of public (or "global" variables) are declared; the form is also declared and instantiated here:
Public Class GlobalVariables
Public Shared FormInstance As New MyFormDesign
End Class
The reason for declaring the form as a public object is to be able to be able to send progress values from various different subs and functions. The GlobalVariables class is imported by all modules that require it.
Behind the ribbon button is a single line of code:
FormInstance.Show()
Clicking the button instantiates and shows the form as intended. To keep things simple we can ignore the bulk of the code; simply clicking the "Cancel" button will trigger the problem. The code behind the "Cancel" button is straightforward:
Me.Close()
GC.Collect()
After closing the form it is no longer possible to create a new instance, per the error message cited above.
I don't really understand what is going on here, but it looks to me like the GlobalVariables class, once created, persists until the end of the Excel session. If that is correct the problem could presumably be cured by instantiating the form in a standard module. Instead of attempting to revive a form that has been disposed, the add-in would just create a new instance each time the user clicks the button. But if I go that route I can't figure out how to send progress values from other subs back to the form. It seems like a Catch-22.
There has got to be a way to both (a) create the form as a public object, and (b) create and destroy a new instance each time the add-in is run. Right? What am I doing wrong?
It has been a long journey, but I finally found out how to build the functionality described in my question. I will post the answer here, as it may help others in the future.
The challenge was to declare a form as Public in order to make it accessible throughout the project, so that subs and functions can send progress updates back to the form.
The problem was that the form, when declared and instantiated as described in my question, can only be created once per Excel session.
The solution is to declare the form as Public without instantiating it, then access it via a Public ReadOnly Property.
First, declare FormInstance as a public variable without instantiating it:
Public FormInstance As MyFormDesign
Second, define a Public ReadOnly Property. This establishes a way to call the form:
Public ReadOnly Property CallMyForm() As MyFormDesign
Get
Return FormInstance
End Get
End Property
Third, the ribbon button's Click event instantiates and shows the form:
Private Sub Button1_Click(sender As Object, e As RibbonControlEventArgs) Handles Button1.Click
FormInstance = New MyFormDesign
FormInstance.Show()
End Sub
Now a new form instance will be created each time the ribbon button is clicked, but the form can still be accessed via the CallMyForm property.
Instead of ...
FormInstance.BackgroundWorker1.ReportProgress(i)
... we will use:
CallMyForm.BackgroundWorker1.ReportProgress(i)
This solves the conundrum laid out in the question.

Opening a second-form more than once error

I have a button in form1 that opens form2. I do this using frm2.show(). It works totally fine for the first time that I open frm2, but when I close frm2 and click on the button in frm1 to open frm2 again, I get this error:
Can someone tell me how to solve it?
Edit: I have a module where I have my database connection and my declaration for the forms:
Public frmGame As New Game
Public frmPlay As New Play
Public frmFinish As New GameFinish
Public frmLogin As New Login
Public frmManage As New Manage
Public frmInsert As New Toevoegen
Where I open the form is just when I click on a button in form1.
Sounds to me like you are Close()ing frm2. Closing a form should dispose it and release its resources, so you can't simply Show() it again. Instead, you need to create a new instance of the object, like this:
frm2=new Form2()
frm2.Show()
If that doesn't work (perhaps because you don't want to re-initialize the form's data members), you could use Hide(), rather than Close() to temporarily hide the form during your program's execution.
If you need to prevent the form from being closed with the X button, you can do this with a few different methods:
The best way to go may be to hide or disable the close button. Read up on This post to get a better idea of how to do that.
You can use the FormClosing event, either from inside frm2 or from the main window. Set the Cancel property on the FormClosingEventArgs object that gets passed in. The problem here is that you will need to provide an additional code path to close the form when you actually want it to close. The CloseReason property of the FormClosingEventArgs object should give you a way to handle that properly. Needless to say, this is probably the riskiest way to do things, since you need this window to close when the application shuts down, but you're also intentionally block that from happening.
You could catch the FormClosed event in the the form that spawns frm2, then create a new instance of the window. Again, you'll need to provide a code path to allow the window to close when the application shuts down.
In all, method 1 is probably the safest. You can close the window with .Close() when the application shuts down, but the user can't close it with the X button.

Application fail to exit when a runtime created object is used

I'm using vb.net 2013, and I have configured Shutdown mode to "When last form is closed".
On my main form, I have a menu item which has this code to close the application:
Application.Exit
Everything is working fine, except one case:
When I open a specific form, where a Combobox is created on runtime and I've used Addhandler to subscribe to several events.
The combobox is created when pressing a button.
When I open this form and I don't create the combobox, everything is working ok. If the combobox is created, when I close this form and try to close the application using the menu item, nothing happens. The application is not closed and no error message is displayed. (the same situation occurs when I try to close the main form with "x" button)
On the form's (where I have the combobox) close event , I tried to put a line of code:
MyCombobox.dispose()
But the situation is the same.
What can I do? Thank you!
What I do from my little experience is
1.) remove the MyCombobox from its parent control (I'm think this is in your combobox close event).
2.) set the MyCombobox to Nothing
3.) Dispose() it.
MyCombobox = Nothing
MyCombobox.Dispose()
It would be useful to see some part of your code for the close event so we can help you check. More power to you!
Update based on OP's comment:
I have read the following from MSDN: https://msdn.microsoft.com/en-us/library/system.windows.forms.form.closing(v=vs.110).aspx
From this, it is important to note that:
The Form.Closed and Form.Closing events are not raised when the Application.Exit method is called to exit your application. If you have validation code in either of these events that must be executed, you should call the Form.Close method for each open form individually before calling the Exit method.

Difference form.Close() and form.hide()

What is the difference between form.Close() and form.Hide() in desktop application.
i know Form_Close event will not be fired in form.Hide() method what about other differences.
Is anyone faster?
form.Close() unloads the form from memory and makes it available to be garbage collected; you can no longer interact with the form in code.
form.Hide() just hides the form, but you can still interact with it in your code.
So it is not really a question of which one is faster, but rather "are you really done using this form or not"?
Hide makes the form invisible to the user. Close actually closes it and calls dispose on it.
From: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.close(v=vs.110).aspx
"When a form is closed, all resources created within the object are closed and the form is disposed. "
Hide only hides the form from the screen. Close is of course closes the form. If you want to get rid of the form that you don't want to use anymore then you should use Close. Hide and Close are different things.
Ditto the above... Typically the way you open the form determines which to use. If you use .Show() the calling code continues while the form is loaded and shown. If you use ShowDialog() then calling code stops while the form is loaded and shown. When you Hide the called form the calling code resumes to the next statement.
Here is a sample of the second case:
Dim frm As New frmSearch2
frm.inFormName = "frmFacility"
frm.ShowDialog(Me)
If frm.outPrimaryKey.Length > 0 Then
frmMain.Open_Form("frmFacility", frm.outPrimaryKey)
End If
frm.Close
frm = Nothing
outPrimaryKey is a form level Public variable. You can also address any of the controls on the form.

vb.net - showdialog() sends main window to background

I have a modal window popup so a user of my application can edit some stuff, then they save it and close the window. When they close the popup window, my parent (main) window gets sent to the back of all other applications on my desktop, and then it immediately gets sent back to the front.
Any idea why this would happen?
In your main form:
Dim frmDlg as New FormDialogToShow
frmDlg.ShowDialog(Me)
The main form should not get sent to the back. The child dialog will display on top of the parent. Without the owner reference, the mainform can sometimes get sent to the back. When you dont specify an owner form and that happens:
Dim frmDlg as New FormDialogToShow
frmDlg.ShowDialog()
Me.BringToFront
(the answer is the same as the first time)
Does your modal form somehow hide itself before ShowDialog line ends? This happened to me and was able to solve it by removing the Hide call from the modal form.
I think I read somewhere here in SO that this happens because Windows does not have an enabled window to send focus to in the active app so it sends focus to the next app instead.
This code seems to solve the problem:
' When closing the subform
' ------------------------
sub_form.close()
main.focus()
sub_form.dispose()
When doing this, my main form does not get sent to the back even when the sub form is modal window.
I was searching desperately to find the answer to a similar problem. I found this to be particularly useful:
Private Sub Frm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
Prompting = False
Frm = Nothing
FrmPrompt.Close()
FrmPrompt.Dispose()
FMain.Activate()
End Sub
Activate allowed my main form to not be sent behind anything else I had open.