VB.NET WinForms 2019跨窗体获取文本框值问题求助
解决VB.NET WinForms跨窗体获取控件值的问题
我升级VB6项目到VB.NET 2019的时候,也遇到过一模一样的问题!VB6的窗体全局单例模式太容易让人形成思维定式,换到VB.NET的面向对象模型就容易踩坑,我给你捋捋原因和解决办法:
为什么你现在的代码拿不到值?
VB6里的窗体是全局单例,不管你怎么调用Form1,都是同一个已经打开的窗体实例。但VB.NET里不一样,每次执行Dim Foo As New frmNonSerialize都会创建一个全新的窗体实例——这个新实例里的文本框根本没被用户输入过内容,自然返回空字符串。
靠谱的解决方法
方法1:传递窗体引用(最符合面向对象原则)
这是我最常用的方法,核心是把已打开的窗体实例传递给需要访问它的窗体,而不是新建实例:
- 在需要获取数据的窗体(比如
frmNonSerialize)里,添加一个字段和带参数的构造函数:Private _mainForm As frmMain ' 假设你的主窗体是frmMain ' 带参数的构造函数 Public Sub New(mainForm As frmMain) InitializeComponent() ' 必须保留这个初始化方法 _mainForm = mainForm End Sub - 打开
frmNonSerialize的时候,把当前主窗体的实例传进去:' 在frmMain里打开frmNonSerialize的代码 Dim foo As New frmNonSerialize(Me) foo.Show() - 现在在
frmNonSerialize里就能直接访问主窗体的内容了,推荐封装成属性(不要直接暴露控件,更安全):
先在frmMain里加一个只读属性:
然后在Public ReadOnly Property WorkOrderNo As String Get Return txtWorkOrderNo.Text End Get End PropertyfrmNonSerialize里调用:MsgBox(_mainForm.WorkOrderNo)
方法2:从应用程序的开放窗体集合中获取实例
如果不想传递引用,可以直接从Application.OpenForms里找到已经打开的窗体实例:
' 查找已打开的frmMain实例 Dim targetForm As frmMain = DirectCast(Application.OpenForms("frmMain"), frmMain) If targetForm IsNot Nothing Then MsgBox(targetForm.WorkOrderNo) ' 同样用封装的属性更稳妥 Else MsgBox("主窗体未打开") End If
⚠️ 注意:要确保窗体的Name属性和代码里的一致,而且这种方法依赖窗体的运行状态,不如传递引用可靠。
方法3:用全局静态类共享数据
如果多个窗体都需要共享这个值,推荐用静态类存储:
- 新建一个公共类:
Public Class AppGlobalData ' 静态属性存储工单编号 Public Shared Property CurrentWorkOrderNo As String End Class - 在主窗体的文本框内容变化时更新这个值:
Private Sub txtWorkOrderNo_TextChanged(sender As Object, e As EventArgs) Handles txtWorkOrderNo.TextChanged AppGlobalData.CurrentWorkOrderNo = txtWorkOrderNo.Text End Sub - 其他窗体直接调用静态属性:
MsgBox(AppGlobalData.CurrentWorkOrderNo)
关键注意点
- 不要直接把控件的
Modifiers改成Public来访问,这会破坏封装性,后期维护容易出问题,用属性封装更合理。 - 永远记住:VB.NET里
New出来的窗体是全新的实例,和用户正在操作的窗体不是同一个!
内容的提问来源于stack exchange,提问作者NaN
相关产品推荐
相关产品推荐

