问题描述
我已经注意到一些很讨厌的用VB.Net的治疗WinForm的对象。
这已经丢弃几个小时我们的时间。它只会变得更糟,因为我们有我们更多的VB6程序员用来做这样的事情,并autoconverted code从VB6带来的结构直冲了过来。
下面是一个可以接受的方式做的事情:
暗淡FormInstance作为新FormClassName
如果FormInstance.ShowDialog()= DialogResult.OK然后
TheAnswer = FormInstance.TextBox1.Text
ENDIF
但是,它允许这样的:
如果FormClassName.ShowDialog()= DialogResult.OK然后
TheAnswer = FormClassName.TextBox1.Text
ENDIF
记住,属性和方法不能共享。谈到应用程序框架的无所谓。看来,在幕后,VB实例形式的全局副本,并重新路由,该语法来全球基准。你可以想象这造成十分一座现代化计划的破坏!通常,开发商会扔在,否则我们就会错过清理从转换一些模糊的code(是的,我找的这个现在,这样有利于)。
任何设置,我可以做,使这个抛出一个错误信息,如引用到非共享成员需要一个对象引用
,喜欢它应该?
这里的解决方案:
我选择选择jmoreno的答案,因为他指出罪魁祸首对我来说: My.Forms
。修复这是因为把这个模块中的一样简单:
命名空间My.MyProject.MyForms
最终命名空间
然后你得到我上面提到的确切的错误。就像你应该。如果需要,对于传统应用程序(一件好事),那么不这样做!我想Gserg可能只是VB扑(有趣,但没有帮助),但他提到的这一切的时候了,因为我找到了答案,但我们和好如初约VB不吸,除非你只是不熟悉它。
请注意,如果你使用的应用程序框架,你会得到你不想在application.designer错误。解决方法:
受保护的覆盖子OnCreateMainForm()
''//是:Me.MainForm = Global.WindowsApplication2.Form1
Me.MainForm =新Form1中
结束小组
我希望这将是它的任何不良副作用!
JMoreno的反思等。
以上是如此简单,我讨厌建议别的,但如果你是好奇,这里有改进上code:(1)增加反射省略不必硬code在每个形成你做出和(2)使自动执行(以在程序启动时只需一个电话到这个分)。只要把这个模块中的:
公用Sub FixMyForms()
对于每一个PI作为System.Reflection.PropertyInfo在的GetType(My.MyProject.MyForms).GetProperties
昏暗的OBJ作为对象= pi.GetValue(My.Forms,为Nothing)
如果TypeOf运算obj是表格然后
AddHandler的CTYPE(OBJ,表格).Load,AddressOf抱怨
结束如果
下一个
结束小组
私人小组抱怨(BYVAL发件人为对象,BYVALË作为System.EventArgs)
MSGBOX(错!)
结束小组
八九不离十。你可以创建一个函数或覆盖的ShowDialog来检查My.Forms集合,看看目前的情况是在它,如果它被抛出的异常。这里没有可以用来prevent它被使用的设置。
编辑:加样code说明概念(用异常的嘟嘟声代替)
共享功能FormIsInMyForms(窗体名称作为字符串,FRM作为表)
如果窗体名称=Form1的那
如果frm.Equals(Form1中)然后
返回TRUE
其他
返回False
结束如果
结束如果
返回False
端功能
公共重载子的ShowDialog()
如果FormIsInMyForms(Form1的,我的)然后
嘟()
结束如果
MyBase.ShowDialog()
结束小组
这样通过反射一样的东西是留给作为练习读者...:)
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
Sorta. You could create a function or override ShowDialog that checks the My.Forms collection to see if the current instance is in it and if it is thrown an exception. There's not a setting that can be used to prevent it from being used.
EDIT: adding sample code illustrating the concept (using a beep instead of an exception).
Shared Function FormIsInMyForms(formName As String, frm As Form)
If formName = "Form1" Then
If frm.Equals(Form1) Then
Return True
Else
Return False
End If
End If
Return False
End Function
Public Overloads Sub ShowDialog()
If FormIsInMyForms("Form1", Me) Then
Beep()
End If
MyBase.ShowDialog()
End Sub
Doing the same thing via reflection is left as an exercise for the reader... :)
这篇关于因为这VB6般的气味,这VB.NET允许,到错误,而不是:WinFormType.InstanceProp =值[无效My.Forms]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!