Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect behavior of Panel on inherited Windows Form?

I need a workaround for incorrect behavior for a Panel on an inherited stock Windows Form. I have a couple buttons that are supposed to be anchored to the bottom right corner of the panel, but their locations vary in a manner I cannot predict on inherited forms. I've tried various combinations of Dock and Anchor properties, but nothing so far makes the buttons show up where they are supposed to. All controls are marked Protected.

Behavior is correct on the base form itself. The incorrect behavior happens only on inherited forms; the buttons are not anchored to their parent panel.

If I anchor the buttons to the top left, I can resize the inherited form bigger and eventually the buttons will be uncovered, somewhere outside the base form size. If I anchor the buttons to the bottom right, I have been unable to make the form big enough to ever uncover the buttons.

I've tried creating a custom panel that inherits Panel, and a GroupBox, but these didn't work any differently. I had the same luck putting the buttons directly on the form, without a container.

What I want: a Panel at the bottom of a resizable Form with my buttons in the lower right corner of it. The remainder of the form should be a resizable area for a DataGridView (I've already worked through the inheritance and docking problems with this one >:-/) The buttons should always be in the bottom right corner regardless of the window size. I don't want to resize the buttons.

If I have to resize the controls myself, I'm willing to do that. But if the framework will do it correctly, and I just need to learn how to use it properly, I would prefer the education.

I found this link that appears to be describing similar misbehavior: How to stop buttons from moving in inherited form. It hasn't been answered.


Here is some code extracted from the program I'm having a problem with.

Base form

// 
// refreshButton
// 
this.refreshButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.refreshButton.Location = new System.Drawing.Point(200, 4);
this.refreshButton.Name = "refreshButton";
this.refreshButton.Size = new System.Drawing.Size(75, 23);
this.refreshButton.TabIndex = 5;
this.refreshButton.Text = "&Refresh";
this.refreshButton.UseVisualStyleBackColor = true;
// 
// saveButton
// 
this.saveButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.saveButton.Location = new System.Drawing.Point(281, 5);
this.saveButton.Name = "saveButton";
this.saveButton.Size = new System.Drawing.Size(75, 23);
this.saveButton.TabIndex = 4;
this.saveButton.Text = "&Save";
this.saveButton.UseVisualStyleBackColor = true;
// 
// buttonPanel
// 
this.buttonPanel.Controls.Add(this.saveButton);
this.buttonPanel.Controls.Add(this.refreshButton);
this.buttonPanel.Dock = System.Windows.Forms.DockStyle.Bottom;
this.buttonPanel.Location = new System.Drawing.Point(0, 231);
this.buttonPanel.Name = "buttonPanel";
this.buttonPanel.Size = new System.Drawing.Size(360, 31);
this.buttonPanel.TabIndex = 6;

Inherited form (resized to fit my data contents)

// 
// refreshButton
// 
this.refreshButton.Location = new System.Drawing.Point(286, 7);
this.refreshButton.TabIndex = 0;
// 
// saveButton
// 
this.saveButton.Location = new System.Drawing.Point(367, 7);
this.saveButton.TabIndex = 1;
// 
// buttonPanel
// 
this.buttonPanel.Location = new System.Drawing.Point(0, 232);
this.buttonPanel.Size = new System.Drawing.Size(445, 33);

Edit: some additional data after playing around with it more. The problem seems to a bug in the Visual Studio 2005 designer, or strange interaction between the designer and C# compiler. When I create my inherited form, the buttons are relocated to some arbitrary (but not random!) location off the edge of the form. The buttons are still available and selectable using the control dropdown of the VS Properties window.

I can select the controls and repair their locations to have them show up in the correct place on the design surface and at runtime. They even move correctly when I resize the form. However, after a build, the designer modifies the visible Location of the buttons. The code in the *.Designer.cs file is still correct, but the button properties are changed. In the inherited form from above, the designer's Location properties for the refreshButton and saveButton are 371,7 and 452,7 even though the containing panel is only 445 pixels wide.

At least this new information gives me a partial fix, but I still don't know why it happens.


Answer: Well, it turns out the buttons actually do stay anchored to the panel. Unfortunately, the designer changes the anchor location to be somewhere off the visible area of the form. The conclusion is that the VS2005 designer is unreliable and doesn't handle inherited forms 100% correctly.

The workaround I deduced was to override the OnResize() method in my base form and correct the buttons' locations there. It's a small hack, but meets my needs.

/// <summary>
/// Must handle some layout operations manually because Visual Studio 
/// 2005 arbitrarily changes some properties of inherited controls.
/// </summary>
/// <param name="e">Data for event.</param>
protected override void OnResize(EventArgs e)
{
    base.OnResize(e);

    // Move Refresh and Save buttons to lower right corner of button panel.
    saveButton.Top = buttonPanel.Bounds.Height -
        (saveButton.Height + saveButton.Padding.Bottom + saveButton.Margin.Bottom);
    saveButton.Left = buttonPanel.Bounds.Width -
        (saveButton.Width + saveButton.Padding.Right + saveButton.Margin.Right);
    refreshButton.Top = saveButton.Top;
    refreshButton.Left = saveButton.Left -
        (refreshButton.Width + refreshButton.Padding.Right + refreshButton.Margin.Right);
}
like image 537
Suncat2000 Avatar asked Feb 11 '11 16:02

Suncat2000


1 Answers

Let's see some code that duplicates the behavior. This code doesn't:

using System;
using System.Drawing;
using System.Windows.Forms;

class FormBase : Form
{
    public FormBase()
    {
        Panel panel;
        Controls.Add(panel = new Panel { Dock = DockStyle.Bottom, Height = 120, BackColor = Color.LightGray });
        panel.Controls.Add(new Button { Text = "Button 1", Anchor = AnchorStyles.Bottom | AnchorStyles.Right, Location = new Point(panel.ClientSize.Width - 80, panel.ClientSize.Height - 60) });
        panel.Controls.Add(new Button { Text = "Button 2", Anchor = AnchorStyles.Bottom | AnchorStyles.Right, Location = new Point(panel.ClientSize.Width - 80, panel.ClientSize.Height - 30) });
    }
}

class FormInherited : FormBase
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new FormInherited());
    }
}
like image 181
Tergiver Avatar answered Nov 02 '22 05:11

Tergiver