Windows 窗体中的布局困难

ipo*_*rto 0 c# user-interface winforms

我正在使用 Windows 窗体使用 C# 编写应用程序。它是一个带有菜单、选项卡式窗格、网格和状态栏的表单。我希望即使在调整窗口大小时控件也能正确显示。如果我将控件添加到窗体而不使用任何布局面板,菜单栏将显示在选项卡的顶部(参见图 1)。另一方面,如果我使用 FlowLayoutPanel 从上到下添加组件,则控件不会填充可用空间(参见图 2)。

\n\n

编辑:我无法使用 TableLayoutPanel 解决它。垂直空间也没有被填充。参见图 3。

\n\n

可能是什么问题?在 Windows 窗体中使用布局的常用方法是什么?先感谢您。

\n\n

没有布局面板的屏幕截图

\n\n

FlowLayoutPanel 的屏幕截图

\n\n

TableLayoutPanel 的屏幕截图

\n\n

代码如下:

\n\n
using System;\nusing System.Collections.Generic;\nusing System.ComponentModel;\nusing System.Data;\nusing System.Drawing;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing System.Windows.Forms;\nusing AGAPconsole;\n\nnamespace AGAP\n{\npublic partial class MainForm : Form\n{\n\n    private String user;\n    private ClassDatabase db;\n\n    private TableLayoutPanel mainPanel;\n    private TabControl mainTabControl;\n    private TabPage mainTabPage;\n\n    // Grid de actuaciones\n    private DataGridView actuacionesGrid;\n    private ContextMenuStrip actuacionesContextMenuStrip;\n    private ToolStripMenuItem verTramitesMenuItem;\n    private ToolStripMenuItem verEncargosMenuItem;\n    private ToolStripMenuItem verTrabajosMenuItem;\n    private ToolStripMenuItem verDatosObraMenuItem;\n\n    // Barra de estado\n    private StatusStrip mainStatusStrip;\n    private ToolStripStatusLabel mainStatusLabel;\n\n    // Menu\n    private MenuStrip mainMenuStrip;\n    private ToolStripMenuItem archivoMenuItem;\n    private ToolStripMenuItem salirMenuItem;\n    private ToolStripMenuItem abrirMenuItem;\n\n    // Importacion\n    private OpenFileDialog openFileDialog;\n\n    // Users\n    public static String USER_CONSULTA_CORUNA = "Delegaci\xc3\xb3n C (R)";\n    public static String USER_EDICION_CORUNA = "Delegaci\xc3\xb3n C (RW)";\n    public static String USER_CONSULTA_OURENSE = "Delegaci\xc3\xb3n OU-LU (R)";\n    public static String USER_EDICION_OURENSE = "Delegaci\xc3\xb3n OU-LU (RW)";\n    public static String USER_CONSULTA_PONTEVEDRA = "Delegaci\xc3\xb3n PO (R)";\n    public static String USER_EDICION_PONTEVEDRA = "Delegaci\xc3\xb3n PO (RW)";\n    public static String USER_IMPORTACION = "Importaci\xc3\xb3n";\n    public static String USER_ZONA = "Zona";\n\n    public static String[] USERS = { USER_ZONA, USER_CONSULTA_CORUNA, \n                                       USER_EDICION_CORUNA, USER_CONSULTA_OURENSE, \n                                       USER_EDICION_OURENSE, USER_CONSULTA_PONTEVEDRA, \n                                       USER_EDICION_PONTEVEDRA, USER_IMPORTACION };\n\n    public MainForm(String user)\n    {\n        this.user = user;\n        db = new ClassDatabase();\n        //InitializeComponent();\n        //this.AutoScaleDimensions = new SizeF(6F, 13F);\n        this.AutoScaleMode = AutoScaleMode.Font;\n        this.ClientSize = new Size(984, 762);\n        this.Name = "MainForm";\n        //this.StartPosition = FormStartPosition.CenterScreen;\n        this.Text = "AGAP";\n        this.WindowState = FormWindowState.Maximized;\n        this.BackColor = SystemColors.Window;\n\n        this.Controls.Add(CreateMainPanel());\n\n        // Menu\n        mainPanel.Controls.Add(CreateMainMenuStrip());\n\n        // Contenido dependiendo del usuario\n\n        // El menu tendra Archivo -> Salir a no ser que sea el usuario de importacion,\n        // que tendra mas cosas.\n        if (!user.Equals(USER_IMPORTACION))\n        {\n            //CreateArchivoSalir();\n            CreateSalir();\n        }\n\n        if (user.Equals(USER_ZONA))\n        {\n            this.Text = "AGAP Visualizaci\xc3\xb3n de datos";\n            InitVisualizacion();\n        }\n\n        if (user.Equals(USER_IMPORTACION))\n        {\n            this.Text = "AGAP Importaci\xc3\xb3n de datos";\n            InitImportacion();\n        }\n\n        // Barra de estado\n        mainPanel.Controls.Add(CreateMainStatusStrip());\n        this.mainStatusLabel.Text = "Autenticado como " + user;\n    }\n\n    private void InitImportacion()\n    {\n        CreateOpenFileDialog();\n        // this.Controls.Add(CreateMainPanel());\n        // mainPanel.Controls.Add(CreateMainMenuStrip());\n        mainMenuStrip.Items.Add(CreateArchivoMenuItem());\n        archivoMenuItem.DropDownItems.Add(CreateAbrirMenuItem());\n        archivoMenuItem.DropDownItems.Add("-");\n        archivoMenuItem.DropDownItems.Add(CreateSalirMenuItem());\n    }\n\n    private void InitVisualizacion()\n    {\n        // this.Controls.Add(CreateMainPanel());\n        mainPanel.Controls.Add(CreateMainTabControl());\n        mainTabPage.Controls.Add(CreateActuacionesGrid());\n        mainTabPage.Text = "Actuaciones";\n        actuacionesGrid.Name = "actuacionesGrid";\n    }\n\n    private OpenFileDialog CreateOpenFileDialog()\n    {\n        if (openFileDialog == null)\n        {\n            openFileDialog = new OpenFileDialog();\n            openFileDialog.AutoUpgradeEnabled = true;\n            openFileDialog.Filter = "Archivos CSV, Excel (*.csv, *.xls, *.xlsx)|*.csv;*.xls;*.xlsx|Todos los archivos (*.*)|*.*";\n            openFileDialog.ValidateNames = true;\n        }\n        return openFileDialog;\n    }\n\n    private ToolStripMenuItem CreateAbrirMenuItem()\n    {\n        if (abrirMenuItem == null)\n        {\n            abrirMenuItem = new ToolStripMenuItem();\n            abrirMenuItem.Name = "abrirMenuItem";\n            abrirMenuItem.Text = "&Abrir...";\n            abrirMenuItem.Click += new EventHandler(abrirMenuItem_Click);\n            abrirMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.O)));\n        }\n        return abrirMenuItem;\n    }\n\n    private void abrirMenuItem_Click(object sender, EventArgs e)\n    {\n        DialogResult result = openFileDialog.ShowDialog();\n        if (result == DialogResult.OK)\n        {\n            bool ret = false;\n            string file = openFileDialog.FileName;\n            if (file.EndsWith(".csv"))\n            {\n                ret = CSVparser.parseCSV(file);\n            }\n            else\n            {\n                // Parse Excel file\n            }\n            string messageBoxText;\n            MessageBoxIcon icon;\n            if (ret)\n            {\n                messageBoxText = "Importaci\xc3\xb3n finalizada";\n                icon = MessageBoxIcon.Information;\n            }\n            else\n            {\n                messageBoxText = "La importaci\xc3\xb3n ha fracasado. Se ha producido un error.";\n                icon = MessageBoxIcon.Warning;\n            }\n            string caption = "AGAP Importaci\xc3\xb3n de datos";\n            MessageBoxButtons buttons = MessageBoxButtons.OK;\n            MessageBox.Show(messageBoxText, caption, buttons, icon);\n        }\n    }\n\n    private void CreateSalir()\n    {\n        mainMenuStrip.Items.Add(CreateSalirMenuItem());\n    }\n\n    private void CreateArchivoSalir()\n    {\n        mainMenuStrip.Items.Add(CreateArchivoMenuItem());\n        archivoMenuItem.DropDownItems.Add(CreateSalirMenuItem());\n    }\n\n    #region Creacion de controles\n    private MenuStrip CreateMainMenuStrip()\n    {\n        if (mainMenuStrip == null)\n        {\n            mainMenuStrip = new MenuStrip();\n            mainMenuStrip.Name = "mainMenuStrip";\n            mainMenuStrip.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;\n        }\n        return mainMenuStrip;\n    }\n\n    private ToolStripMenuItem CreateArchivoMenuItem()\n    {\n        if (archivoMenuItem == null)\n        {\n            archivoMenuItem = new ToolStripMenuItem();\n            archivoMenuItem.Name = "archivoToolStripMenuItem";\n            archivoMenuItem.Text = "&Archivo";\n\n        }\n        return archivoMenuItem;\n    }\n\n    private ToolStripMenuItem CreateSalirMenuItem()\n    {\n        if (salirMenuItem == null)\n        {\n            salirMenuItem = new ToolStripMenuItem();\n            salirMenuItem.Name = "salirToolStripMenuItem";\n            salirMenuItem.Text = "&Salir...";\n            salirMenuItem.Click += new EventHandler(salirMenuItem_Click);\n            salirMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.Q)));\n        }\n        return salirMenuItem;\n    }\n\n    private StatusStrip CreateMainStatusStrip()\n    {\n        if (mainStatusStrip == null)\n        {\n            mainStatusStrip = new StatusStrip();\n            mainStatusStrip.Name = "mainStatusStrip";\n            mainStatusStrip.BackColor = SystemColors.Window;\n            mainStatusStrip.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;\n            mainStatusStrip.Items.Add(CreateMainStatusLabel());\n        }\n        return mainStatusStrip;\n    }\n\n    private ToolStripStatusLabel CreateMainStatusLabel()\n    {\n        if (mainStatusLabel == null)\n        {\n            mainStatusLabel = new ToolStripStatusLabel();\n            mainStatusLabel.Name = "mainStatusLabel";\n            mainStatusLabel.BackColor = SystemColors.Window;\n        }\n        return mainStatusLabel;\n    }\n    private TableLayoutPanel CreateMainPanel()\n    {\n        if (mainPanel == null)\n        {\n            mainPanel = new TableLayoutPanel();\n            mainPanel.Name = "mainPanel";\n            mainPanel.Dock = DockStyle.Fill;\n            //mainPanel.FlowDirection = FlowDirection.TopDown;\n            mainPanel.Size = new Size(1280, 1024);\n            mainPanel.ColumnCount = 1;\n            mainPanel.RowCount = 3;\n        }\n        return mainPanel;\n    }\n\n    private TabControl CreateMainTabControl()\n    {\n        if (mainTabControl == null)\n        {\n            mainTabControl = new TabControl();\n            mainTabControl.Controls.Add(CreateMainTabPage());\n            //mainTabControl.Location = new Point(0, 0);\n            mainTabControl.Name = "mainTabControl";\n            mainTabControl.SelectedIndex = 0;\n            //this.mainTabControl.Size = new System.Drawing.Size(745, 559);\n            //mainTabControl.TabIndex = 0;\n            //mainTabControl.Size = new Size(1280, 1024);\n            mainTabControl.Dock = DockStyle.Fill;\n            //mainTabControl.Dock = DockStyle.Bottom | DockStyle.Top | DockStyle.Left;\n            //mainTabControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right ;\n            mainTabControl.MouseClick += new MouseEventHandler(mainTabControl_MouseClick);\n        }\n        return mainTabControl;\n    }\n\n    private void mainTabControl_MouseClick(object sender, MouseEventArgs e)\n    {\n        if (e.Button == MouseButtons.Right)\n        {\n            ContextMenuStrip cms = CreateMainTabControlContextMenuStrip();\n            cms.Show(mainTabControl, e.Location);\n        }\n        if (e.Button == MouseButtons.Middle)\n        {\n            if (mainTabControl.SelectedIndex != 0)\n            {\n                mainTabControl.TabPages.Remove(mainTabControl.SelectedTab);\n            }\n        }\n    }\n\n    private ContextMenuStrip CreateMainTabControlContextMenuStrip()\n    {\n        ContextMenuStrip cms = new ContextMenuStrip();\n        cms.Items.AddRange(new ToolStripMenuItem[] { CreateCloseTabMenuItem() });\n        return cms;\n    }\n\n    private ToolStripMenuItem CreateCloseTabMenuItem()\n    {\n        var closeTabMenuItem = new ToolStripMenuItem();\n        closeTabMenuItem.Text = "&Cerrar pesta\xc3\xb1a";\n        closeTabMenuItem.Click += new EventHandler(closeTabMenuItem_Click);\n        //closeTabMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.F4)));\n        return closeTabMenuItem;\n    }\n\n    private void closeTabMenuItem_Click(object sender, EventArgs e)\n    {\n        if (mainTabControl.SelectedIndex != 0)\n        {\n            mainTabControl.TabPages.Remove(mainTabControl.SelectedTab);\n        }\n    }\n\n    private TabPage CreateTabPage()\n    {\n        var tabPage = new TabPage();\n        //tabPage.Location = new Point(4, 22);\n        //tabPage.Padding = new Padding(3);\n        //tabPage.UseVisualStyleBackColor = true;\n        return tabPage;\n    }\n\n    private TabPage CreateMainTabPage()\n    {\n        if (mainTabPage == null)\n        {\n            mainTabPage = CreateTabPage();\n            mainTabPage.Name = "mainTabPage";\n            mainTabPage.Text = "Actuaciones";\n            //mainTabPage.TabIndex = 0;\n        }\n        return mainTabPage;\n    }\n\n    private DataGridView CreateGrid()\n    {\n        DataGridView grid = new DataGridView();\n        // Propiedades fijas\n        grid.AllowUserToOrderColumns = true;\n        grid.RowHeadersVisible = false;\n        grid.StandardTab = false;\n        grid.ReadOnly = true;\n        grid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;\n        grid.MultiSelect = false;\n        grid.ScrollBars = ScrollBars.Both;\n        grid.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells;\n        grid.BackgroundColor = SystemColors.Window;\n\n        // Propiedades dudosas\n        //grid.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;\n        grid.Dock = DockStyle.Fill;\n        //grid.Location = new Point(0, 0);\n        //grid.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;\n        grid.TabIndex = 0;\n        //grid.Size = new Size(1280, 1024);\n        //grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;\n        //grid.AutoSize = true;\n\n        //grid.PerformLayout();\n\n        return grid;\n    }\n\n    private DataGridView CreateActuacionesGrid()\n    {\n        if (actuacionesGrid == null)\n        {\n            actuacionesGrid = CreateGrid();\n            actuacionesGrid.MouseDown += new MouseEventHandler(actuacionesGrid_MouseDown);\n            actuacionesGrid.DataSource = ComunicacionBD.SelectActuaciones(db).Tables[0].DefaultView;\n            actuacionesGrid.ContextMenuStrip = CreateActuacionesContextMenuStrip();\n        }\n        return actuacionesGrid;\n    }\n\n    private ContextMenuStrip CreateActuacionesContextMenuStrip()\n    {\n        if (actuacionesContextMenuStrip == null)\n        {\n            actuacionesContextMenuStrip = new ContextMenuStrip();\n            actuacionesContextMenuStrip.Name = "actuacionesContextMenuStrip";\n            actuacionesContextMenuStrip.Items.AddRange(new ToolStripMenuItem[] { CreateVerTramitesMenuItem(),\n                CreateVerEncargosMenuItem(), CreateVerTrabajosMenuItem(), CreateVerDatosObraMenuItem()});\n        }\n        return actuacionesContextMenuStrip;\n    }\n\n    private ToolStripMenuItem CreateVerDatosObraMenuItem()\n    {\n        if (verDatosObraMenuItem == null)\n        {\n            verDatosObraMenuItem = new ToolStripMenuItem();\n            verDatosObraMenuItem.Name = "verDatosObraMenuItem";\n            verDatosObraMenuItem.Text = "Ver &datos de obra";\n            verDatosObraMenuItem.Click += new EventHandler(verDatosObraMenuItem_Click);\n            verDatosObraMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.D)));\n        }\n        return verDatosObraMenuItem;\n    }\n\n    private ToolStripMenuItem CreateVerTramitesMenuItem()\n    {\n        if (verTramitesMenuItem == null)\n        {\n            verTramitesMenuItem = new ToolStripMenuItem();\n            verTramitesMenuItem.Name = "verTramitesMenuItem";\n            verTramitesMenuItem.Text = "Ver &tr\xc3\xa1mites";\n            verTramitesMenuItem.Click += new EventHandler(verTramitesMenuItem_Click);\n            verTramitesMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.T)));\n        }\n        return verTramitesMenuItem;\n    }\n\n    private ToolStripMenuItem CreateVerEncargosMenuItem()\n    {\n        if (verEncargosMenuItem == null)\n        {\n            verEncargosMenuItem = new ToolStripMenuItem();\n            verEncargosMenuItem.Name = "verEncargosMenuItem";\n            verEncargosMenuItem.Text = "Ver &encargos";\n            verEncargosMenuItem.Click += new EventHandler(verEncargosMenuItem_Click);\n            verEncargosMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.E)));\n        }\n        return verEncargosMenuItem;\n    }\n\n    private ToolStripMenuItem CreateVerTrabajosMenuItem()\n    {\n        if (verTrabajosMenuItem == null)\n        {\n            verTrabajosMenuItem = new ToolStripMenuItem();\n            verTrabajosMenuItem.Name = "verTrabajosMenuItem";\n            verTrabajosMenuItem.Text = "Ver t&rabajos";\n            verTrabajosMenuItem.Click += new EventHandler(verTrabajosMenuItem_Click);\n            verTrabajosMenuItem.ShortcutKeys = ((Keys)((Keys.Control | Keys.W)));\n        }\n        return verTrabajosMenuItem;\n    }\n\n    #endregion\n\n    #region Event Handlers\n    private void actuacionesGrid_MouseDown(object sender, MouseEventArgs e)\n    {\n        if (e.Button == MouseButtons.Right)\n        {\n            var hti = actuacionesGrid.HitTest(e.X, e.Y);\n            actuacionesGrid.ClearSelection();\n            actuacionesGrid.Rows[hti.RowIndex].Selected = true;\n        }\n    }\n\n    private void verTramitesMenuItem_Click(object sender, EventArgs e)\n    {\n        // Coger la actuacion seleccionada.\n        //Actuacion act = (Actuacion) actuacionesGrid.CurrentRow.DataBoundItem;\n        string obraid = actuacionesGrid.CurrentRow.Cells["ObraId"].Value.ToString();\n\n        // Crear la pesta\xc3\xb1a.\n        var tabPage = CreateTabPage();\n        tabPage.Name = "tramitesTabPage" + obraid;\n        tabPage.Text = "Tr\xc3\xa1mites actuaci\xc3\xb3n " + obraid;\n        mainTabControl.TabPages.Add(tabPage);\n        mainTabControl.SelectedTab = tabPage;\n\n        // Crear el FlowLayoutPanel\n        //var panel = new FlowLayoutPanel();\n        //tabPage.Controls.Add(panel);\n\n        // Crear el panel con las labels de la actuacion\n        //panel.Controls.Add(CreateActuacionPanel(act));\n\n        // Crear la tabla\n        var grid = CreateTramitesGrid();\n        grid.DataSource = ComunicacionBD.SelectTramites(db, obraid).Tables[0].DefaultView;\n        tabPage.Controls.Add(grid);\n    }\n\n    private void verDatosObraMenuItem_Click(object sender, EventArgs e)\n    {\n        // Coger la actuacion seleccionada.\n        //Actuacion act = (Actuacion) actuacionesGrid.CurrentRow.DataBoundItem;\n        string obraid = actuacionesGrid.CurrentRow.Cells["ObraId"].Value.ToString();\n\n        // Crear la pesta\xc3\xb1a.\n        var tabPage = CreateTabPage();\n        tabPage.Name = "datosObraTabPage" + obraid;\n        tabPage.Text = "Datos de obra " + obraid;\n        mainTabControl.TabPages.Add(tabPage);\n        mainTabControl.SelectedTab = tabPage;\n\n        // Crear el FlowLayoutPanel\n        //var panel = new FlowLayoutPanel();\n        //tabPage.Controls.Add(panel);\n\n        // Crear el panel con las labels de la actuacion\n        //panel.Controls.Add(CreateActuacionPanel(act));\n\n        // Crear la tabla\n        var grid = CreateTramitesGrid();\n        grid.DataSource = ComunicacionBD.SelectDatosObra(db, obraid).Tables[0].DefaultView;\n        tabPage.Controls.Add(grid);\n    }\n\n\n    private Panel CreateActuacionPanel(Actuacion act)\n    {\n        var actuacionPanel = new FlowLayoutPanel();\n        actuacionPanel.FlowDirection = FlowDirection.LeftToRight;\n\n        var actuacionLabel = new Label();\n        actuacionLabel.Text = "Actuaci\xc3\xb3n: " + act.ActuacionId;\n\n        var descLabel = new Label();\n        descLabel.Text = "Descripci\xc3\xb3n: " + act.Descripcion;\n\n        actuacionPanel.Controls.Add(actuacionLabel);\n        actuacionPanel.Controls.Add(descLabel);\n        return actuacionPanel;\n    }\n\n    private DataGridView CreateTramitesGrid()\n    {\n        var grid = CreateG

Sin*_*atr 5

你必须使用TableLayoutPanel而不是FlowLayoutPanel.

FlowLayoutPanel用于形成一堆控件,一个接一个地解决环绕问题。 TableLayoutPanel是一个包含各种单元格操作的表格:垂直/水平延伸到更多单元格、调整大小、比例等。

对于您的任务,您将需要TableLayoutPanel

  • 只有一栏;
  • 3 行:用于菜单(自动调整大小)、用于DataGridView(我猜是在选项卡式窗格内?)(100%)和状态栏(自动调整大小)。

在此输入图像描述

然后将TableLayoutPanel对接设置为Fill,应该就差不多了。

提示:在将 row 设置为 之前,请确保将控件放入单元格内AutoSize

这里的要点是TableLayoutPanel可以分配指定的百分比(在我们的例子中100%或任何其他值都可以,因为只有 1 行请求大小百分比),并且如果面板大小更改,将增加/减少单元格大小。然后,您可以使用单元格以您喜欢的方式将控件停靠/锚定在单元格内。对于这一点,请参阅@Hassan Nisar的回答,尽管它已经被投票,但它不会以当前的形式解决您的问题,也许是有用的;-)。