Display a modeless Form but only one - vb.net

VB2010. I must be missing something because I couldn't find a solution after searching for an hour. What I want to do is simple. In my app I want to display a modeless form so that it is floating while the user can still interact with the main form.
dim f as New frmColors
f.Show(Me)
But I only want one instance of the form at any time. So how can I prevent more than once instance being displayed, and if there is one instance then just give it focus?

Does something like this work for you, if the form is already visible you can not do a Show, you can just do a BringToFront, also you can check to see if the Form has been disposed so you can New up another one.
Public Class Form1
Dim f As New frmColors
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
If f.IsDisposed Then f = New frmColors 'To handle user closing form
CheckForm(f)
End Sub
Private Sub CheckForm(frm As Form)
If frm.Visible Then
frm.BringToFront()
Else
frm.Show(Me)
End If
End Sub
End Class

Make your form follow the singleton pattern. I can't vouch for this sample, but from the text it appears to do what you want.

Related

VB.Net passing datagridview row from one form to another form that is already open

I'm trying to develop a search window that allows a user to fill in criteria, then click the search button. When the search button is clicked the results are returned in a DataGridView. When a result in the DataGridView is clicked, I'd like to pass the row number to another form that is already open.
I understand I can pass the result by creating a new instance of the form. I pass variables to my Search Window using the following method:
Private Sub SearchButton_Click(sender As Object, e As EventArgs) Handles SearchButton.Click
Dim ST = New Search_Tool(DGV_Ongoing.DataSource, AgencyOptions, EthnicityOptions, EmploymentTypeOptions, EmploymentStatusOptions,
CategoryOptions, OutcomeOptions)
ST.Show()
End Sub
however I cannot call the form I want to pass the row value to because it is already open (its the main form). Is there a way to handle this? I'm struggling to find any information that doesn't call the form to open it whilst passing the data.
I can't reference Main_form.Main_DGV.CurrentCell as Visual Studio says it requires an Object Reference in order to do so.
Thanks in advance!
I'd recommend an event in your Search_Tool form that is raised when the user has found what they're looking for.
The main form is subscribed to that and can then access its datagrid.
Class Search_Tool
Inherits Form
Public Event SearchResultFound(resultId As Integer)
Private Sub OnUserClickedARowOrPressedAButtonOrWhatever()
RaiseEvent SearchResultFound(currentRow.Id)
End Sub
End Class
And in the main form.
Private Sub SearchButton_Click(sender As Object, e As EventArgs) Handles SearchButton.Click
Dim ST = New Search_Tool(DGV_Ongoing.DataSource, AgencyOptions, EthnicityOptions, EmploymentTypeOptions, EmploymentStatusOptions,
CategoryOptions, OutcomeOptions)
AddHandler ST.SearchResultFound, Sub(result As Integer)
'handle your result id here.
MessageBox.Show("User selected row " & result)
End Sub
ST.Show()
End Sub
The advantage of this is that the SearchForm doesn't need to know what it's being used by. It's just there to give results which will make it easier to reuse later.

ShowDialog() in vb.net not working properly

I'm not sure if this question has been already posted or not but since I couldn't find the answer I'm looking for so I'll ask anyways.
When I use ShowDialog() to call another form from the current form it just displays the name of the controls the first time it opens, if I close it and open it again then it displays at it should have. For example if I write a simple code as follows
Form1
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Form2.Display("Message")
End Sub
End Class
Form2
Public Class Form2
Public Sub Display(ByVal msg As String)
Me.ShowDialog(Parent)
Label1.Text = msg
End Sub
End Class
When I click the button the first time all I get is "Label1" instead of "Message" displayed on the called form but when I click on the button a second time I get the desired output.
I tried the same thing with Show() and didn't have any such problem. But I need the called form to be modal (like a MessageBox), so is there any other way to do it or can someone tell me the right way to use ShowDialog() ?
I'm new to vb so please keep it simple.
Thanks
ShowDialog is a blocking call. You need to set everything before you call it.

Create And Implement a Custom Form in VB.NET

