VS 2010 Ultimate VB.NET Project form won't compile/show up - vb.net

When press F5 to compile a project, there are no errors or warnings but the form won't show up. What's up?

Every time that you try to run your code, it starts by creating an instance of frmMain, your default form and the one that is shown at application startup.
When this form is created, it automatically instantiates an instance of Form3 because you instantiate a variable of that type called modifyForm at the top of this form's code file:
Dim modifyForm As New Form3 'modify student
The problem is that, when the runtime goes to instantiate an object of type Form3, it gets called right back to where it was because of this statement at the top of the Form3 code file:
Dim frmMain As New frmMain
Rinse, lather, and repeat. Your code turns into an infinite loop, trying to instantiate an instance of frmMain, which tries to instantiate an instance of Form3, which tries to instantiate an instance of frmMain, ad nauseum. Eventually, this will overflow your available memory and cause a StackOverflowException.
It's important to note that all of this happens before the default instance of frmMain is even shown, because these variables are declared outside of any methods in your code. Because the computer never can escape this infinite loop, it never gets a chance to move on and actually display your form.
And the moment you've all been reading so patiently for:
Fix it by removing the declaration of frmMain at the top of the Form3 code file. I don't know what that's there for, anyway.
EDIT: Hopefully, I can clear up a little confusion regarding passing values between forms. Upon further study of your code, my instincts tell me that the best solution for you is to overload the constructor for Form3 to accept the calling form (the existing instance of frmMain) as an argument. This will allow you to access all of the public members of frmMain from within your Form3 class.
Here's a rough sketch of how you might do this in your code:
Public Class frmMain
''#The private data field that stores the shared data
Private _mySharedData As String = "This is the data I want to share across forms."
''#A public property to expose your shared data
''#that can be accessed by your Form3 object
Public Property MySharedData As String
Get
Return _mySharedData
End Get
Set(ByVal value As String)
_mySharedData = value
End Set
End Property
Private Sub frmMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
''#Do all of your other stuff here...
''#Create a new instance of Form3, specifying this form as its caller
Dim otherForm As New Form3(Me)
''#Show the new instance of Form3
otherForm.Show()
End Sub
End Class
Public Class Form3
''#The private field that holds the reference to the main form
''#that you want to be able to access data from
Private myMainForm As frmMain
Public Sub New(ByVal callingForm As frmMain)
InitializeComponent()
''#Save the reference to the calling form so you can use it later
myMainForm = callingForm
End Sub
Private Sub Form3_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
''#Access anything that you need from the main form
MessageBox.Show(myMainForm.MySharedData)
End Sub
End Class
As you can see, frmMain exposes a public property (backed by a correspondingly-named private variable) called MySharedData. This can be absolutely anything you want, and you can have as many of these as you want.
Also notice that how the constructor (the New method) for Form3 accepts an instance of frmMain as an argument. Whenever you create a new Form3 object from frmMain, you just specify Me, which indicates that you want to pass the current instance of frmMain. In the constructor method, Form3 stores that reference to its calling form away, and you can use this reference any time you like in Form3's code to access the public properties exposed by frmMain.

In VS2010 menu, go to Build -> Configuration Manager, does your project have the checkbox in the "Build" column enabled?
If it's project upgraded from an older Visual Studio version it may be that it is not targeting .NET Framework 4.0. In that case you should change it as explained here.

To analyze the problem press F8 (or F10, depends on your default keyboard settings) to step into the code instead of running the app. This should take you to the main method where the main form would be initialized.

Related

Find out reason for form instancing

In my application, a certain form is instanciated, and I have no idea why this happens.
I would therefore like to ask if it's possible to detect the "caller" that loads / instanciates the form.
Is it possible to get it from here?
Public Sub New()
InitializeComponent()
Or is there any other way how I could do this?
Edit:
This is the callstack:
The issue here was due to that you were accessing frmMain's default instance from a background thread.
VB.NET includes default instances of every form so that you don't have to do a Dim ... As New myForm every time you want to open a new form. This behaviour will let you shorten:
Dim mainForm As New frmMain
mainForm.Show()
to:
frmMain.Show()
And although not specifically documented, from previously conducting my own test it appears that the default instance is specific to the current thread only. Thus if you try to access the default form instance in any way from a background thread it will create a new instance for that specific thread, and therefore not be the same as the one you're using on the UI thread.
In the end this brings us to one of the golden rules of WinForms, which LarsTech mentioned: Leave all (G)UI related work on the (G)UI thread!
If you really need to access your first instance of frmMain from a background thread you should make a Shared property that returns that specific instance:
Private Shared _instance As frmMain = Nothing
Public Shared ReadOnly Property MainInstance As frmMain
Get
Return _instance
End Get
End Property
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If frmMain._instance Is Nothing Then frmMain._instance = Me 'Setting the main instance if none exists.
End Sub
Then from a background thread you'll be able to do:
frmMain.MainInstance.DoSomething

