2

在 Visual Basic 2008 Express 中,我想引用一个表单。但是,当我输入时Dim mainmenu as New MainMenu,这会创建一个新实例。当我想通过使用表单 2 中的按钮更改表单主菜单中的标签时,我必须执行以下操作:

    Dim mainmenu As New MainMenu
    Dim pitchint As Integer
    pitchint = Val(Pitch_txt.Text) 'simple way will filter out trailing non-numerics input
    If pitchint > 720 Then
        pitchint -= 720
    ElseIf pitchint > 360 Then
        pitchint -= 360
    End If

    Pitch_txt.Text = pitchint '<--put this line here will solve your "070" issue
    mainmenu.Pitchlbl.Text = pitchint
    If Pitch_txt.Text.Length <> 0 Then
        If Pitchlbl.Text <> Pitch_txt.Text Then
            Pitchlbl.Text = Pitch_txt.Text
        End If
    End If

    Dim yawint As Integer
    yawint = Val(Yaw_txt.Text) 'simple way will filter out trailing non-numerics input
    If yawint > 90 Then
        yawint -= 90
    End If
    If yawint < -90 Then
        yawint += 90
    End If

    Yaw_txt.Text = yawint '<--put this line here will solve your "070" issue

    If Yaw_txt.Text.Length <> 0 Then
        If Yawlbl.Text <> Yaw_txt.Text Then
            Yawlbl.Text = Yaw_txt.Text
        End If
    End If

这将创建表单主菜单的新实例。然后,当我插入行mainmenu.Yawlbl.Text = yawintmainmenu.Pitchlbl.Text = pitchint时,什么也没有发生。我没有得到任何错误。请帮忙。提前致谢。

4

3 回答 3

2

我的解决方案被错误地描述了,并且对回答这个问题的各种可能方法存在一些混淆,所以我编辑了我的原始帖子,以比较和对比本页详细讨论的三种主要方法。

解决方案 1:使用 VB.NET 默认表单实例

将此行放在后面Dim mainmenu As New MainMenu

mainmenu.Show()

您可能会有两个 MainMenu 表单。这是因为 VB 允许您仅通过使用其类名来引用表单的静态实例。所以你可以说 ie MainMenu.Property = value,它会在 VB 创建的静态实例上运行。

尝试删除该行Dim mainmenu As New MainMenu。这可能是您需要做的所有事情(只要您 Show() 表单),因为您将引用与类名相同。

方案二:遵循Singleton设计模式(简化版,无线程安全)

单例设计模式确保一个类只能有一个实例。将此代码放入您的 MainMenu 肯定会导致屏幕上出现一些错误。

Public Class MainMenu

    ' static (shared) instance of this class
    Private Shared _instance As MainMenu

    ' function which returns the static instance
    ' with lazy initialization (constructor is called once GetInstance is 
    Public Shared Function GetInstance() As MainMenu
        If _instance Is Nothing Then
            _instance = New MainMenu()
        End If
        Return _instance
    End Function

    ' private constructor to restrict instantiation of this class (only allowed in GetInstance)
    Private Sub New()
        ' This call is required by the designer.
        InitializeComponent()
        ' Add any initialization after the InitializeComponent() call.

    End Sub

    ' all the rest of your original MainMenu code here

End Class

修复错误的方法是使用一个变量来保存对 MainMenu 实例的引用。简单地说,在你使用表格之前,mainmenu用一个变量替换,比如:myMainMenu

Dim myMainMenu As MainMenu = MainMenu.GetInstance()
myMainMenu.Show()

解决方案 3:创建您自己的实例

解决方案 1解决方案 3之间存在差异。在解决方案 1中,如果您只使用默认实例,您将只有一个表单实例。此解决方案允许您拥有任意数量的实例!你可能不需要这个,但是这里......

您将再次创建一个名为 myMainMenu 的 MainMenu 新实例,但这次您直接调用构造函数。

Dim myMainMenu As New MainMenu()
myMainMenu.Show()

无论您在何处使用名称调用表单,都将其mainmenu替换为myMainMenu. 我有没有提到我们称它为 myMainMenu 而不是 mainmenu,因为我们不想使用与类名相同的名称?(VB 不区分大小写,所以mainmenu= MainMenu,但由于默认实例,这很容易混淆。编译器使用上下文来确定我们是在谈论类本身还是类的默认实例......)使用类名仅在以下情况下有效您引用解决方案 1中的默认静态实例。

