c#在panel中动态增加控件时怎样自动调整panel的行列大小

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#在panel中动态增加控件时怎样自动调整panel的行列大小相关的知识,希望对你有一定的参考价值。

比如:要在panel中动态增加picturebox,它们尺寸是相等的,首先设置的panel的行列数都是2。现在的情况是增加picturebox时panel的行数也在增加,这是肯定的,但是问题是它增加的行间距并不是相等的,这样我的图片根本显示不完全。怎样做到增加picturebox时panel自动增加的行间距是和开始设置的那两行的行间距相等?
谢谢了!希望我描述得够清楚。

  在new GridPanel时加这个:
  viewConfig:
  forceFit: true, // 注意不要用autoFill:true,那样设置的话当GridPanel的大小变化(比如你resize了它)时不会自动调整column的宽度
  scrollOffset: 0 //不加这个的话,会在grid的最右边有个空白,留作滚动条的位置
  ,
  然后还需要给GridPanel所属的容器设置layout:'fit'。不然还是没有效果。
参考技术A pictureBox里面有个Anchor属性,你修改下试试,

另外panel里面也有Anchor属性,
要不行再试试把panel的AutoSize属性改为true,
让Pamel随着窗体的变化而变化,这样要是窗体最大化哪么Panel也就变大了
pictureBox的Anchor属性设置成4边都跟随变化就会变大了。

ps:要是Panel跟着变换可能会影响整体的布局,
可以吧AutoScroll设置为true,这样图片太大Panel就会出现滚动条,不影响你的布局,

在winforms c#中自动调整项目/控件的大小显示错误

【中文标题】在winforms c#中自动调整项目/控件的大小显示错误【英文标题】:Auto resizing items/controls in winforms c# showing error 【发布时间】:2022-01-05 03:41:51 【问题描述】:

我一直在尝试让我的 windows 窗体应用程序自动调整大小,即当用户调整应用程序大小时,它的控件也会相应地调整大小,在网上搜索后,我遇到了以下 .cs 文件形式的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

public class clsResize

    List<System.Drawing.Rectangle> _arr_control_storage = new List<System.Drawing.Rectangle>();
    private bool showRowHeader = false;
    public clsResize(Form _form_)
    
        form = _form_; //the calling form
        _formSize = _form_.ClientSize; //Save initial form size
        _fontsize = _form_.Font.Size; //Font size
    

    private float _fontsize   get; set; 

    private System.Drawing.SizeF _formSize get;set; 

    private Form form  get; set; 

    public void _get_initial_size() //get initial size//
    
        var _controls = _get_all_controls(form);//call the enumerator
        foreach (Control control in _controls) //Loop through the controls
        
            _arr_control_storage.Add(control.Bounds); //saves control bounds/dimension            
            //If you have datagridview
            if (control.GetType() == typeof(DataGridView))
                _dgv_Column_Adjust(((DataGridView)control), showRowHeader);
        
    

    public void _resize() //Set the resize
    
        double _form_ratio_width = (double)form.ClientSize.Width /(double)_formSize.Width; //ratio could be greater or less than 1
        double _form_ratio_height = (double)form.ClientSize.Height / (double)_formSize.Height; // this one too
        var _controls = _get_all_controls(form); //reenumerate the control collection
        int _pos = -1;//do not change this value unless you know what you are doing
        foreach (Control control in _controls)
        
            // do some math calc
            _pos += 1;//increment by 1;
            System.Drawing.Size _controlSize = new System.Drawing.Size((int)(_arr_control_storage[_pos].Width * _form_ratio_width),
                (int)(_arr_control_storage[_pos].Height * _form_ratio_height)); //use for sizing

            System.Drawing.Point _controlposition = new System.Drawing.Point((int)
            (_arr_control_storage[_pos].X * _form_ratio_width),(int) (_arr_control_storage[_pos].Y * _form_ratio_height));//use for location

            //set bounds
            control.Bounds = new System.Drawing.Rectangle(_controlposition, _controlSize); //Put together

            //Assuming you have a datagridview inside a form()
            //if you want to show the row header, replace the false statement of 
            //showRowHeader on top/public declaration to true;
            if (control.GetType() == typeof(DataGridView))
                _dgv_Column_Adjust(((DataGridView)control), showRowHeader);


            //Font AutoSize
            control.Font = new System.Drawing.Font(form.Font.FontFamily,
             (float)(((Convert.ToDouble(_fontsize) * _form_ratio_width) / 2) +
              ((Convert.ToDouble(_fontsize) * _form_ratio_height) / 2)));

        
    

    private void _dgv_Column_Adjust(DataGridView dgv, bool _showRowHeader) //if you have Datagridview 
    //and want to resize the column base on its dimension.
    
        int intRowHeader = 0;
        const int Hscrollbarwidth = 5;
        if (_showRowHeader)
            intRowHeader = dgv.RowHeadersWidth;
        else
            dgv.RowHeadersVisible = false;

        for (int i = 0; i < dgv.ColumnCount; i++)
        
            if (dgv.Dock == DockStyle.Fill) //in case the datagridview is docked
                dgv.Columns[i].Width = ((dgv.Width - intRowHeader) / dgv.ColumnCount);
            else
                dgv.Columns[i].Width = ((dgv.Width - intRowHeader - Hscrollbarwidth) / dgv.ColumnCount);
        
     


      

    private static IEnumerable<Control> _get_all_controls(Control c)
    
        return c.Controls.Cast<Control>().SelectMany(item =>
            _get_all_controls(item)).Concat(c.Controls.Cast<Control>()).Where(control => 
            control.Name != string.Empty);
    