passing form textbox value to another form in same project

I currently have 2 forms. 1 holds user data and is modifiable. The other is a display/read only form.
I am trying to pull data (tbUSI.text) from ReportSettings and pass it to Form1 and display it on my UserData.text control.
I have tried using public properties but to no avail. I would rather use public properties, since its cleaner. Here is the code im using to set the property:
Public Property UserSignedInto As String
Get
Return tbUSI.Text
End Get
Set(value As String)
End Set
End Property
Here is my code attempting to call that property on the main form (form1)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
UserData.text = UserSignedInto
End Sub
It doesn't pull anything, the textbox on my main form is blank.
Take a look here:
SCCMReports = New ReportSettings
UserData.text = SCCMReports.UserSignedInto
When was the SCCMReports form ever displayed to the user? Since it was never displayed, its tbUSI.Text value will of course be empty because the user never had an opportunity to enter text.
It sounds like you need a reference to an existing instance of ReportSettings, rather than creating a new instance. Where do you have that existing instance?
If Form1 created the instance in another block of code, store it in a class-level member on Form1 (perhaps called SCCMReportsInstance or something of that nature). When the instance is created, set it to the value of that property and reference that property in your code:
UserData.text = Me.SCCMReportsInstance.UserSignedInto
If the ReportSettings form is instead creating the instance of Form1 then it can pass a reference to itself. You'd still have a property on Form1, it would just be set in the constructor. Something like this:
Sub New(ByVal sccmReportsInstance As ReportSettings)
Me.SCCMReportsInstance = sccmReportsInstance
End Sub
So when initializing the Form1 instance, you'd pass the reference:
Dim form1 As Form1
form1 = New Form1(Me)
form1.Show()
Any way you go about it, you need to access the existing instance of the displayed form in order to access its properties. A new instance would have new versions of those properties and wouldn't have the same values.

When are default form instances created?

The startup sequence and handling of form instances is quite weird in VB.NET. When you refer to a form as for example Form2.Textbox1.Text = "Foo" then the CLR automatically uses the instance of the form that is created in the background and can be directly acessed through My.Forms.Form2.
I am using a WinForms application that starts up through a custom Sub Main(). Here the application is run by calling Application.Run(frmMain).
Since I have multiple forms that needs initilializing I would like to know exactly at which point the real form instances are created. Are they all created at Application.Run or are they only created when I call Form2.Show()? My startup sequence is as follows right now:
Sub Main()
Sub Main() calls Application.Run(frmMain)
frmMain.Load calls frmNotMain.Show()
I can nowwhere find a line like My.Forms.frmNotMain = New frmNotMain, so it's not apparent where the instance is created.
Thank you in advance.
According to MSDN:
When you access Form through My.Forms.Form1, the factory method checks to see if an instance of Form1 is already open. If it is, that instance is returned. Otherwise, an instance of Form1 is created and returned.
So essentially it is created and Sub New called just before it is shown (not created somewhere and held until needed). The link includes this code showing how it creates those default instances:
'Code ... generated by the compiler
Public m_Form1 As Form1
Public Property Form1() As Form1
Get
m_Form1 = Create__Instance__ (Of Form1)(m_Form1)
Return m_Form1
End Get
Set(ByVal Value As Form1)
If Value Is m_Form1
Return
End If
If Not Value Is Nothing Then
Throw New ArgumentException("Property can only be set to Nothing.")
End If
Dispose__Instance__ (Of Form1)(m_Form1)
End Set
End Property
However, you are talking about the default ("weird") instance method which is ill-advised to begin with. This largely exists to provide compatibility with VB6 type code where you did just do myForm.Show() to instance and show a form (and probably for tinkerers who do not really understand instancing or OOP).
Forms are classes and should be treated as such by explicitly creating instances; so, generally:
Dim frm As New frmMain ' NEW creates the instance
frm.Show
You can set a breakpoint on InitializeComponent in the form's Sub New to see when it is invoked. To create a global reference to it, like you might with any other class:
Friend frmMain As MainForm ' no instance yet
Friend myMain As MainClass
Public Sub Main
' do this before any forms are created
Application.EnableVisualStyles()
myMain = New MainClass()
myMain.DoStuff()
frmMain = New MainForm() ' instanced (NEW)
Application.Run(frmMain)
End Sub
Likewise:
Dim frm2 = New frmNotMain ' declare and instance
' short for:
Dim frm2 As frmNotMain ' declare frm2
frm2 = New frmNotMain ' create instance
frm2.Show
In all cases, Sub New for your form(s) would be called when you use the New operator to create a New form. VB tries to make this clear thru the repeated use of New, but with the default instance all that is actually tucked away in the form factory.