这个解决方案的吸引人之处在于您可以同时拥有多个 MainMenu 实例。所以你可以把它放在后面:

Dim myMainMenu2 As New MainMenu()
myMainMenu2.Show()

瞧,您打开了两个 MainMenu。但你可能不需要两个!

概括

为什么有这么多方法?

好吧,添加第一种方法是为了吸引 VB6 程序员使用 VB.NET,因为这就是在 VB6 中完成的方式!准确地说,在VB6中也可以这样,但是一些脑残的程序员还是选择了方法3。但是默认的实例方法之所以如此普遍,是因为它对于普通程序员来说非常容易使用——尤其是所有那些外行在 VBA 中使用它!

第二种方法在某些情况下是优选的,但在其他情况下不是。它是单例设计模式的简单实现。查看 Douglas Barbie's answer 中的链接,以获得对它的体面解释以及 Java 中的一些示例。它列出了你需要使用它的所有时间的一个很好的总结——一个应该只有一次实例的记录器、一个配置加载器、一个工厂或其他实例生成器——这些可能超出了你的范围,但也许只是想想Microsoft Office 中的打印对话框。一次只需要打开一个打印窗口。这是一个很好的例子。你的代码需要这个吗?遵循模式允许这种行为,但我在示例中放置了一些额外的配置。如果应用程序足够简单,它可能不需要它。

第三个是面向对象编程的典型示例(了解 OOP 是一个很好的起点;仅此一项知识就可以为您提供在未来解决此类问题的工具)。它使用您创建的名为 MainMenu 的类,并可能使用该类的多个实例,称为objects。这样做的一个优点是您可以拥有同一个类的两个对象实例,但这些对象具有不同值的属性。想想类的两个实例Car,一个有Car.Make = "Ford",另一个Car.Make = "Chevy". 这两款车,但它们的属性值不同。这与前两个的不同之处仅在于您可以拥有多个实例。如果我们想获得技术,您可以合并解决方案 1 和 3,并使用默认实例并制作您自己的实例,但几乎所有讨论它的人都会警告这一点(谷歌“VB.NET 表单默认实例”以获取更多信息)那件事)。

最后,如果你在小范围内编写代码,那么它对你来说是可靠的。

于 2013-07-16T15:49:20.090 回答
1

查看单例模式:http ://www.oodesign.com/singleton-pattern.html

确保您从不实例化多个 MainMenu 表单实例,然后在需要时引用该表单。您可能必须在更大的范围内实例化它,例如“Main”Sub(或任何与 C# 中的 public static void Main() 等效的 VB)。

编辑:在 VB Windows 窗体项目中,如果您不喜欢禁用应用程序框架,您仍然可以从您的启动窗体中实例化任何其他窗体。如果 MainMenu 是您的启动窗体,那么请务必将 MainMenu 设置为 Form2 的所有者。所以它可能看起来像:

Public Class MainMenu

  Public Sub Foo()
    ' This is wherever you instantiate Form2
    Dim frm2 As New Form2()
    ' There are a few ways to declare frm2's owner:
    frm2.Owner = Me
    frm2.Show(Me)
  End Sub
End Class

然后在 Form2 中:

Public Class Form2
  Private Sub Form2_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Dim pitchint As Integer
    pitchint = Val(Pitch_txt.Text) 'simple way will filter out trailing non-numerics input
    If pitchint > 720 Then
        pitchint -= 720
    ElseIf pitchint > 360 Then
        pitchint -= 360
    End If

    Pitch_txt.Text = pitchint '<--put this line here will solve your "070" issue

    ' refer to MainMenu as Form2's owner:
    Me.Owner.Pitchlbl.Text = pitchint

    ' Etc...
  End Sub
End Class
于 2013-07-16T15:34:20.283 回答
0

您需要将对 MainMenu 表单的引用传递给 Form2。所以 Form2 可能看起来像这样(代码仅用于说明目的。不完整):

Public Class Form2
    'This will hold a reference to the MainMenu instance
    Private mainMenuForm As MainMenu

    Public Sub New(parent As MainMenu)
        mainMenuForm = parent
    End Sub

    Private Sub SomeMethod()
        mainmenuForm.Pitchlbl.Text = "Some new value"
    End Sub
End Class

然后在需要显示Form2的时候在MainMenu窗体中:

Dim frm2 As New Form2(Me)     'Pass the reference to the current MainMenu form to Form2
frm2.Show()
于 2013-07-17T15:30:28.377 回答