I have notice something very obnoxious with VB.Net's treatment of Winform objects.
This has trashed several hours of our time. It will only get worse as we have more of our VB6 programmers that are used to doing things like this, and autoconverted code which brings the construct straight over from vb6.
Here is an acceptable way to do things:
Dim FormInstance as New FormClassName
If FormInstance.ShowDialog() = DialogResult.OK then
TheAnswer = FormInstance.TextBox1.Text
EndIf
However, it allows this:
If FormClassName.ShowDialog() = DialogResult.OK then
TheAnswer = FormClassName.TextBox1.Text
EndIf
Bear in mind, the properties and methods are not Shared. Turning of Application Framework doesn't matter. It seems that behind the scenes, VB instantiates a global copy of the form, and re-routes this syntax to that global reference. You can imagine the havoc this wreaks on a modern program! Often a developer will throw it in or we'll miss cleaning up some obscure code from conversion (yes, I am looking for this now, so that helps).
Any setting I can make to cause this to throw an error message, e.g., Reference to a non-shared member requires an object reference
, like it ought to?
Here's the solution:
I chose to select the answer of jmoreno because he pointed out the culprit for me: My.Forms
. Fixing it was as easy as putting this in a module:
Namespace My.MyProject.MyForms
End Namespace
Then you get the exact error I mentioned above. Just like you should. If you need that for legacy apps (a good thing), then don't do this! I thought Gserg might just be VB bashing (fun but not helpful) but he mentioned all this right away, and since I found the answer, there we're good again about vb not sucking unless you are just unfamiliar with it.
Note if you use the application framework you'll get an error you don't want in application.designer. The fix:
Protected Overrides Sub OnCreateMainForm()
''//was: Me.MainForm = Global.WindowsApplication2.Form1
Me.MainForm = New Form1
End Sub
Hopefully that would be it for any bad side effects!
JMoreno's reflection, etc.
The above is so simple that I'd hate to suggest anything else, but if you are curious, here are improvements on that code to (1) add reflection to omit having to hardcode in each form you make and (2) make it automatically enforcing (with just one call to this sub at program startup). Just put this in a module:
Public Sub FixMyForms()
For Each pi As System.Reflection.PropertyInfo In GetType(My.MyProject.MyForms).GetProperties
Dim obj As Object = pi.GetValue(My.Forms, Nothing)
If TypeOf obj Is Form Then
AddHandler CType(obj, Form).Load, AddressOf Complainer
End If
Next
End Sub
Private Sub Complainer(ByVal sender As Object, ByVal e As System.EventArgs)
MsgBox("WRONG!")
End Sub
See Question&Answers more detail:
os