【问题标题】:Align controls to center in a FlowLayout对齐控件以在 FlowLayout 中居中
【发布时间】:2012-05-15 11:42:13
【问题描述】:

我有一个流程布局如下:

我需要将表单上的所有控件居中(换句话说,假设表单的宽度为 200。btnOpt1 到 btnOpt4 的 Left 应该从 100 减去按钮宽度的一半开始,不是 0 .)

【问题讨论】:

  • FLowLayout 不是为此而设计的。
  • @SLaks 你能推荐一个替代方案吗?
  • 你知道你想要实现什么吗?您的第一点与关于布局的第二点相矛盾。在哪种情况下,您将根据您的第一个条件将它们放回原处??...而不是使用 flowlayout 面板,将控件放在面板中,然后根据使用锚属性或停靠属性你的要求..
  • @NiranjanKala 在实施方面,其中一个都很好。但我删除了第二个只是为了让您开心并保持问题的相关性。
  • 这是 WPF 获胜的另一个案例。

标签: c# .net winforms


【解决方案1】:

您可以通过两种方式进行操作,但每种方式都有一些限制。

  1. 使用Anchor 属性
  2. 借助 DockingAnchor 属性使用布局控件。

方法一:锚属性

控件默认锚定在表单的左上角 表示当表格大小改变时,它们与顶部的距离 表单的左侧将保持不变。如果你改变控制 锚定到左下角,那么控件将保持相同的距离 当窗体调整大小时,从窗体的底部和左侧开始。

关闭某个方向的锚点将使控件保持居中 调整大小时的那个方向。

例子:

public TestForm12()
{
   InitializeComponent();

   Button btn = new Button();
   btn.Width = this.Width - 10;
   btn.Height = 20;
   btn.Left = (this.ClientSize.Width - btn.Width) / 2;
   btn.Top = (this.ClientSize.Height - btn.Height) / 2;
   btn.Text = "click me";
   this.Controls.Add(btn);
   btn.Anchor = AnchorStyles.None;               

}

2。使用布局控件

  1. 添加 TableLayout 控件,将其 Dock 属性设置为 Fill。
  2. 添加 1 行,大小类型样式百分比 100%
  3. 添加 3 列 Column1(大小类型 - 百分比(100%)),Column2(大小类型 - 绝对(200px)),Column3(大小类型 - 百分比(100%))。
  4. 现在将面板控件添加到 Column2 并将其 Dock 属性设置为 Fill
  5. 将按钮添加到此控件并根据需要设置其大小并将其锚属性设置为 AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top

示例 - Designer.cs 代码 sn-p 表单。

private void InitializeComponent()
 {
     this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
     this.panel1 = new System.Windows.Forms.Panel();
     this.button1 = new System.Windows.Forms.Button();
     this.button2 = new System.Windows.Forms.Button();
     this.tableLayoutPanel1.SuspendLayout();
     this.panel1.SuspendLayout();
     this.SuspendLayout();
     // 
     // tableLayoutPanel1
     // 
     this.tableLayoutPanel1.ColumnCount = 3;
     this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
     this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 200F));
     this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
      this.tableLayoutPanel1.Controls.Add(this.panel1, 1, 0);
      this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
      this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
      this.tableLayoutPanel1.Name = "tableLayoutPanel1";
      this.tableLayoutPanel1.RowCount = 1;
      this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
      this.tableLayoutPanel1.Size = new System.Drawing.Size(284, 262);
      this.tableLayoutPanel1.TabIndex = 0;
      // 
      // panel1
      // 
      this.panel1.Controls.Add(this.button2);
      this.panel1.Controls.Add(this.button1);
      this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
      this.panel1.Location = new System.Drawing.Point(45, 3);
      this.panel1.Name = "panel1";
      this.panel1.Size = new System.Drawing.Size(194, 256);
      this.panel1.TabIndex = 0;
      // 
      // button1
      // 
      this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
    | System.Windows.Forms.AnchorStyles.Right)));
    this.button1.Location = new System.Drawing.Point(3, 9);
    this.button1.Name = "button1";
    this.button1.Size = new System.Drawing.Size(188, 23);
    this.button1.TabIndex = 0;
    this.button1.Text = "button1";
    this.button1.UseVisualStyleBackColor = true;
    // 
    // button2
    // 
    this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
    | System.Windows.Forms.AnchorStyles.Right)));
    this.button2.Location = new System.Drawing.Point(3, 38);
    this.button2.Name = "button2";
    this.button2.Size = new System.Drawing.Size(188, 23);
    this.button2.TabIndex = 0;
    this.button2.Text = "button1";
    this.button2.UseVisualStyleBackColor = true;
    // 
    // TestForm11
    // 
    this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    this.ClientSize = new System.Drawing.Size(284, 262);
    this.Controls.Add(this.tableLayoutPanel1);
    this.Name = "TestForm11";
    this.Text = "TestForm11";
    this.tableLayoutPanel1.ResumeLayout(false);
    this.panel1.ResumeLayout(false);
    this.ResumeLayout(false);

}

 #endregion

private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button1;

希望对您有所帮助..

【讨论】:

  • 对我来说,将 AnchorStyle 设置为 None 就足够了(无需设置左侧或其他任何内容),我想知道我是否缺少任何东西。
  • 如果您在表格布局面板中使用该控件,那么它可能会工作。如果您将 AnchorStype 设置为 None,它可能会正常工作。