我将此添加到我的项目中,代码如下:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace KryptonTest

    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class MainForm : KryptonForm
    
        clsResize _form_resize;
        
        
        public MainForm()
        
            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();
            

            _form_resize = new clsResize(this);
            this.Load += MainFormLoad;
            this.Resize += MainFormResize;
        

        void MainFormLoad(object sender, EventArgs e)
        

            _form_resize._get_initial_size();
            
        

        void MainFormResize(object sender, EventArgs e)
        
            _form_resize._resize();
        
    

但是当我运行它时,我两次收到以下错误

我该如何解决这个问题?

【问题讨论】:

它的控件也会相应地调整大小 - 这是什么意思?如果用户将窗口大小加倍,那么所有文本框的大小也会加倍吗? @CaiusJard 是的,那将是理想的 添加try catch,看看哪一行出现异常,帮助调试 在第一个代码中,错误显示在 System.Drawing.Size _controlSize = new System.Drawing.Size((int)(_arr_control_storage[_pos].Width * _form_ratio_width), (int)(_arr_control_storage[_pos].Height * _form_ratio_height)); //use for sizing 和第二个代码中 _form_resize._resize(); 【参考方案1】:

当我们调整表单的大小时,我们通常会选择一些控件来变大,而另一些则不会 - 将名称 TextBox 或 Checkbox 的宽度和高度加倍并没有多大意义,因为您不会键入/查看它们中的文字明显更多。其他项目,如日志列表框、电子邮件正文设计器 TextBox 等,调整这些内容的大小是有意义的。

安排一个调整大小的布局非常简单:每个控件都有一个 Anchor 属性,当设置特定边的锚点时,控件将移动或调整大小,因此控件和给定边缘之间的距离相同容器。显然,如果一个控件锚定在相对的两侧,那么当它所在的容器变大时它会拉伸

一些例子:

TextBox 宽 100,高 20,固定在左上角。表格宽 200 像素,高 200 像素。 TextBox 似乎没有移动或增长;它与左上角的距离保持不变

TextBox 宽 100,高 20,固定在右上角。表格宽 200 像素,高 200 像素。 TextBox 向右移动 200 个像素,因为它是右锚定的,并且在窗体右边缘之间保持相同的距离。它不会变宽;它与左上角的距离保持不变。它不会长高,因为它是顶部锚定而不是底部锚定

TextBox 宽 100,高 20,锚定在左上右下。它是一个多行文本框。表格宽 200 像素,高 200 像素。由于表单增长了 200x200,因此 TextBox 的宽度增加了 200 像素,高度增加了 200 像素 - 四周的锚点意味着文本框边缘与表单边缘的距离相同

您需要连续 3 个文本框,当表单变宽时,中间的文本框应该变宽;其他两个文本框不应该增长

您将左侧的 TextBox 锚定在左上角 您将中间的文本框锚定在左上角 您将右文本框锚定在右上角

当窗体变宽时,左侧 TextBox 保持不动,右侧 TextBox 向右移动,随着窗体变宽,中间 TextBox 横向扩展,与窗体变宽一样

当双方都没有锚定时,控件在该方向移动调整大小距离的一半

不要忘记,您可以将面板以一种方式固定在其中,然后将控件以另一种方式固定在其中。对于其他类型的布局,您可能需要一个表格或流布局面板,但对于大多数 UI,锚定系统工作得很好

【讨论】:

【参考方案2】:

您确定枚举工作正常吗?错误消息告诉您列表中的项目比您尝试调用的要少。

索引超出范围。必须是非负数且小于大小 的集合。参数名称:索引

