【问题标题】:Incorrect behavior of Panel on inherited Windows Form?Panel 在继承的 Windows 窗体上的行为不正确?
【发布时间】:2011-06-25 16:47:05
【问题描述】:

我需要一个解决方法来解决继承的库存 Windows 窗体上的面板的错误行为。我有几个按钮应该锚定在面板的右下角,但是它们的位置以我无法在继承的表单上预测的方式变化。我已经尝试了 Dock 和 Anchor 属性的各种组合,但到目前为止还没有使按钮显示在它们应该显示的位置。所有控件都标记为受保护。

base 表单本身的行为是正确的。错误行为仅发生在 inherited 表单上;按钮没有锚定到它们的父面板。

如果我将按钮锚定在左上角,我可以将继承的表单调整得更大,最终按钮将在基本表单大小之外的某个位置被发现。如果我将按钮固定在右下角,我将无法使表单大到足以露出按钮。

我尝试创建一个继承 Panel 和 GroupBox 的自定义面板,但它们的工作方式没有任何不同。我有同样的运气将按钮直接放在表单上,​​没有容器。

我想要的:一个可调整大小的表单底部的面板,我的按钮在它的右下角。表单的其余部分应该是 DataGridView 的可调整大小区域(我已经解决了这个问题的继承和对接问题>:-/)无论窗口大小如何,按钮都应该始终位于右下角。我不想调整按钮的大小。

如果我必须自己调整控件的大小,我愿意这样做。但如果框架能正确地做到这一点,我只需要学习如何正确使用它,我更喜欢教育。

我发现这个链接似乎描述了类似的不当行为:How to stop buttons from moving in inherited 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;

继承的表单(调整大小以适合我的数据内容)

// 
// 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);

编辑:多玩一些额外的数据。这个问题似乎是 Visual Studio 2005 设计器中的一个错误,或者是设计器与 C# 编译器之间的奇怪交互。当我创建继承的表单时,按钮会重新定位到表单边缘的某个任意(但不是随机!)位置。这些按钮仍然可用,并且可以使用 VS 属性窗口的控制下拉菜单进行选择。

我可以选择控件并修复它们的位置,以使它们显示在设计图面和运行时的正确位置。当我调整表单大小时,它们甚至可以正确移动。但是,在构建之后,设计者会修改按钮的 可见 位置。 *.Designer.cs 文件中的代码仍然正确,但按钮属性发生了变化。在从上面继承的表单中,refreshButton 和 saveButton 的设计器的 Location 属性是 371,7 和 452,7,即使包含面板只有 445 像素宽。

至少这个新信息给了我一个部分修复,但我仍然不知道为什么会发生。


答案:嗯,事实证明按钮实际上确实固定在面板上。不幸的是,设计者将锚点位置更改为表单可见区域之外的某个位置。结论是 VS2005 设计器不可靠,不能 100% 正确处理继承的表单。

我推断出的解决方法是在我的基本表单中覆盖 OnResize() 方法并更正按钮的位置。这是一个小技巧,但可以满足我的需求。

/// <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);
}

【问题讨论】:

  • VS2010是否出现问题?如果没有,请尝试使用 Express Edition。
  • 谢谢,但我使用的是 VS2005 Professional。升级不是一个负担得起的选择。
  • 了解它是否已在更高版本中修复会很有用。
  • V2013 中的相同症状,通过左侧、底部锚点而不是右侧、底部锚点“解决”...

标签: c# winforms inheritance controls anchor


【解决方案1】:

让我们看看一些重复该行为的代码。此代码不会:

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

【讨论】:

  • 已编辑问题以包含相关代码。看起来像一个设计错误。
  • 代码继承工作正常。视觉(设计器)继承不可靠。
【解决方案2】:

我在继承的表单上锚定的结果非常不可靠。

我发现,如果您尽可能将控件停靠(而不是锚定),这似乎一切都会更好,即使这意味着将控件放置在面板内的面板上。 (你确实说解决方法对吗?!)

【讨论】:

    【解决方案3】:

    我在使用面板时遇到了同样的问题。
    要解决此问题,首先在父窗体的设计器中设置锚属性。
    然后,转到构建 -> 重建解决方案

    这也应该适用于旧版本的 Visual Studio。

    编辑: 对于按钮,您需要处理 Resize 事件,正如其他答案所建议的那样。

    【讨论】:

      【解决方案4】:

      我有 VS 2012,它甚至包含继承的表单,但我有同样的问题,无论我是自己继承还是使用模板......锚出错了,位置变化成倍增加,就像我只有形式,1px 移动 1px,如果我还有一个面板,它移动 2 移动 1px,如果我有 2 个面板移动 3...我没有测量它,但它看起来像那样.. .


      有点答案:

      一分钟前,我测试了一些东西,我将所有嵌套容器的修饰符设置为一些可访问的东西,然后子窗体生成更多代码,运行时间是正确的,但现在设计器在每次编译后重新定位我的控件表单,所以关于这一点,我还在子表单中添加了另一个面板,并将其设置为停靠模式,然后将我的控件锚定到它,然后它修复了,以前甚至锚定都出错了......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-18
        • 2014-05-24
        相关资源
        最近更新 更多