Question

I am experiencing a strange behaviour when using RightToLayout layout: My form automatically closes.

I have created a simple project to reproduce the problem:

Create a new VB.NET project in VS2012 and add forms "Form1" and "Form2" to it. Set "Form1" to be the start form.

Then add the following code to "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

Add the following code to "Form2":

Public Class Form2

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

        modControls.setFormRTL(Me)

    End Sub
End Class

Add a module with the name "modControls" to the project. Add the following code to it:

Module modControls

    Public Sub setFormRTL(ByVal uForm As Form)

        uForm.RightToLeft = RightToLeft.Yes

    End Sub

End Module

Without the setFormRTL, my project works perfectly fine, but with it, "Form2" automatically closes down. You can see this because the messagebox is shown.

When I remove the line

        modControls.setFormRTL(Me)

from Form1 load, it works fine again. Yes, I really mean from "Form1", not from "Form2"!!!

Now this is really strange because it should not matter at all because this line is not processed before the dialog is closed. I hope somebody understands what I mean.

Can anybody shed some light on what might be happening here?

Was it helpful?

Solution

Yes, you'll get unexpected behavior if you set the RightToLeft property anywhere other than a control's constructor (in VB.NET parlance, that's the New method).

In fact, the constructor is where you should set all of the properties of a form or control object. If you come from VB 6, it might seem logical to do it in the Load event handler, but that's not idiomatic .NET and, as you've discovered, can cause problems when initializing certain properties.

The technical reason for this is that certain properties (like RightToLeft) can actually only be set on the native window (which is how the Form objects used in the .NET world are implemented behind the scenes) at the time that it is created. When you attempt to change the property, the framework code actually has to destroy and then re-create the native window with the new property values.

Change the code to look like this instead:

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

Speaking of non-idiomatic .NET code:

  1. Methods should all be Pascal cased by convention. That means your setFormRTL method should be named SetFormRtl.

  2. A helper function that sets the properties of an object just seems wrong to me. If anything, that's just bad OO design. If you want this method to be available for all of your Form objects, derive a custom form class and add this method (or even do the desired initialization in the constructor). Either way, all forms that you derive from this custom form object will inherit the functionality. Example:

    Public Class MyCustomForm : Inherits System.Windows.Forms.Form
    
        Public Sub New()
            MyBase.New()
    
            Me.SetRtl()
        End Sub
    
        Public Sub SetRtl()
            Me.RightToLeft = RightToLeft.Yes
        End Sub
    
    End Class
    
    Public Class Form1 : Inherits MyCustomForm
    
        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 : Inherits MyCustomForm
    
        Private Sub Form2_Load(sender As Object, e As EventArgs) Handles Me.Load
    
        End Sub
    
    End Class
    

OTHER TIPS

can you try this? all i am doing here is setting the RTL before the form is displayed.

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

and remove code form load event of form 2

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top