【问题标题】:Why does Visual Studio Designer instantiate a base class for controls?为什么 Visual Studio 设计器要实例化控件的基类?
【发布时间】:2012-09-20 01:58:07
【问题描述】:

我有一个表单,它基于我拥有的另一种标准表单(支持透明度的表单),它在运行时通过自己的类型标识自己。然而,在设计器中,我设置了一些消息框输出,它们在设计时显示它在设计器控件堆栈顶部标识为父类型。

示例代码

Public Class SpecificForm
    Inherits GenericForm
    Implements IUsefulInterface
    ...
End Class

Public Class GenericForm
    Inherits System.Windows.Forms.Form
    ...
End Class

我在表单上有一些控件,可以让它们的父级知道如何正确绘制。在运行时它工作正常,因为特定类型实现了一个携带绘图信息的接口。循环通过父母产量

"Control1" As System.Windows.Forms.Control, parented by
"MainForm1" As SpecificForm, parented by
Nothing

作为设计时间,虽然在父母之间循环会产生

"Control1" As System.Windows.Forms.Control, parented by
"MainForm1" As GenericForm, parented by
"" As System.Windows.Forms.Design.DesignerFrame+OverlayControl, parented by
"" As System.Windows.Forms.Design.DesignerFrame, parented by
"" As System.Windows.Forms.Control, parented by
Nothing

在运行时 MainForm 标识为 SpecificForm 类型,在设计时由设计器托管是可以理解的,但它现在标识为 GenericType。

【问题讨论】:

    标签: .net visual-studio instantiation windows-forms-designer


    【解决方案1】:

    我尊重您提出这个问题的事实。但是,不要误会我的意思,这个问题有点天真。您观察到了大多数人没有观察到的现象(恭喜您作为 WinForms 程序员已接近成熟!--我是认真的,而不是讽刺的......)

    现在,我说你的问题有点幼稚,因为这就像在问“为什么圆这么圆?”。下一个解释可能听起来有点多余,但它是唯一的一个:

    在设计时,在SpecificForm 的设计器中,您不是在“运行”SpecificForm 的实例,而是您正在设计一个基于 GenericForm 的原型,并且实际上是您正在“运行”的控件的类型(即,在运行时上下文中。)

    我再说一遍,SpecificForm 的设计者没有SpecificForm“运行”的实例,而是GenericForm 的实例。设计器中不存在 SpecificForm 实例,因为,嗯.. 您正在设计它!!!

    我使用这个确切的解释来引导另一个用户理解他所看到的: https://stackoverflow.com/a/12499053/1426433。但是你自己注意到了。

    【讨论】:

    • 感谢您提供此信息。这很令人沮丧,因为您无法将 GenericForm 抽象化,但现在至少我明白为什么必须这样做了。
    【解决方案2】:

    此外,为了进一步记录您所看到的内容,您可以进行以下实验:

    创建一个名为FooUserControl 的简单UserControl,它仅用于显示一个消息框,其中包含创建位置的堆栈跟踪:

    using System;
    using System.Windows.Forms;
    
    namespace Test {
        public partial class FooUserControl : UserControl {
            public FooUserControl() {
                InitializeComponent();
                MessageBox.Show(Environment.StackTrace);
            }
        }
    }
    

    构建您的项目,然后打开您的任何表单设计器,例如,打开一个名为 FooForm 的表单的设计器(它可能是您的 SpecificForm 或您正在创作的任何其他控件的设计器。)将 FooUserControl 拖放到设计器表面上,您会看到一个消息框,上面写着类似的内容;

    每次重新打开此设计器时,您都会看到如下内容:

    然而,每次“运行”应用程序时,您都会看到如下内容:

    这就是说,Windows 窗体设计器甚至没有执行任何名为FooForm.InitializeComponent() 的方法。该方法仅在运行时执行,因为它仅在运行时执行正在设计的控件的构造函数,然后调用FooForm.InitializeComponent()

    信不信由你,设计师所做的实际上是逐句解析 FooForm.Designer.cs 文件中的行(可能使用 CodeDOM)。

    希望这些解释有所帮助。

    【讨论】:

    • 虽然我很荣幸在 WinForms 中被授予“成熟”这样的称号,但这对于设计师来说仍然是一个非常不幸的架构决定。我一直对设计师坚持以混合编译的 dll 和伪脚本方式运行感到沮丧。 DLL 缓存在设计器中导致了很多问题,我希望整个事情都被虚拟化并且完全像设计器中的脚本一样。我知道他们可能在追求性能,并且知道有些人将他们所有的业务逻辑都放在一个表单中,但这只是另一个选择缺陷的例子。
    • 我会将此标记为答案,因为这正是所提问题的答案。
    猜你喜欢
    • 2010-10-05
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-06
    相关资源
    最近更新 更多