Search code examples
c#winformsuser-controls

Margin is not being applied


I have a user control that I need to manually resize during runtime, although I would like the margin to be applied. I found, from link 1 below, that for the margin to work the AutoSize property needs to be set to true. Although, since I need to manually resize the control during runtime, the AutoSize property needs to be false to my understanding.

The user control (Accordion) contains a horizontal split panel where the first panel contains a button and the second panel contains a Panel control. In the image below you can see multiple "Accordions" which, in the picture, is one of the buttons. The Accordions are docked at the top of the container. The intent is when I click on the button it resizes and shows the "contents panel" and the contents panel's control. My problem is that setting the User Control's margin property does not cause them to automatically distance themselves from the other controls nor the container they are in.

enter image description here

Link 1: WinForm Bottom Margin Property Doesn't Do Anything

Hopefully some useful chunks of what I'm working with.

namespace CustomControls
{
partial class Accordion
{
    /// <summary> 
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Component Designer generated code

    /// <summary> 
    /// Required method for Designer support - do not modify 
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.split = new System.Windows.Forms.SplitContainer();
        this.ToggleCollapse = new System.Windows.Forms.PictureBox();
        this.MainButton = new System.Windows.Forms.Button();
        this.contentsPanel = new System.Windows.Forms.Panel();
        ((System.ComponentModel.ISupportInitialize)(this.split)).BeginInit();
        this.split.Panel1.SuspendLayout();
        this.split.Panel2.SuspendLayout();
        this.split.SuspendLayout();
        ((System.ComponentModel.ISupportInitialize)(this.ToggleCollapse)).BeginInit();
        this.SuspendLayout();
        // 
        // split
        // 
        this.split.Dock = System.Windows.Forms.DockStyle.Fill;
        this.split.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
        this.split.IsSplitterFixed = true;
        this.split.Location = new System.Drawing.Point(0, 0);
        this.split.Margin = new System.Windows.Forms.Padding(3, 3, 3, 10);
        this.split.Name = "split";
        this.split.Orientation = System.Windows.Forms.Orientation.Horizontal;
        // 
        // split.Panel1
        // 
        this.split.Panel1.Controls.Add(this.ToggleCollapse);
        this.split.Panel1.Controls.Add(this.MainButton);
        this.split.Panel1MinSize = 0;
        // 
        // split.Panel2
        // 
        this.split.Panel2.Controls.Add(this.contentsPanel);
        this.split.Size = new System.Drawing.Size(663, 488);
        this.split.SplitterDistance = 40;
        this.split.TabIndex = 0;
        // 
        // ToggleCollapse
        // 
        this.ToggleCollapse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
        this.ToggleCollapse.BackColor = System.Drawing.SystemColors.ActiveCaption;
        this.ToggleCollapse.Enabled = false;
        this.ToggleCollapse.Image = global::CustomControls.Properties.Resources.TrianglePointer;
        this.ToggleCollapse.Location = new System.Drawing.Point(621, 13);
        this.ToggleCollapse.Name = "ToggleCollapse";
        this.ToggleCollapse.Size = new System.Drawing.Size(39, 24);
        this.ToggleCollapse.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
        this.ToggleCollapse.TabIndex = 0;
        this.ToggleCollapse.TabStop = false;
        // 
        // MainButton
        // 
        this.MainButton.AutoEllipsis = true;
        this.MainButton.BackColor = System.Drawing.SystemColors.ActiveCaption;
        this.MainButton.Dock = System.Windows.Forms.DockStyle.Fill;
        this.MainButton.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
        this.MainButton.FlatAppearance.BorderSize = 3;
        this.MainButton.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
        this.MainButton.Font = new System.Drawing.Font("Verdana", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        this.MainButton.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
        this.MainButton.Location = new System.Drawing.Point(0, 0);
        this.MainButton.Name = "MainButton";
        this.MainButton.Size = new System.Drawing.Size(663, 40);
        this.MainButton.TabIndex = 0;
        this.MainButton.Text = "Accordion Activator";
        this.MainButton.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
        this.MainButton.UseVisualStyleBackColor = false;
        this.MainButton.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MainButton_MouseDown);
        this.MainButton.MouseEnter += new System.EventHandler(this.MainButton_MouseEnter);
        this.MainButton.MouseLeave += new System.EventHandler(this.MainButton_MouseLeave);
        this.MainButton.MouseUp += new System.Windows.Forms.MouseEventHandler(this.MainButton_MouseUp);
        // 
        // contentsPanel
        // 
        this.contentsPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
        this.contentsPanel.Dock = System.Windows.Forms.DockStyle.Fill;
        this.contentsPanel.Location = new System.Drawing.Point(0, 0);
        this.contentsPanel.Name = "contentsPanel";
        this.contentsPanel.Size = new System.Drawing.Size(663, 444);
        this.contentsPanel.TabIndex = 0;
        this.contentsPanel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Panel_MouseDown);
        this.contentsPanel.MouseLeave += new System.EventHandler(this.Panel_MouseLeave);
        this.contentsPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Panel_MouseMove);
        this.contentsPanel.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Panel_MouseUp);
        // 
        // Accordion
        // 
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;
        this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        this.Controls.Add(this.split);
        this.DoubleBuffered = true;
        this.Margin = new System.Windows.Forms.Padding(3, 3, 3, 10);
        this.Name = "Accordion";
        this.Size = new System.Drawing.Size(663, 488);
        this.split.Panel1.ResumeLayout(false);
        this.split.Panel2.ResumeLayout(false);
        ((System.ComponentModel.ISupportInitialize)(this.split)).EndInit();
        this.split.ResumeLayout(false);
        ((System.ComponentModel.ISupportInitialize)(this.ToggleCollapse)).EndInit();
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.SplitContainer split;
    private System.Windows.Forms.Button MainButton;
    private System.Windows.Forms.PictureBox ToggleCollapse;
    protected System.Windows.Forms.Panel contentsPanel;
}
}

