Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom panel with layout engine

I'm trying to create a custom Panel control with my own layout engine. I need every control that is added to my panel to be added below and to take full width (-padding), like below: enter image description here

Below is my code:

using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Layout;

namespace VContainer
{
    internal class VerticalFillList : Panel
    {
        public VerticalFillList()
        {
            AutoScroll = true;
            MinimumSize = new Size(200, 200);
            Size = new Size(200, 300);
            Padding = new Padding(10);
        }

        private readonly VerticalFillLayout _layoutEngine = new VerticalFillLayout();

        public override LayoutEngine LayoutEngine
        {
            get { return _layoutEngine; }
        }

        private int _space = 10;

        public int Space
        {
            get { return _space; }
            set
            {
                _space = value;
                Invalidate();
            }
        }
    }

    internal class VerticalFillLayout : LayoutEngine
    {
        public override bool Layout(object container, LayoutEventArgs layoutEventArgs)
        {
            var parent = container as VerticalFillList;

            Rectangle parentDisplayRectangle = parent.DisplayRectangle;
            Point nextControlLocation = parentDisplayRectangle.Location;

            foreach (Control c in parent.Controls)
            {
                if (!c.Visible)
                {
                    continue;
                }

                c.Location = nextControlLocation;
                c.Width = parentDisplayRectangle.Width;
                nextControlLocation.Offset(0, c.Height + parent.Space);
            }
            return false;
        }
    }
}

Above code works fine, except one thing: when I'm adding controls to my container they are added correctly (new below parent, 100% width), but when height of controls is bigger than my container height I get horizontal scrollbars, but after adding couple controls more scrollbar is removed. adding components

Same thing happens when I want to resize my container: resizing container

How this can be fixed? I just need to remove that horizontal scrollbar.

Of course all improvements are welcome :)

I don't want to use table layout or flow layout as this one gives me exactly when I need.

I need a simple container that orders all child controls from top to bottom and stretches them horizontally so they take as much width so container horizontal scrollbar isn't needed.

like image 601
Misiu Avatar asked Mar 12 '13 11:03

Misiu


1 Answers

Here is a working example that unfortunately, does not use your Layout Engine class. It simply relies on the OnControlAdded and OnControlRemoved methods, and anchoring and setting the AutoScrollMinSize property to specifically make sure the horizontal scrollbar never appears:

internal class VerticalPanel : Panel {
  private int space = 10;

  public int Space {
    get { return space; }
    set {
      space = value;
      LayoutControls();
    }
  }

  protected override void OnControlAdded(ControlEventArgs e) {
    base.OnControlAdded(e);
    LayoutControls();
  }

  protected override void OnControlRemoved(ControlEventArgs e) {
    base.OnControlRemoved(e);
    LayoutControls();
  }

  private void LayoutControls() {
    int height = space;
    foreach (Control c in base.Controls) {
      height += c.Height + space;
    }
    base.AutoScrollMinSize = new Size(0, height);

    int top = base.AutoScrollPosition.Y + space;
    int width = base.ClientSize.Width - (space * 2);
    foreach (Control c in base.Controls) {
      c.SetBounds(space, top, width, c.Height);
      c.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
      top += c.Height + space;
    }
  }
}
like image 198
LarsTech Avatar answered Oct 23 '22 14:10

LarsTech