Delegates not working in another module

Running into an odd issue with tasks and delegates. Code in question is running under dotNET 4.5.1, VS2013. On the form's code I have a sub that updates a grid, it checks to see if an invoke is required, and if it is it calls a delegate. When a task runs that's called in the same module, it works as expected, no problems. Threaded or not, the grid updates properly.
However, if the same thing is called from another module, the delegate never gets called and the visual component doesn't get updated. Just a watered down bit of pseudocode to clarify..
In the form's module:
Private Delegate Sub DoWhateverDelegate(ByVal _____)
Public Sub DoWhatever(ByVal _____)
If MyComponent.InvokeReqired
Dim Delegated As New DoWhateverDelegate(AddressOf DoWhatever)
Debug.Print("The delegate fired")
Invoke(Delegated, _____)
Else
' .. carry on as usual ..
End If
End Sub
Elsewhere....
Task.Run(Sub()
' .. various things I'd rather not block the UI thread with ..
DoWhatever()
End Sub)
Works fine. I can do Task.Run__ that calls DoWhatever and it's all happy and good. However if I create a task in another module and call DoWhatever, it doesn't fire the delegate and that visual component doesn't update. The code is identical, in the same module it works, in another module it does not.
I'm probably missing something blatantly obvious.. anyone care to point out my mistake? Thanks.
Edit -- just to clarify, that other module is just code, there's only one form in the entire solution. It's created at program startup automatically, there is no other form creation going on.
Should be a thread-specific issue. Check this:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
foo.DoSomething()
End Sub
End Class
The class with the delegate:
Public Class foo
Public Shared Sub DoSomething()
Task.Run(Sub() UpdateText())
End Sub
Public Delegate Sub UpdateTextDelegate()
Public Shared Sub UpdateText()
Dim f = Form1
'Dim f As Form1 = Application.OpenForms("Form1")
If f.InvokeRequired Then
Dim d As UpdateTextDelegate = AddressOf UpdateText
f.Invoke(d)
Else
f.TextBox1.Text = "Hi"
End If
End Sub
End Class
Run the code and the textbox will not be updated. Use the second f=.... (that one that take a reference from OpenForms) and it will be updated.
If you just try to access the default instance and you are outside the UI-thread, a new instance of the form will be created. That means, the content IS updated, but because that form is not shown, you will not see it.
NOTE I do NOT advise to solve your problem, by using OpenForms. I'd advise to correctly instantiate forms!
Add a new module/class to your code:
Module Startup
Public MyForm1 As Form1
Public Sub main()
MyForm1 = New Form1
Application.Run(MyForm1)
End Sub
End Module
Go to project properties -> application. Disable application framework and choose Sub Main as your start object. In the app, access your form via MyForm1 - or whatever you want to name it. Problem should be gone then.

vb.net auto instantiation (forms)

In VB.Net you can show a form without crete an object reference before... vb.net do it to you, but, that "feature" is generating many problems, eg:
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Form3.Show()
End Sub
End Class
Public Class Form3
Inherits System.Windows.Forms.Form
End Class
Is there any way to disable this?
No there is no way to disable that. It is called the default instance. If you don't want to use it - don't use it. I recommend creating a new instance.
Dim f3 As New Form3
f3.Show()
I looking for a solution to do the same and ran across this thread.
Seeing that there is no way to get rid of the default instance, and it would allow you to make the "whoops" of calling the form without an object reference, I just resorted to do this:
''' <summary>
''' This overrided of Sub New is only here to force you to create an object reference. Passing true or false will make no difference.
''' </summary>
Public Sub New(MustInstanciate As Boolean)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
This forces you to create an object reference because it gets rid of the implicit Sub New, having only one constructor which requires a variable, which requires an object reference.
This trick works for me at least. I just thought I would just add it as a solution in case someone else runs into this thread for the same reason I did.