I am trying to create a customized form class (CustomBorderlessForm) in VB.NET.
My Progress So Far
I created a new Class and named it CustomBorderlessForm.vb
I then proceeded to write the following code:
CustomBorderlessForm.vb
Public Class CustomBorderlessForm
Inherits Form
Dim _form As Form = Nothing
Public Sub New(form As Form)
_form = form
MsgBox("Testing: New()")
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
MsgBox("Testing OnMouseMove()")
End Sub
End Class
Form1.vb
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim form As New CustomBorderlessForm(Me)
End Sub
End Class
Results of progress
A message box displays "Testing: New()" on load
Nothing shows on mouse move
As you can see, my problem lies with the events
Questions
Is it possible to create a form object and use that instead of the pre-populating form?
If so, can I give this form custom properties, such as, a border and some boolean values (shadow...etc), just like any other custom object/class?
What am I doing wrong in my current approach?
Why isn't the OnMouseMove being overridden?
Am I initialising the class wrong?
Can it even be done this way?
After creating a form you also need to show it. Change your logic to:
Dim form As New CustomBorderlessForm(Me)
form.Show()
Before you do that, I'd recommend changing from MsgBox to Console.WriteLine(), otherwise you can run into a fun/frustrating little cat and mouse game.
EDIT
Based on the comments, if, from VS you did a "Add New, Windows Form" you can just right-click the project, select property and on the Application tab change the Startup object to your new form. VS only allows you to do this with forms it creates for you (by default, more on this later).
If you wrote that file by hand (which is absolutely fine) you can perform the Show() like I did above and call Me.Hide() to hide the "parent" form. Unfortunately the Load event is fired before the Show event so if you place this in Form1_Load() it won't work. Instead you can use the Shown event like this:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim form As New CustomBorderlessForm(Me)
form.Show()
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
Me.Hide()
End Sub
Another option has to do with "Application framework". You can read about it here however it basically handles application events that other languages have to manually implement. If you go into your project properties you can uncheck the "Enable application framework" checkbox. This will give you more option in the "Startup object" dropdown. If you add the following code to your project one of the items in the Startup object dropdown menu should now be "Loader"
Public Module Loader
<STAThread()>
Public Sub Main()
Dim form As New CustomBorderlessForm(Nothing)
form.ShowDialog()
End Sub
End Module
You'll notice that the above bypasses Form1 completely. Also, instead of Show() I'm using ShowDialog() because otherwise the form shows and then the program ends.

Open Form as ShowDialog But Close Initation Form

Is there any way to do the following, other than hiding then closing the hidden form later?
Mainform opens SecondForm as show dialog, i need to Open ThirdForm from SecondForm while closing SecondForm while keeping third form acting as "showdialog" on the MainForm?
When you show SecondForm(), pass in MainForm() as the owner to ShowDialog():
Public Class MainForm
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sf As New SecondForm
If sf.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
' ... do some processing in here ...
End If
End Sub
End Class
Now, in SecondForm(), you can then set the owner of ThirdForm() to that of SecondForm():
Public Class SecondForm
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.Hide()
Dim tf As New ThirdForm
tf.ShowDialog(Me.Owner)
Me.DialogResult = Windows.Forms.DialogResult.OK
End Sub
End Class
You could simply open the third form from the main form as soon as the second form returns a dialog result
You also might want to look at MDI this gives you more control over what the user can and can't do.
After trying Idle_mind suggestion it was still giving me problems going back and forth between forms continously showing them as .showdialog. I solved my problem just like tinstaafl suggested. I wish i would have got his message before a couple hours of trying different methods before coming up with this one.
When i close each form, i set a boolean flag in the main form. then i call a sub that is in the main form to show the next form as showdialog from the main form. i use the flag which triggers logic in the form im loading whether or not to bind data from datatable so i can edit it.
sorry with all those forms i know it gets confusing. to sum it up, close the dialog form (me.close), set flag so calling code knows what to do once the showdialog code is satisfied.

How to make an single instance form

I have a mdicontainer form that summons forms. My problem is when the a user clicks again the menu for that form, it also make another instance of it.
What I did is declare a public class with a public variable on it ex: Boolean isFormOneOpen = false. Then every time formOne opens, it checks first the global variable I declared a while ago if it's false, if it is, instantiate an object of a formOne and then show it. Otherwise, do nothing. Very static, imagine if I have many forms, I have to declare a variable for each form to check if it's already open. Can you provide me a solution for this? Maybe a method that accepts a Form? Or any more clever way to do this.
You don't need a variable, you could iterate the MdiChildren collection to see if the form is already opened. For example:
Private Sub btnViewChild_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnViewChild.Click
For Each child In Me.MdiChildren
If TypeOf child Is Form2 Then
child.WindowState = FormWindowState.Normal
child.Focus()
Exit sub
End If
Next
Dim frm As New Form2
frm.MdiParent = Me
frm.Show()
End Sub
The VB.NET-centric solution:
Private Sub btnViewChild_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnViewChild.Click
Form2.MdiParent = Me
Form2.WindowState = FormWindowState.Normal
Form2.Show
End Sub
Rather than a boolean, declare a variable of the form's type. Then just make sure the variable isn't Nothing and call it's .Open() method. This has the nice side effect of also bringing your existing form instance to the front if it's already open.
Even better, in VB.Net 2.0 and later all forms have a default instance with the same name as their type, so you can just say FormName.Open() and be done with it. However, I haven't tried this in an mdi situation before.