UserControl не рендерится в FlowLayoutPanel при изменении док-станции - PullRequest
5 голосов
/ 15 сентября 2011

Когда я добавляю свои пользовательские элементы управления в панель FlowLayout, они отображаются правильно.Когда я изменяю свойства Dock или Anchor в UserControls перед их добавлением, они все еще добавляются, но не отображаются.

В соответствии с « How to: Anchor and Dock Child Controls » это должновозможно.

  • Я могу сказать, что элементы управления добавляются (несмотря на то, что они не рисуются), потому что при добавлении их достаточно, появляется вертикальная полоса прокрутки.
  • Установка свойства «Док»UserControls в «Left» или «None» вызовет их рендеринг, но ни одна из других опций.
  • Установка свойства «Anchor» в UserControls на что угодно, кроме Top |Слева не отображается.
  • Установка до или после добавления элемента управления не имеет значения (Добавить, Dock против Dock, Добавить).
  • FlowLayoutPanel сама закреплена (Fill),для FlowDirection установлено значение TopDown, для WrapContents установлено значение false, для AutoScroll установлено значение true и в противном случае используется значение по умолчанию.

Я использую .NET 3.5.


В ответена комментарий, две закомментированные строки - это места, где я пытался сменить док-станцию.Второе место определенно имеет больше смысла, но я попробовал другое, потому что это не могло повредить.

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;
}

Ответы [ 2 ]

0 голосов
/ 28 апреля 2016

Я думаю, что, возможно, нашел обходной путь (читай: подвох) ... этот ответ помог указать мне правильное направление. Вот выдержка из статьи 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
  }
}
0 голосов
/ 28 ноября 2014

попробуйте использовать функции SuspendLayout и Resumelayout для элементов управления, прежде чем вносить какие-либо изменения, которые требуют рендеринга для правильного просмотра.

Вы можете увидеть код из Designer.cs для этого конкретного элемента управления

Синтаксис

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