编辑: 我刚刚将您的代码复制并粘贴到 VS 2022 中的一个新 WinForms 项目中,它没有任何问题,尽管我确实不得不放弃对 KryptonForm 的继承引用,因为我没有它。如果有帮助,我使用 .Net 6.0 (LTS) 运行它

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WinFormsApp1

    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class MainForm : Form
    
        clsResize _form_resize;


        public MainForm()
        
            InitializeComponent();


            _form_resize = new clsResize(this);
            this.Load += MainFormLoad;
            this.Resize += MainFormResize;
        

        void MainFormLoad(object sender, EventArgs e)
        

            _form_resize._get_initial_size();

        

        void MainFormResize(object sender, EventArgs e)
        
            _form_resize._resize();
        
    


    public class clsResize
    
        List<System.Drawing.Rectangle> _arr_control_storage = new List<System.Drawing.Rectangle>();
        private bool showRowHeader = false;
        public clsResize(Form _form_)
        
            form = _form_; //the calling form
            _formSize = _form_.ClientSize; //Save initial form size
            _fontsize = _form_.Font.Size; //Font size
        

        private float _fontsize  get; set; 

        private System.Drawing.SizeF _formSize  get; set; 

        private Form form  get; set; 

        public void _get_initial_size() //get initial size//
        
            var _controls = _get_all_controls(form);//call the enumerator
            foreach (Control control in _controls) //Loop through the controls
            
                _arr_control_storage.Add(control.Bounds); //saves control bounds/dimension            
                                                          //If you have datagridview
                if (control.GetType() == typeof(DataGridView))
                    _dgv_Column_Adjust(((DataGridView)control), showRowHeader);
            
        

        public void _resize() //Set the resize
        
            double _form_ratio_width = (double)form.ClientSize.Width / (double)_formSize.Width; //ratio could be greater or less than 1
            double _form_ratio_height = (double)form.ClientSize.Height / (double)_formSize.Height; // this one too
            var _controls = _get_all_controls(form); //reenumerate the control collection
            int _pos = -1;//do not change this value unless you know what you are doing
            foreach (Control control in _controls)
            
                // do some math calc
                _pos += 1;//increment by 1;
                System.Drawing.Size _controlSize = new System.Drawing.Size((int)(_arr_control_storage[_pos].Width * _form_ratio_width),
                    (int)(_arr_control_storage[_pos].Height * _form_ratio_height)); //use for sizing

                System.Drawing.Point _controlposition = new System.Drawing.Point((int)
                (_arr_control_storage[_pos].X * _form_ratio_width), (int)(_arr_control_storage[_pos].Y * _form_ratio_height));//use for location

                //set bounds
                control.Bounds = new System.Drawing.Rectangle(_controlposition, _controlSize); //Put together

                //Assuming you have a datagridview inside a form()
                //if you want to show the row header, replace the false statement of 
                //showRowHeader on top/public declaration to true;
                if (control.GetType() == typeof(DataGridView))
                    _dgv_Column_Adjust(((DataGridView)control), showRowHeader);


                //Font AutoSize
                control.Font = new System.Drawing.Font(form.Font.FontFamily,
                 (float)(((Convert.ToDouble(_fontsize) * _form_ratio_width) / 2) +
                  ((Convert.ToDouble(_fontsize) * _form_ratio_height) / 2)));

            
        

        private void _dgv_Column_Adjust(DataGridView dgv, bool _showRowHeader) //if you have Datagridview 
                                                                               //and want to resize the column base on its dimension.
        
            int intRowHeader = 0;
            const int Hscrollbarwidth = 5;
            if (_showRowHeader)
                intRowHeader = dgv.RowHeadersWidth;
            else
                dgv.RowHeadersVisible = false;

            for (int i = 0; i < dgv.ColumnCount; i++)
            
                if (dgv.Dock == DockStyle.Fill) //in case the datagridview is docked
                    dgv.Columns[i].Width = ((dgv.Width - intRowHeader) / dgv.ColumnCount);
                else
                    dgv.Columns[i].Width = ((dgv.Width - intRowHeader - Hscrollbarwidth) / dgv.ColumnCount);
            
        

        private static IEnumerable<Control> _get_all_controls(Control c)
        
            return c.Controls.Cast<Control>().SelectMany(item =>
                _get_all_controls(item)).Concat(c.Controls.Cast<Control>()).Where(control =>
                control.Name != string.Empty);
        
    

【讨论】:

我无法弄清楚/如何解决它,这就是问题所在...... 我正在使用。 Net 4.5 & 我仍然收到错误,但如果我单击继续,应用程序似乎可以工作。但是我不确定忽略错误是否正确

以上是关于c#在panel中动态增加控件时怎样自动调整panel的行列大小的主要内容,如果未能解决你的问题,请参考以下文章

C# WinForm 动态添加-删除控件内存未释放

c# winform groupbox上动态生成的控件,如何让控件随着分辨率变化而自动调整位置和大小

C# WinForm的SplitContainer控件固定Panel大小

c# panel里面的内容超出怎么自动出现滚动条

C#怎样判断鼠标移动到控件上了

调整splitcontainer时,如何使panel1里面的outlook控件随panel1的变化而变化