none
Mirror Contents of Tab Page RRS feed

  • Question

  • I am trying to build an application that needs to mirror its contents when changing to a right-to-left language. The application has a tab control with two tab pages. So far I am able to have the form and the tab control mirror and display in a Right To Left format, but I am not able to have the contents to each tab page for the tab control also display right to left. I am setting each tabPage.RightToLeft = Yes, but still the contents of each tab page is not mirroring into a right to left format. How do you have the contents of the tab page also display in a right to left format?
    Wednesday, May 2, 2018 4:48 AM

Answers

  • Oh I see... well, that is not quite how it works.

    The position of the control will not change, just the alignment of the text within the control.

    If you were to stretch the label to fill the width of the tabpage you would see the text shift.

    However, if you place all of the controls on the tab page into a FlowLayoutPanel, then the positions will change as you desire.  But you'll need to redesign your form.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by Gills5 Wednesday, May 2, 2018 5:33 PM
    Wednesday, May 2, 2018 5:27 PM
    Moderator
  •  Reed's method would probably be the easiest method to accomplish this.  Also,  it is possible to set the WS_EX_LAYOUTRTL extended window style for a tabpage to reposition the controls but,  it has bugs that stop it from being reliable as far as I could find with my testing with it.

     Below is another method which could be used depending on the layout of your controls on the tabpage.  You could set up a method to reverse the X locations of each control on each tabpage depending on their current X locations.  Below is a short example but,  if you have controls that are inside other container controls like GroupBoxes,  Panels,  and such,  you would need to modify the inner loop that iterates through the control to be a recursive loop. 

    Public Class Form1
        Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
            TabControl1.RightToLeft = If(CheckBox4.Checked, RightToLeft.Yes, RightToLeft.No)
            TabControl1.RightToLeftLayout = CheckBox4.Checked
        End Sub
    
        Private Sub TabControl1_RightToLeftLayoutChanged(sender As Object, e As EventArgs) Handles TabControl1.RightToLeftLayoutChanged
            For Each tp As TabPage In TabControl1.TabPages
                For Each ctrl As Control In tp.Controls
                    Dim bnds As Rectangle = ctrl.Bounds
                    If TabControl1.RightToLeftLayout Then
                        If ctrl.Left < (tp.Width - ctrl.Right) Then
                            ctrl.Left = tp.Width - bnds.Width - bnds.Left
                        Else
                            ctrl.Left = tp.Width - ctrl.Right
                        End If
                    Else
                        If ctrl.Left < (tp.Width - ctrl.Right) Then
                            ctrl.Left = tp.Width - ctrl.Right
                        Else
                            ctrl.Left = tp.Width - bnds.Width - bnds.Left
                        End If
                    End If
                Next
            Next
        End Sub
    End Class
     

     


     

    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Wednesday, May 2, 2018 9:06 PM
    • Marked as answer by Gills5 Wednesday, May 2, 2018 9:26 PM
    Wednesday, May 2, 2018 9:04 PM

