关闭和重新打开声明为公开的表单的正确方法是什么?

问题描述

我的问题与 Microsoft Excel 的 COM 加载项有关。用例如下: 1. 用户单击功能区上的加载项按钮。 2. 出现一个表格窗口。 3. 用户与表单窗口交互并单击“确定”按钮。 4. 生成各种报表,同时表单窗口上的进度条显示进度。 5. 流程结束时,表单窗口关闭

该过程在第一次运行时按设计工作,但在表单窗口关闭后,无法启动新的“会话”。从用户的角度来看,加载项按钮变得无响应。从 Visual Studio 以调试模式运行时,再次单击加载项按钮会生成错误消息:“无法访问已处理的对象。”

显然,我将所有内容连接起来的方式有问题,但我无法找到有关如何正确执行此操作的简单描述。这是我所拥有的:

在公共类中声明了许多公共(或“全局”变量);表单也在此处声明和实例化:

Public Class GlobalVariables

        Public Shared FormInstance As New MyFormDesign

End Class

将表单声明为公共对象的原因是能够从各种不同的子和函数发送进度值。 GlobalVariables 类由所有需要它的模块导入。

功能区按钮后面是一行代码

FormInstance.Show()

单击按钮实例化并按预期显示表单。为了简单起见,我们可以忽略大部分代码;只需单击“取消”按钮就会触发问题。 “取消”按钮背后的代码很简单:

Me.Close()
GC.Collect()

关闭表单后,根据上面引用的错误消息,无法再创建新实例。

我不太明白这里发生了什么,但在我看来,GlobalVariables 类一旦创建,就会一直持续到 Excel 会话结束。如果这是正确的,那么问题大概可以通过在标准模块中实例化表单来解决。加载项不会尝试恢复已处理的表单,而是在用户每次单击按钮时创建一个新实例。但是如果我走那条路,我就无法弄清楚如何将其他潜艇的进度值发送回表单。好像是第 22 条军规。

必须有一种方法来 (a) 将表单创建为公共对象,以及 (b) 每次运行加载项时创建和销毁一个新实例。对?我做错了什么?

解决方法

这是一段漫长的旅程,但我终于找到了如何构建我的问题中描述的功能。我会在这里发布答案,因为它将来可能会帮助其他人。

挑战在于将表单声明为 Public 以使其在整个项目中都可以访问,以便子项和函数可以将进度更新发送回表单。

问题是,当按照我的问题中的描述声明和实例化表单时,每个 Excel 会话只能创建一次。

解决方案是将表单声明为 Public 而不实例化它,然后通过 Public ReadOnly Property 访问它。

首先,将 FormInstance 声明为公共变量而不实例化它:

Public FormInstance As MyFormDesign

其次,定义一个 Public ReadOnly Property。这建立了一种调用表单的方法:

Public ReadOnly Property CallMyForm() As MyFormDesign    
    Get
        Return FormInstance
    End Get
End Property

第三,功能区按钮的 Click 事件实例化并显示表单:

Private Sub Button1_Click(sender As Object,e As RibbonControlEventArgs) Handles Button1.Click

    FormInstance = New MyFormDesign
    FormInstance.Show()

End Sub

现在,每次单击功能区按钮时都会创建一个新的表单实例,但仍然可以通过 CallMyForm 属性访问该表单。

代替...

FormInstance.BackgroundWorker1.ReportProgress(i)

...我们将使用:

CallMyForm.BackgroundWorker1.ReportProgress(i)

这解决了问题中提出的难题。