使用旧对象实例/以前的对象实例

时间:2013-07-16 15:13:27

标签: vb.net

在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时,没有任何反应。我没有得到任何错误。请帮忙。提前谢谢。

3 个答案:

答案 0 :(得分:2)

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

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

将此行放在Dim mainmenu As New MainMenu之后:

mainmenu.Show()

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

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

解决方案2:遵循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,但由于默认实例,这很容易让人困惑。编译器使用上下文来确定我们是在讨论类本身还是类的默认实例...)使用classname仅在引用默认静态实例时有效,如解决方案1 ​​中那样。

此解决方案的吸引人之处在于您可以同时使多个MainMenu实例处于活动状态。所以你可以把它放在:

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

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

<强>摘要

为什么有那么多方法?

嗯,第一种方法是为了吸引VB6程序员加入VB.NET,因为这是在VB6中完成的!准确地说,可以在VB6中以这种方式完成,但是一些半脑的程序员仍然选择遵循方法3.但是默认的实例方法是如此广泛,因为它对于偶然来说非常容易程序员使用 - 特别是那些在VBA内使用它的外行!

在某些情况下,第二种方法是首选,但在其他情况下则不是。它是Singleton设计模式的简单实现。查看Douglas Barbie的答案中的链接,以获得对它的正确解释和Java中的一些示例。它列出了你需要使用它的所有时间的一个很好的总结 - 一个只应该有一次实例的记录器,一个配置加载器,一个工厂或其他实例生成器 - 这些可能超出了你的范围,但可能只是考虑一下Microsoft Office中的“打印”对话框。一次只需打开一个打印窗口。这是一个很好的例子。你的代码是否需要这个?遵循该模式允许此行为,但是我在示例中添加了一些其他配置。如果应用程序足够简单,它可能不需要它。

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

最后,如果你是小规模的编码,那就是你可靠的工作。

答案 1 :(得分:1)

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

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

编辑:在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

答案 2 :(得分: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()