Я думаю, что, возможно, нашел обходной путь (читай: подвох) ... этот ответ помог указать мне правильное направление. Вот выдержка из статьи MS , на которую вы также ссылались:
Для вертикальных направлений потока элемент управления FlowLayoutPanel вычисляет ширину подразумеваемого столбца из самого широкого дочернего элемента управления в столбце. Все остальные элементы управления в этом столбце со свойствами Anchor или Dock выровнены или растянуты, чтобы соответствовать этому подразумеваемому столбцу.
Поведение работает аналогичным образом для горизонтальных направлений потока. Элемент управления FlowLayoutPanel вычисляет высоту подразумеваемой строки из самого высокого дочернего элемента управления в строке, и все закрепленные или закрепленные дочерние элементы управления в этой строке выровнены или имеют размер, подходящий для подразумеваемой строки.
На этой странице специально не упоминается, что вы не можете закрепить / закрепить самый высокий / самый широкий элемент управления. Но так как этот элемент управления определяет поведение макета 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's Resize event, if applicable
// B) Subscribe to the new parent's 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
}
}