【解决方案2】:

我会选择TableLayoutPanel

  • 将 TableLayoutPanel 放在表单上
  • 将停靠样式Fill设置为面板
  • 在面板内只保留一列
  • 为每个按钮创建行(并将按钮放入表格单元格)
  • 设置行大小类型Autosize
  • 为每个按钮设置停靠样式Fill,除了最后一个
  • 将停靠样式Top 设置为最后一个按钮

顺便说一句,在您的解决方案中,您应该迭代 flowLayoutPanel 控件而不是表单控件。还可以考虑从宽度中减去水平边距和内边距:

foreach (Control control in flowLayoutPanel.Controls)
{
    control.Size = new Size(flowLayoutPanel.Width - control.Margin.Horizontal,
                            control.Height); 
}

但我建议你改用 TableLayoutPanel。

【讨论】:

    【解决方案3】:

    我通过更改边距值解决了这个问题。不过,我正在将我的内容添加到面板中。

    C#:

    int horizontalMargin = (int)(0.5 * (this.containingPanelOrForm.Width - this.button.Width));
    this.btnOptX.Margin = new Padding(horizontalMargin, 0, horizontalMargin, 0);
    

    【讨论】:

      【解决方案4】:

      或者您可以使用网格布局。

      【讨论】:

        【解决方案5】:

        我不擅长 C#,但您也可以在 flowlayoutpanel 中添加一个与 flowlayoutpanel 宽度相同的面板。然后您可以在运行时创建的面板中添加您想要的按钮并将停靠栏设置为向左或向右。如你所愿。让我在 VB.net 和 C# 中展示一个示例(使用在线转换)

        VB.net

             Dim btn As New Button
                    btn.Text = "Example"
                    btn.Name = "Button"
                    btn.Size = New Size(60,10)
                    Dim panel As New Panel
                    panel.Size = New Size(FlowLayoutPanel1.Width, 10) 'size of the flowlayoutpanel + height of button
                    btn.Dock = DockStyle.Right
                    FlowLayoutPanel1.Controls.Add(panel)
        panel.controls.add(btn)
        

        C#

        Button btn = new Button();
        btn.Text = "Example";
        btn.Name = "Button";
        btn.Size = new Size(60, 10);
        Panel panel = new Panel();
        panel.Size = new Size(FlowLayoutPanel1.Width, 10);
        //size of the flowlayoutpanel + height of button
        btn.Dock = DockStyle.Right;
        FlowLayoutPanel1.Controls.Add(panel);
        panel.controls.@add(btn);
        

        【讨论】:

          【解决方案6】:

          使用 Name = lblEmpty 和 AutoSize = False 创建空标签。将此控件先放在FlowLayoutPanel1中的控件列表中,然后在下面添加代码。

          示例:假设 FlowLayoutPanel1 中存在三个标签,结果应依次为 lblEmpty、LabelExisting1 和 LabelExisting2。

          Dim MarginLabelEmpty As Integer = ((FlowLayoutPanel1.Width - (LabelExisting1.Width + LabelExisting2.Width)) / 2)
                  lblEmpty.Width = MarginLabelEmpty
          

          我通过创建这段代码解决了我的问题。

          在您使用按钮控件的情况下,使用 .Text=""(empty) 创建 4 个新标签,并将每个标签放在每个按钮的开头,命名标签如下:lblEmpty1、lblEmpty2、lblEmpty3、lblEmpty4。

          然后添加以下代码:

          Dim MarginLeftbtnOptAll As Integer = ((FlowLayoutPanel1.Width - btnOpt1.Width) / 2)
                  lblEmpty1.AutoSize = False
                  lblEmpty1.Width = MarginLeftbtnOptAll
                  lblEmpty2.AutoSize = False
                  lblEmpty2.Width = MarginLeftbtnOptAll
                  lblEmpty3.AutoSize = False
                  lblEmpty3.Width = MarginLeftbtnOptAll
                  lblEmpty4.AutoSize = False
                  lblEmpty4.Width = MarginLeftbtnOptAll
          

          这个中心按钮,根据FlowLayoutPanel1的宽度增加空标签的宽度

          【讨论】:

            【解决方案7】:

            将按钮直接扔到表单或面板(不是 FlowLayoutPanel),并为所有按钮设置Anchor = Top(仅顶部),它们不会居中,但始终与表单(或容器)成比例移动调整大小时的边。

            【讨论】:

              【解决方案8】:
              Private Sub FlowLayoutPanel1_SizeChanged(sender As Object, e As EventArgs)` Handles FlowLayoutPanel1.SizeChanged
              
                      Dim TotalWidth As Integer = FlowLayoutPanel1.Controls.Count * button.Width
                      Dim LeftPadding As Integer = (FlowLayoutPanel1.Width - TotalWidth) / 2
                      Dim GapPadding As Integer = FlowLayoutPanel1.Controls.Count * 5
              
                      If TotalWidth <= FlowLayoutPanel1.Width Then
                          FlowLayoutPanel1.Padding = New Padding(LeftPadding - GapPadding, 0, 0, 0)
                      End If
              
              End Sub
              

              【讨论】:

                猜你喜欢
                • 2013-05-26
                • 1970-01-01
                • 2021-08-30
                • 1970-01-01
                • 2015-07-25
                • 2012-03-22
                • 2015-05-06
                • 1970-01-01
                • 2012-10-15
                相关资源
                最近更新 更多