VB.NET绝对奇怪的表单加载行为

时间:2014-04-29 05:37:22

标签: vb.net winforms visual-studio-2012 right-to-left

使用RightToLayout布局时遇到奇怪的行为: 我的表单自动关闭。

我创建了一个简单的项目来重现问题:

在VS2012中创建一个新的VB.NET项目,并向其添加表单“Form1”和“Form2”。 将“Form1”设置为开始表单。

然后将以下代码添加到“Form1”:

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load

        Me.Hide()

        Dim f As New Form2
        f.ShowDialog()

        MessageBox.Show("After dialog closed.")

        modControls.setFormRTL(Me) 'This line causes the Form2 to automatically close. Why??? This line should only be processed AFTER the dialog has been shown and closed

    End Sub
End Class

将以下代码添加到“Form2”:

Public Class Form2

    Private Sub Form2_Load(sender As Object, e As EventArgs) Handles Me.Load

        modControls.setFormRTL(Me)

    End Sub
End Class

将一个名为“modControls”的模块添加到项目中。 将以下代码添加到其中:

Module modControls

    Public Sub setFormRTL(ByVal uForm As Form)

        uForm.RightToLeft = RightToLeft.Yes

    End Sub

End Module

没有setFormRTL,我的项目工作得很好,但有了它,“Form2”会自动关闭。您可以看到这一点,因为会显示消息框。

当我删除该行

        modControls.setFormRTL(Me)

从Form1加载,它再次正常工作。 是的,我的意思是“Form1”,而不是“Form2”!!!

现在这真的很奇怪,因为它根本不重要,因为在关闭对话框之前不会处理这一行。 我希望有人理解我的意思。

有人可以了解这里可能发生的事情吗?

2 个答案:

答案 0 :(得分:3)

是的,如果将RightToLeft属性设置为控件构造函数以外的任何位置,则会出现意外行为(用VB.NET的说法,那就是{{1}方法)。

实际上,构造函数是您应该设置表单或控件对象的所有属性的地方。如果你来自VB 6,那么在New事件处理程序中执行此操作似乎是合乎逻辑的,但这不是惯用的.NET,并且正如您所发现的那样,在初始化某些事件时可能会导致问题属性。

技术原因是某些属性(如Load)实际上只能在本机窗口上设置(这就是.NET世界中使用的RightToLeft对象在后面实现的方式。场景)在创建时。当您尝试更改属性时,框架代码实际上必须销毁然后使用新属性值重新创建本机窗口。

将代码更改为:

Form

说到非惯用的.NET代码:

  1. 方法应该按照惯例进行Pascal。这意味着您的Public Class Form1 Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() modControls.SetFormRtl(Me) End Sub Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load Me.Hide() Dim f As New Form2 f.ShowDialog() MessageBox.Show("After dialog closed.") End Sub End Class Public Class Form2 Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() modControls.SetFormRtl(Me) End Sub Private Sub Form2_Load(sender As Object, e As EventArgs) Handles Me.Load End Sub End Class 方法应命名为setFormRTL

  2. 设置对象属性的辅助函数对我来说似乎不对。如果有的话,这只是糟糕的OO设计。如果希望此方法可用于所有SetFormRtl个对象,则派生自定义表单类并添加此方法(甚至在构造函数中执行所需的初始化)。无论哪种方式,您从此自定义表单对象派生的所有表单都将继承该功能。例如:

    Form

答案 1 :(得分:1)

你可以尝试一下吗?我在这里所做的就是在显示表单之前设置RTL。

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load

        Me.Hide()

        Dim f As New Form2
        modControls.setFormRTL(f)
        f.ShowDialog()

        MessageBox.Show("After dialog closed.")

        modControls.setFormRTL(Me)

    End Sub
End Class

并删除表单2的代码表单加载事件