UserControl does not render in FlowLayoutPanel when dock changes

When I add my UserControls to the FlowLayoutPanel, they display correctly. When I change the Dock or Anchor properties to UserControls before adding them, they are still added, but not displayed.

According to “ How: Child Controls for Anchors and Docking Stations, ” this should be possible.

  • I can say that the controls are added (despite not drawing), because adding enough of them causes a vertical scrollbar to appear.
  • Setting the "Dock" property in UserControls to "Left" or "None" will render them, but none of the other options.
  • Setting the Anchor property in UserControls for everything except Top | Left is not displayed.
  • Setting the dock before or after adding the control does not matter (Add, Dock vs. Dock, Add).
  • The FlowLayoutPanel itself is docked (Fill), has a FlowDirection set to TopDown, has a WrapContents value of false, an AutoScroll value of true, and otherwise, the default.

I am using .NET 3.5.


In response to the comment, two commented lines are the places where I tried to change the dock. Second place definitely makes more sense, but I tried another because it couldn’t hurt.

public void CreateObjectControl( object o )
{
    ObjectControl oc = new ObjectControl();

    oc.MyObject = o;

    //This was a spot I mentioned:
    //oc.Dock = DockStyle.Fill;

    ObjectDictionary.Add( o, oc );
    flowLayoutPanel1.Controls.Add( oc );

    //This is the other spot I mentioned:
    oc.Dock = DockStyle.Fill;
}
+5
source share
2 answers

SuspendLayout Resumelayout , - , .

Designer.cs

control.SuspendLayout();
{Your code for designer amendments}
control.resumeaLayout();
0

, (: )... . MS, :

FlowLayoutPanel . , .

. FlowLayoutPanel , , .

, Dock/Anchor / . FlowLayoutPanel , , , , , Dock Anchor " ". , , , .

, ? 0 FlowLayoutPanel, . false. Resize/Layout FlowLayoutPanel, . . , , , .

, " " . , "" , , , . , FlowLayoutPanel , , , , FlowLayoutPanel, . , , , , IDE. , , ControlDesigner. .

, FlowLayoutPanel, ClientSize . , , , . , , , FlowLayoutPanel.

, , , ; -)

using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Windows.Forms;

namespace ControlTest
{
  public sealed class InvisibleControl : Control
  {
    public InvisibleControl()
    {
      TabStop = false;
    }

    #region public interface

    // Reduce the temptation ...
    public new AnchorStyles Anchor
    {
      get { return base.Anchor; }
      set { base.Anchor = AnchorStyles.None; }
    }
    public new DockStyle Dock
    {
      get { return base.Dock; }
      set { base.Dock = DockStyle.None; }
    }

    // We don't ever want to move away from (0,0)
    public new Point Location
    {
      get { return base.Location; }
      set { base.Location = Point.Empty; }
    }

    // Horizontal or vertical orientation?
    private Orientation _orientation = Orientation.Horizontal;
    [DefaultValue(typeof(Orientation), "Horizontal")]
    public Orientation Orientation
    {
      get { return _orientation; }
      set
      {
        if (_orientation == value) return;
        _orientation = value;
        ChangeSize();
      }
    }

    #endregion

    #region overrides of default behaviour

    // We don't want any margin around us
    protected override Padding DefaultMargin => Padding.Empty;

    // Clean up parent references
    protected override void Dispose(bool disposing)
    {
      if (disposing)
        SetParent(null);
      base.Dispose(disposing);
    }

    // This seems to be needed for IDE support, as OnParentChanged does not seem
    // to fire if the control is dropped onto a surface for the first time
    protected override void OnHandleCreated(EventArgs e)
    {
      base.OnHandleCreated(e);
      ChangeSize();
    }

    // Make sure we don't inadvertantly paint anything
    protected override void OnPaint(PaintEventArgs e) { }
    protected override void OnPaintBackground(PaintEventArgs pevent) { }

    // If the parent changes, we need to:
    // A) Unsubscribe from the previous parent Resize event, if applicable
    // B) Subscribe to the new parent Resize event
    // C) Resize our control according to the new parent dimensions
    protected override void OnParentChanged(EventArgs e)
    {
      base.OnParentChanged(e);
      // Perform A+B
      SetParent(Parent);
      // Perform C
      ChangeSize();
    }

    // We don't really want to be resized, so deal with it
    protected override void OnResize(EventArgs e)
    {
      base.OnResize(e);
      ChangeSize();
    }

    #endregion

    #region private stuff

    // Make this a default handler signature with optional params, so that this can
    // directly subscribe to the parent resize event, but also be called without parameters
    private void ChangeSize(object sender = null, EventArgs e = null)
    {
      Rectangle client = Parent?.ClientRectangle ?? new Rectangle(0, 0, 10, 10);
      Size proposedSize = _orientation == Orientation.Horizontal
        ? new Size(client.Width, 0)
        : new Size(0, client.Height);
      if (!Size.Equals(proposedSize)) Size = proposedSize;
    }

    // Handles reparenting
    private Control boundParent;
    private void SetParent(Control parent)
    {
      if (boundParent != null)
        boundParent.Resize -= ChangeSize;
      boundParent = parent;
      if (boundParent != null)
        boundParent.Resize += ChangeSize;
    }

    #endregion
  }
}
0

All Articles