【问题标题】:VB.NET 2019 Open a form from another formVB.NET 2019 从另一个表单打开一个表单
【发布时间】:2020-08-04 02:55:50
【问题描述】:

我知道这似乎是一个相当普遍的话题,应该从之前的帖子中得到解决。但是我遇到的情况似乎仍然没有在线解决方案: 我有一个名为ExpenseEntry 的表单,其中有一个名为Public Sub OpenVoucher 的子过程。 我想从另一个表单中调用这个子,我使用以下代码:

        Dim ExpForm As New ExpenseEntry
         ExpForm.Show()
        ExpForm.OpenVoucher()

虽然这工作得很好,但问题是每次我单击按钮时,都会启动一个 ExpenseEntry 的新窗口。根据我设计应用程序的方式,不允许重复窗口,一次只能使用一个窗口。 我尝试了各种方法来限制一种以上的形式,例如使用变量来控制形式,但这会引起其他问题。 如果我使用Application.OpenForms 但仍然无法解决问题。 我之前在以下链接中对此进行了查询: Textbox not refreshing

我正在使用 VB.NET 2019,它不允许启动像 Form.Show 这样的表单的默认实例。我知道这是不好的做法,但在 VB.NET 2017 之前它更容易管理。

现在通过创建一个表单变量并启动它会创建一个无限循环,在该循环中我不能只在单个线程上运行一个表单实例。

【问题讨论】:

    标签: vb.net winforms singleton


    【解决方案1】:

    真正简单的处理方法是使用表单类型的默认实例。在 VB 中,自 2005 年以来,每种表单类型都有一个默认实例,您可以通过类型名称访问该实例。 Read here 了解更多信息。在你的情况下,你可以这样做:

    'Display the form if it is not already displayed.
    ExpenseEntry.Show()
    
    'Activate the form if it is already displayed.
    ExpenseEntry.Activate()
    
    'Do the deed.
    ExpenseEntry.OpenVouncher()
    

    也就是说,默认实例有点狡猾。它们确实使初学者能够在某些情况下从项目中的任何地方访问表单,但它们也有可能导致问题的限制。但最重要的是,它们通过将表单与其他类型区别对待来帮助阻止您学习正确的 OOP。如果您想按照适当的开发人员的方式执行此操作,那么只需声明一个变量来引用表单的当前实例:

    Private expenseEntryDialogue As ExpenseEntry
    

    当需要使用表单时,您只需检查该变量是否引用了一个可用的实例,如果是则使用它,否则创建一个新实例:

    If expenseEntryDialogue Is Nothing OrElse expenseEntryDialogue.IsDisposed Then
        expenseEntryDialogue = New ExpenseEntry
    End If
    
    expenseEntryDialogue.Show()
    expenseEntryDialogue.Activate()
    expenseEntryDialogue.OpenVoucher()
    

    第三种选择是实现您自己的单例,即只能有一个实例的类型。你可能不会在 VB 中这样做,因为默认实例基本上是一个特定于线程的单例,并且会更自动地执行,但如果你愿意,你可以这样做:

    Public Class ExpenseEntry
    
        Private Shared _instance As ExpenseEntry
    
        'The one and only instance of the type.
        Public Shared ReadOnly Property Instance As ExpenseEntry
            Get
                If _instance Is Nothing OrElse _instance.IsDisposed Then
                    _instance = New ExpenseEntry
                End If
    
                Return _instance
            End Get
        End Property
    
        'The constructor is private to prevent external instantiation.
        Private Sub New()
            ' This call is required by the designer.
            InitializeComponent()
    
            ' Add any initialization after the InitializeComponent() call.
        End Sub
    
    End Class
    

    然后是这个:

    ExpenseEntry.Instance.Show()
    ExpenseEntry.Instance.Activate()
    ExpenseEntry.Instance.OpenVoucher()
    

    【讨论】:

    • 没错,但我在 VB.NET 2019 中找不到 Form.Show 选项。
    • 没什么可找的。您输入表单类的名称,输入一个点,然后输入“show”。
    • 亲爱的@jmcilhinney 非常感谢您解决了这个问题。在我在类级别声明变量后,您展示的第二个选项非常有效。但是,我也尝试了ExpenseEntry.Show 方法,但它在下方弹出一条红线,错误显示为Reference to a non-shared members requires an object reference。请有空的时候看看。该项目也无法编译该行。
    • @KhalidKagzi 将类成员方法定义为Shared 或创建这样的实例:Dim x As New MyClass 并通过x.Method() 访问该方法。您不能按照 OOP 的规则直接访问该方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-25
    相关资源
    最近更新 更多