FlowLayoutPanel - Largeur automatique des contrôles?
-
28-10-2019 - |
Question
Est-il possible de rendre les éléments insérés dans FlowLayoutPanel la taille automatique du FlowLayoutPanel?Voici un exemple:
Un formulaire avec 1 FlowLayoutPanel et 3 boutons à l'intérieur:
si je redimensionne le formulaire, les contrôles ressemblent à ceci: ils organisent "de gauche à droite"
Ce que je veux, c'est ceci: Les contrôles doivent avoir la largeur du FlowLayoutPanel:
Des idées comment faire cela?J'ai changé le FlowDirection et joué avec la propriété Anchor mais sans chance.
Je pourrais bien sûr redimensionner les contrôles dans l'événement FlowLayoutPanel_Resize, mais je veux ajouter environ 500 contrôles utilisateur - je l'ai testé et c'est lent.
La solution
Je vous suggère d'utiliser TableLayoutPanel avec une colonne dans ce cas.J'ai trouvé TableLayoutPanel beaucoup plus prévisible et solide que FlowLayoutPanel.
Une autre option, si vous souhaitez toujours utiliser FlowLayoutPanel, consiste à définir la largeur du premier contrôle sur celle souhaitée et à utiliser Dock= Top pour tous les autres contrôles.
Autres conseils
C'est un moyen simple de le faire. Liez simplement l'événement SizeChanged de votre flowLayoutPannel et redimensionnez le contrôle contenant. Comme:
private void myFlowLayoutPannel_SizeChanged(object sender, EventArgs e)
{
myFlowLayoutPannel.SuspendLayout();
foreach (Control ctrl in pnSMS.Controls)
{
if (ctrl is Button) ctrl.Width = pnSMS.ClientSize.Width;
}
myFlowLayoutPannel.ResumeLayout();
}
ici, j'ai ma classe StackPanel:
/// <summary>
/// A stackpanel similar to the Wpf stackpanel.
/// </summary>
public class StackPanel: FlowLayoutPanel
{
public StackPanel(): base()
{
InitializeComponent();
this.ForceAutoresizeOfControls = true;
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// StackPanel
//
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.WrapContents = false;
this.ResumeLayout(false);
}
/// <summary>
/// Override it just in order to hide it in design mode.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public new bool WrapContents
{
get { return base.WrapContents; }
set { base.WrapContents = value; }
}
/// <summary>
/// Override it just in order to set its default value.
/// </summary>
[DefaultValue(typeof(AutoSizeMode), "GrowAndShrink")]
public override AutoSizeMode AutoSizeMode
{
get { return base.AutoSizeMode; }
set { base.AutoSizeMode = value; }
}
/// <summary>
/// Get or set a value that when is true forces the resizing of each control.
/// If this value is false then only control that have AutoSize == true will be resized to
/// fit the client size of this container.
/// </summary>
[DefaultValue(true)]
public bool ForceAutoresizeOfControls { get; set; }
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
this.SuspendLayout();
switch (FlowDirection)
{
case FlowDirection.BottomUp:
case FlowDirection.TopDown:
foreach (Control control in this.Controls)
if (ForceAutoresizeOfControls || control.AutoSize)
control.Width = this.ClientSize.Width - control.Margin.Left - control.Margin.Right;
break;
case FlowDirection.LeftToRight:
case FlowDirection.RightToLeft:
foreach (Control control in this.Controls)
if (ForceAutoresizeOfControls || control.AutoSize)
control.Height = this.ClientSize.Height - control.Margin.Top - control.Margin.Bottom;
break;
default:
break;
}
this.ResumeLayout();
}
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
if (levent != null && levent.AffectedControl != null)
{
Control control = levent.AffectedControl;
if (ForceAutoresizeOfControls || control.AutoSize)
{
switch (FlowDirection)
{
case FlowDirection.BottomUp:
case FlowDirection.TopDown:
control.Width = this.ClientSize.Width - control.Margin.Left - control.Margin.Right;
break;
case FlowDirection.LeftToRight:
case FlowDirection.RightToLeft:
control.Height = this.ClientSize.Height - control.Margin.Top - control.Margin.Bottom;
break;
default:
break;
}
}
}
}
}
Le FlowLayoutPanel
organise les contrôles d'une manière particulière, selon MSDN :
... pour les directions d'écoulement verticales, le contrôle FlowLayoutPanel calcule la largeur d'une colonne implicite à partir du contrôle enfant le plus large du colonne .Toutes les autres commandes de cette colonne avec Anchor ou Dock les propriétés sont alignées ou étirées pour s'adapter à cette colonne implicite.La Le comportement fonctionne de la même manière pour les directions d'écoulement horizontales.
Ce n'est pas idéal, mais vous pouvez le faire de manière native, à condition qu'un contrôle enfant soit défini sur la même largeur que le conteneur et que le reste des contrôles soit défini sur Dock
.
Je suggère ... essayez de jouer avec les ancres des boutons ... essayez de le définir comme
Button1.Anchor = (AnchoreStyle.Left or AnchoreStyle.Right)
ou définissez-le dans les propriétés ...
puis placez-le dans un Panel au lieu du FlowLayoutPanel ...;)
Vous devriez pouvoir faire ce que vous voulez avec un contrôle FlowLayoutPanel
normal.
Ancrez-le sur les quatre côtés pour qu'il s'étire avec votre formulaire, puis ajoutez vos boutons et définissez-les tous sur Dock: Top.
Travail terminé.
Comme d'autres réponses l'ont indiqué, le Panel lui-même est suffisant pour gérer vos boutons.Un peu de code qui fonctionne pour moi:
public class ButtonWindow : Panel
{
public ButtonWindow()
{
Dock = DockStyle.Fill;
AutoScroll = true;
for (int i = 0; i < 500; i++)
{
Button button = new Button() { Height = 100, Dock = DockStyle.Top };
Controls.Add(button);
}
}
}
Passez une bonne journée.