All replies

  • I'm not entirely sure I follow the effect you are trying to achieve, but, perhaps you just need to loop through all of the controls on the tab page and set the RightToLeft property for each?  Something like:

    For Each c In TabPage1.Controls
       c.RightToLeft = True
    Next


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Wednesday, May 2, 2018 1:03 PM
    Moderator
  • Hi Reed,

    That is the effect I am trying to achieve, but unfortunately setting the RightToLeft setting for each item on the tab page does not seem to have an effect. I have this code for mirroring all of the items on the form itself:

    Private _mirrored As Boolean = False
        <Description("Change to the right-to-left layout."),
        DefaultValue(False), Localizable(True),
        Category("Appearance"), Browsable(True)>
        Public Property Mirrored() As Boolean
            Get
                Return _mirrored
            End Get
            Set(ByVal Value As Boolean)
                If _mirrored <> Value Then
                    _mirrored = Value
                    MyBase.OnRightToLeftChanged(EventArgs.Empty)
                End If
            End Set
        End Property
    
        Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
            Get
                Dim CP As System.Windows.Forms.CreateParams = MyBase.CreateParams
                If Mirrored Then
                    CP.ExStyle = CP.ExStyle Or WS_EX_LAYOUTRTL Or WS_EX_NOINHERITLAYOUT
                End If
                Return CP
            End Get
        End Property
    End Class

    But this doesn't touch the tab control or the contents of the tab page itself(essentially just a bunch of labels and a button). I was able to get the tab control to also flip using: TabControl.RightToLeft = RightToLeft.Yes, but doing that for the individual labels on the tab page doesn't seem to have any effect. Any ideas on why that might be?
    Wednesday, May 2, 2018 4:26 PM
  • Hmm, the following is working as expected for me:

    Private Sub FlipButton_Click(sender As Object, e As EventArgs) Handles FlipButton.Click
        TabControl1.RightToLeft = If(TabControl1.RightToLeft = RightToLeft.Yes, RightToLeft.No, RightToLeft.Yes)
        TabControl1.RightToLeftLayout = Not TabControl1.RightToLeftLayout
    End Sub
    
    When I click the button, everything (tabs at the top of the control and text within any controls on the tab pages) shift from left to right and back again (on subsequent clicks).


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Wednesday, May 2, 2018 4:35 PM
    Moderator
  • Hi Reed,

    Thank you so much for helping me, I really appreciate it. The code you sent does flip all the tabcontrols and tabs themselves, but the contents on the pages are still not flipping.The general idea is for the label in the upper left of the tab page to now appear in the upper right of the tab page, and the button on the lower right of the tab page to appear in the lower left.

    As it is working right now, the tab controls and tabs are switching on the button click, but the label and button on the tab page are not moving. Any ideas on why that might be?

    Wednesday, May 2, 2018 4:47 PM
  • Oh I see... well, that is not quite how it works.

    The position of the control will not change, just the alignment of the text within the control.

    If you were to stretch the label to fill the width of the tabpage you would see the text shift.

    However, if you place all of the controls on the tab page into a FlowLayoutPanel, then the positions will change as you desire.  But you'll need to redesign your form.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    • Marked as answer by Gills5 Wednesday, May 2, 2018 5:33 PM
    Wednesday, May 2, 2018 5:27 PM
    Moderator
  • Perfect! That worked perfectly! Thank you for all the help, you're a hero!
    Wednesday, May 2, 2018 5:34 PM
  • You're welcome, glad we got it figured out. :)

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Wednesday, May 2, 2018 6:01 PM
    Moderator
  • Hi Reed,

    Sorry to keep bothering you, but I am running into an issue with the FlowLayoutPanel. I am trying to move all my controls from the tab page onto the panel, but the controls are all aligning next to each other, starting in the upper left corner and being added right next to the last control added. Is there any way I can arrange these controls in the locations I want, or does the FlowLayoutPanel force the locations of all controls?

    Thanks again for the help

    Wednesday, May 2, 2018 7:42 PM
  • Be sure to check the documentation when you work with a new control for the first time. ;)

    Whenever you add a control to the FlowLayoutPanel, it, in turn, adds a new property to the control called "FlowBreak".  When you set FlowBreak to true, it causes the next control in the container to drop down to a new line.

    Setting FlowBreak to True for all controls will cause them to all stack vertically instead of horizontally.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Wednesday, May 2, 2018 7:49 PM
    Moderator
  • Additionally, you can use the Margin settings on each control to influence the space around each control.

    There might be some limitations to what you can achieve but this is one of those issues where you might have to give a little to get a little.  :)


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Wednesday, May 2, 2018 7:51 PM
    Moderator
  • Oh ok, I had the flow break set up but I didn't have the margins. I think that should get me what I need, but I'll have to play around with it a little bit. Unfortunately the locations of all the controls is very specifically called for so I may have to redesign the whole project. Thanks again for all the help!
    Wednesday, May 2, 2018 8:01 PM
  • If the design requirements are too stringent for this solution you can always write code to move the controls around.  In that case, a TableLayoutPanel may work better because you would (in theory) only have to change the table cell format and/or anchoring of the contained controls.  It would be more work, but sometimes you gotta do what you gotta do. :)

    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Wednesday, May 2, 2018 8:19 PM
    Moderator
  • Perfect, I'll take a look at that too. Thanks again for all the help!
    Wednesday, May 2, 2018 8:26 PM
  •  Reed's method would probably be the easiest method to accomplish this.  Also,  it is possible to set the WS_EX_LAYOUTRTL extended window style for a tabpage to reposition the controls but,  it has bugs that stop it from being reliable as far as I could find with my testing with it.

     Below is another method which could be used depending on the layout of your controls on the tabpage.  You could set up a method to reverse the X locations of each control on each tabpage depending on their current X locations.  Below is a short example but,  if you have controls that are inside other container controls like GroupBoxes,  Panels,  and such,  you would need to modify the inner loop that iterates through the control to be a recursive loop. 

    Public Class Form1
        Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
            TabControl1.RightToLeft = If(CheckBox4.Checked, RightToLeft.Yes, RightToLeft.No)
            TabControl1.RightToLeftLayout = CheckBox4.Checked
        End Sub
    
        Private Sub TabControl1_RightToLeftLayoutChanged(sender As Object, e As EventArgs) Handles TabControl1.RightToLeftLayoutChanged
            For Each tp As TabPage In TabControl1.TabPages
                For Each ctrl As Control In tp.Controls
                    Dim bnds As Rectangle = ctrl.Bounds
                    If TabControl1.RightToLeftLayout Then
                        If ctrl.Left < (tp.Width - ctrl.Right) Then
                            ctrl.Left = tp.Width - bnds.Width - bnds.Left
                        Else
                            ctrl.Left = tp.Width - ctrl.Right
                        End If
                    Else
                        If ctrl.Left < (tp.Width - ctrl.Right) Then
                            ctrl.Left = tp.Width - ctrl.Right
                        Else
                            ctrl.Left = tp.Width - bnds.Width - bnds.Left
                        End If
                    End If
                Next
            Next
        End Sub
    End Class
     

     


     

    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Wednesday, May 2, 2018 9:06 PM
    • Marked as answer by Gills5 Wednesday, May 2, 2018 9:26 PM
    Wednesday, May 2, 2018 9:04 PM
  • That did the trick! Thank you so much for the response and the help!
    Wednesday, May 2, 2018 9:25 PM