简体   繁体   English

在面板内的列中动态创建控件

[英]Create dynamically controls in columns inside a Panel

I have a panel where I create Labels and NumericUpDown fields dinamically like:我有一个面板,我可以在其中以动态方式创建 Labels 和 NumericUpDown 字段,例如:

        List<string> Labels = new List<string>();
        public List<Label> DeliveryBreakdownLabelsModel = new List<Label>();
        public List<NumericUpDown> DeliveryBreakdownNumericUpDownModel = new List<NumericUpDown>();


    private void SetDeliveryBreakdownAmountForm_Load(object sender, EventArgs e)
        {
           var rModel = //List data from database
            AddRow(rModel);
            Arrange();
        }




      private void AddRow(IList<DeliveryBreakdownGetViewModel> rModel)
        {
            for (int i = 0; i < rModel.Count; i++)
            {
                Labels.Add(rModel[i].DesignGroupName);
                var label = new Label
                {
                    AutoSize = true, // make sure to enable AutoSize
                    Name = "label" + Labels.Count,
                    Text = rModel[i].DesignGroupName,
                    Location = new Point(12, YPos)
                };
                this.Controls.Add(label);
                pnlDeliveryBreakdown.Controls.Add(label);
                DeliveryBreakdownLabelsModel.Add(label);


                var numericUpDown = new NumericUpDown
                {
                    Name = "numericUpDown" + Labels.Count,
                    Text = rModel[i].ContractedAmount.ToString(),
                    Location = new Point(12, YPos),
                    Size = new Size(60, 19),
                    DecimalPlaces = 2,
                    Maximum = decimal.MaxValue
                };
                this.Controls.Add(numericUpDown);
                this.Controls.Add(numericUpDown);
                pnlDeliveryBreakdown.Controls.Add(numericUpDown);
                DeliveryBreakdownNumericUpDownModel.Add(numericUpDown);


                YPos += 25;
            }
        }





         void Arrange()
        {
            // Determine the widest label sized by the AutoSize 
            var maxLabelX = 0;
            for (int i = 0; i < Labels.Count; i++)
            {
                maxLabelX = Math.Max(maxLabelX, DeliveryBreakdownLabelsModel[i].Location.X + DeliveryBreakdownLabelsModel[i].Size.Width);
            }

            // Move all the text boxes a little to the right of the widest label
            var maxNumericX = 0;
            for (int i = 0; i < Labels.Count; i++)
            {
                maxNumericX = Math.Max(maxNumericX, DeliveryBreakdownNumericUpDownModel[i].Location.X + DeliveryBreakdownNumericUpDownModel[i].Size.Width);
                DeliveryBreakdownNumericUpDownModel[i].Location = new Point(maxLabelX + 10, DeliveryBreakdownNumericUpDownModel[i].Location.Y);
            }

            //Set total wi
            this.Width = maxNumericX + maxLabelX + 60;
        }

So it looks like:所以它看起来像:

在此处输入图片说明

My question is, how can I modify my code in order to create more than one column.我的问题是,如何修改我的代码以创建多个列。 I want to do that because sometimes I can have alot of data so shows only in vertical may be a problem in future.我想这样做是因为有时我可以拥有大量数据,因此仅以垂直方式显示将来可能会成为问题。 Expected result: IE预期结果:IE

在此处输入图片说明

I suggest using a TableLayoutPanel with a UserControl that contains exactly one label and one numeric box.我建议将TableLayoutPanelUserControl一起使用,该UserControl包含一个标签和一个数字框。

Even in the designer, this looks neat.即使在设计师中,这看起来也很整洁。

图片1

All you have to do is expose the properties you want from the numeric box in your user control.您所要做的就是从用户控件中的数字框中公开所需的属性。

In the example above, I am using the following code:在上面的示例中,我使用了以下代码:

// Fixed height user control
// Some code taken from: https://stackoverflow.com/a/4388922/380384
[Designer(typeof(MyControlDesigner))]
public partial class LabelNumeric : UserControl
{
    public LabelNumeric()
    {
        InitializeComponent();
    }

    protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
    {
        base.SetBoundsCore(x, y, width, 24, specified);
    }
    [DefaultValue("Label")]
    public string Caption
    {
        get => label1.Text;
        set => label1.Text = value;
    }
    [DefaultValue(0)]
    public decimal Value
    {
        get => numericUpDown1.Value;
        set => numericUpDown1.Value =value;
    }
    [DefaultValue(0)]
    public int DecimalPlaces
    {
        get => numericUpDown1.DecimalPlaces;
        set => numericUpDown1.DecimalPlaces = value;
    }
    [DefaultValue(100)]
    public decimal MaxValue
    {
        get => numericUpDown1.Maximum;
    }
    [DefaultValue(0)]
    public decimal MinValue
    {
        get => numericUpDown1.Minimum;
    }
}
internal class MyControlDesigner : ControlDesigner
{
    MyControlDesigner()
    {
        base.AutoResizeHandles = true;
    }
    public override SelectionRules SelectionRules
    {
        get
        {
            return SelectionRules.LeftSizeable | SelectionRules.RightSizeable | SelectionRules.Moveable;
        }
    }
}

You can access all the controls from the tableLayoutPanel1.Controls property and check their position in the table like this:您可以从tableLayoutPanel1.Controls属性访问所有控件并检查它们在表格中的位置,如下所示:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        foreach (var item in tableLayoutPanel1.Controls.OfType<LabelNumeric>())
        {
            var pos = tableLayoutPanel1.GetCellPosition(item);
            item.Caption = $"Row{pos.Row}Col{pos.Column}";
        }
    }
}

So at runtime it is as follows:所以在运行时它是这样的:

图片2

The trick is to have one extra row on the bottom autosized, and all the other rows that contain the controls be of fixed height of 24pt .诀窍是在底部自动调整一个额外的行,并且包含控件的所有其他行的固定高度为24pt

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM