6
votes

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);
}
4
Does the problem occur with VS2010? Try the express edition if you don't have it.Tergiver
Thanks, but I'm using VS2005 Professional. Upgrading is not an affordable option.Suncat2000
It would be useful to know if it's something that has been fixed in a later version.Tergiver
Same sympthoms in V2013, "solved" by left, bottom anchor instead of right, bottom...kristian mo

4 Answers

2
votes

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());
    }
}
1
votes

I have had very unreliable results with anchoring on inherited forms.

I've found it seems to all work better if you dock controls where ever possible (instead of anchoring), even if this means placing controls on panels within panels. (You did say work around right?!)

0
votes

I had the same problem with Panels.
To fix this, first set the Anchor Property in the Designer on the parent Form.
Then, go to BUILD -> REBUILD SOLUTION.

This should also work in older versions of Visual Studio.

EDIT: For Buttons, you need to Handle the Resize event, as other answers have suggested.

0
votes

I'm having VS 2012, it even contain inherited forms, but i have same issue, no matter if i inherit it my self or use template... the anchor goes wrong, and the position change multiplied, like if i have only form, it goes 1px for 1px, if i have also a panel, it move 2 for 1px, if i have 2 panel it move 3... i didn't measure it, but it look like, like that...


Kinda An Answer:

A minute ago, i test some thing, i set modifier of all nested container, to some thing accessible, then the child form generate more code, run time was correct, but now the designer after each compile, repositioned my controls inside the form, so regarding that, i also add another panel in child form, and set it to dock mode, and then anchor my control to it, then it fixed, previously even anchoring went wrong...