This is when and how I manually resize

       public bool Collapsed
       {
        get
        {
            return split.Panel2Collapsed;
        }
        set
        {
            Freeze(true);
            if (Dock == DockStyle.Fill && this.DesignMode)
            {
                if (firstResize)
                {
                    if (value)
                        this.Parent.Height = MainButtonHeight;
                    else
                        this.Parent.Height = ExpandedHeight;
                }
                else
                {
                    if (value)
                        CollapseAnimation(1);
                    else
                        ExpandAnimation(5);
                }
            }
            else
            {
                if (firstResize)
                {
                    if (value)
                        this.Height = MainButtonHeight;
                    else
                        this.Height = ExpandedHeight;
                    if (loadBegan)
                        firstResize = !firstResize;
                }
                else
                {
                    if (value)
                        CollapseAnimation(1);
                    else
                        ExpandAnimation(5);
                }
            }
            split.Panel2Collapsed = value;
            ToggleCollapse.Image = toggleImageNeutral;
            Freeze(false);
        }
    }

Solution

  • Not sure I completely understood your problem but maybe this can be of help. If you want a fixed margin to stay around your control after a resize (due to the SplitContainer panel extending/collapsing), you can try this:

    • on your blank user control drag a Panel control and set its Margin to (0,0,0,0) and Padding to (x,x,x,x), where x is the width of the margin you want.

    panel2 expanded

    panel2 collapsed

    Be careful when doing calculations on the height of the children controls to resize the control, always take the paddings and margins into account if you have them set on some children.

    UPDATE:

    As stated here: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.margin?view=netframework-4.8

    "Setting the Margin property on a docked control has no effect on the distance of the control from the edges of its container."

    So, I think you have to choose a specific container like TableLayoutPanel or a FlowLayoutPanel. Try with a FlowLayoutPanel and set it like this:

    • AutoSize = true;
    • BorderStyle = FixedSingle (just to see if the margin is kept correctly)
    • FlowDirection = TopDown

    Then drag inside of it some of your controls with the AutoSize property set to false and with the Margin set as you prefer. You should get something like this:

    enter image description here

    Note: the height of your controls may still be changed (maybe setting a minimum control height can be of help), but once you set their width, the FlowLayoutPanel control can't cut the control because of the margin.