2

I have a WinForms application that contains two SplitContainers. The first SplitContainer spans the entire form and its orientation is horizontal. The second SplitContainer is within the left panel of the first split container and its orientation is vertical. I bound each split container's SplitterDistance property with an application setting so that the position will be saved when the user quits the program. However, this causes strange problems. If I drag the main split container's position and then drag the second split container's position, the first split container jumps back to the original position and the position is not saved. If I remove the second split container everything works fine. I also don't see this problem if the SplitterDistance property is not bound.

Does anybody know what is causing this or how I can fix it?

Update I also figured out now if I remove the property binding from the second split container everything works fine. Even if I manually try to implement this (that is, removing the property binding and add My.Settings.sideDist = SplitContainer2.SplitterDistance in the SplitContainer2.SplitterMoved event), the problem is still present.

I am using vb.net.

The designer generated code:

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.SplitContainer1 = New System.Windows.Forms.SplitContainer()
        Me.SplitContainer2 = New System.Windows.Forms.SplitContainer()
        Me.ListBox1 = New System.Windows.Forms.ListBox()
        Me.ListBox2 = New System.Windows.Forms.ListBox()
        CType(Me.SplitContainer1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SplitContainer1.Panel1.SuspendLayout()
        Me.SplitContainer1.Panel2.SuspendLayout()
        Me.SplitContainer1.SuspendLayout()
        CType(Me.SplitContainer2, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SplitContainer2.Panel1.SuspendLayout()
        Me.SplitContainer2.SuspendLayout()
        Me.SuspendLayout()
        '
        'SplitContainer1
        '
        Me.SplitContainer1.DataBindings.Add(New System.Windows.Forms.Binding("SplitterDistance", Global.WindowsApplication1.My.MySettings.Default, "mainDist", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged))
        Me.SplitContainer1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.SplitContainer1.Location = New System.Drawing.Point(0, 0)
        Me.SplitContainer1.Name = "SplitContainer1"
        '
        'SplitContainer1.Panel1
        '
        Me.SplitContainer1.Panel1.Controls.Add(Me.SplitContainer2)
        '
        'SplitContainer1.Panel2
        '
        Me.SplitContainer1.Panel2.Controls.Add(Me.ListBox2)
        Me.SplitContainer1.Size = New System.Drawing.Size(730, 413)
        Me.SplitContainer1.SplitterDistance = Global.WindowsApplication1.My.MySettings.Default.mainDist
        Me.SplitContainer1.TabIndex = 0
        '
        'SplitContainer2
        '
        Me.SplitContainer2.DataBindings.Add(New System.Windows.Forms.Binding("SplitterDistance", Global.WindowsApplication1.My.MySettings.Default, "sideDist", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged))
        Me.SplitContainer2.Dock = System.Windows.Forms.DockStyle.Fill
        Me.SplitContainer2.Location = New System.Drawing.Point(0, 0)
        Me.SplitContainer2.Name = "SplitContainer2"
        Me.SplitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal
        '
        'SplitContainer2.Panel1
        '
        Me.SplitContainer2.Panel1.Controls.Add(Me.ListBox1)
        Me.SplitContainer2.Size = New System.Drawing.Size(310, 413)
        Me.SplitContainer2.SplitterDistance = Global.WindowsApplication1.My.MySettings.Default.sideDist
        Me.SplitContainer2.TabIndex = 0
        '
        'ListBox1
        '
        Me.ListBox1.Dock = System.Windows.Forms.DockStyle.Fill
        Me.ListBox1.FormattingEnabled = True
        Me.ListBox1.Location = New System.Drawing.Point(0, 0)
        Me.ListBox1.Name = "ListBox1"
        Me.ListBox1.Size = New System.Drawing.Size(310, 49)
        Me.ListBox1.TabIndex = 0
        '
        'ListBox2
        '
        Me.ListBox2.Dock = System.Windows.Forms.DockStyle.Fill
        Me.ListBox2.FormattingEnabled = True
        Me.ListBox2.Location = New System.Drawing.Point(0, 0)
        Me.ListBox2.Name = "ListBox2"
        Me.ListBox2.Size = New System.Drawing.Size(416, 413)
        Me.ListBox2.TabIndex = 0
        '
        'Form1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(730, 413)
        Me.Controls.Add(Me.SplitContainer1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.SplitContainer1.Panel1.ResumeLayout(False)
        Me.SplitContainer1.Panel2.ResumeLayout(False)
        CType(Me.SplitContainer1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.SplitContainer1.ResumeLayout(False)
        Me.SplitContainer2.Panel1.ResumeLayout(False)
        CType(Me.SplitContainer2, System.ComponentModel.ISupportInitialize).EndInit()
        Me.SplitContainer2.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub
    Friend WithEvents SplitContainer1 As System.Windows.Forms.SplitContainer
    Friend WithEvents ListBox2 As System.Windows.Forms.ListBox
    Friend WithEvents SplitContainer2 As System.Windows.Forms.SplitContainer
    Friend WithEvents ListBox1 As System.Windows.Forms.ListBox

End Class
Kritz
  • 7,099
  • 12
  • 43
  • 73

2 Answers2

2

While I advise not setting the DataBindings property of a SplitContainer via the designer file (there are reasons why that property is not exposed to the designer), the real issue is that the application settings are not getting updated. When the user modifies the SplitterDistance all is well, however when the control becomes invalidated, the setting is re-read and applied from the settings which have not changed from their initial value. The simple solution is to save the new value back to the settings. the following code should suffice for you:

''' <summary>
''' Sets the mainDist application setting to the new SplitterDistance
''' </summary>
''' <remarks>http://stackoverflow.com/users/2659234/brandon-b</remarks>
Private Sub SplitContainer1_SplitterMoved(sender As SplitContainer, e As SplitterEventArgs) Handles SplitContainer1.SplitterMoved
    Global.WindowsApplication1.My.MySettings.Default.mainDist = sender.SplitterDistance
End Sub

''' <summary>
''' Sets the sideDist application setting to the new SplitterDistance
''' </summary>
''' <remarks>http://stackoverflow.com/users/2659234/brandon-b</remarks>
Private Sub SplitContainer2_SplitterMoved(sender As SplitContainer, e As SplitterEventArgs) Handles SplitContainer2.SplitterMoved
    Global.WindowsApplication1.My.MySettings.Default.sideDist = sender.SplitterDistance
End Sub
0

Old topic, but I was able to solve this SplitContainer bug(?) by recording location of the Splitter as a decimal of the height of the splitcontainer. So my Settings Save() method looks like this:

Properties.Settings.Default.VertSplitterDistance = (decimal)VertSplitContainer.SplitterDistance / (decimal)VertSplitContainer.Width;
Properties.Settings.Default.Save();

And after the Initialization of the Form, to load the settings on application start:

VertSplitContainer.SplitterDistance = (int)Math.Round(Properties.Settings.Default.HorizontalSplitterDistance * HorizontalSplitContainer.Height, 0);

(This is C#, but should be easily convertible to vb.net...)

CJ K
  • 146
  • 11