Winform自定义控件 - 设计器随机停止初始化/调用构造函数

5
这是一个令人发狂的噩梦,我急需帮助。我到处寻找帮助,但没有一种方法可以永久解决问题。
我开发了一些自定义控件,这些控件扩展了按钮、用户控件等。我有一个问题,VS2010会随机地完全删除调用自定义控件构造函数的代码行(由Windows Forms生成器编辑),因此无法查看设计视图。应用程序仍然可以完全构建和运行。
我已经测试并排除了以下问题:
  1. Public constructor - evidently having a non public (internal, etc.) constructor can cause issues like this. I've checked 100 times - ALL the custom controls have public constructors.

  2. Empty constructors - in addition to being public, it needs to be empty.

  3. No calling anything that could fail in the constructor - I've reduced ALL constructors for custom controls to empty

     Name() { }
    calls. No luck there.

  4. Namespaces - evidently being in a different namespace can cause problems? I'm in the same one, and the files are IN THE SAME PROJECT.

  5. Unload project. Close VS. Delete .suo intellisense file. Delete obj files. Open VS. Reload project. Rebuild project. Still no luck.

这真的非常令人沮丧。我已经到了想要放弃使用自定义控件并手动逐个设置每个控件皮肤的地步,以避免这种情况。有没有人知道是什么原因引起的?


一些可能无用的想法:您是否已安装了最新的 VS2010 服务包?您的空公共构造函数是否调用:base()(不确定是否必要)?如果创建全新的空白 UserControl,是否会出现这种情况? - AndrewS
你需要查找被诊断吞咽的异常。启动另一个VS实例,并使用"工具+附加到进程"将其附加到第一个实例上。在调试菜单中,选择"异常",勾选CLR异常的"抛出"框。回到第一个实例并开始设计。 - Hans Passant
请务必仔细检查您的SO用户名对代码的影响。 - Hans Passant
设计文件明确警告您不要做您所做的事情。你会因为它出了问题而感到惊讶吗? - Tom W
@TomW - 我在我的问题中已经说过了 - 我没有编辑.designer.cs文件,该文件中缺少的构造函数调用是问题的症状。 - trycatch
提到设计师的部分不够清晰。我和至少另外一位发帖人都认为,当你说一行代码消失了时,你期望它在那里,因为你曾经放过它。我无法编辑评论,如果我删除它,对话就没有意义了。 - Tom W
1个回答

3

首先,问题是...你正在将内容放置在".designer.cs"代码中...不要这么做。那是微软的沙盒。当 WinForms 表单和可视化控件被创建时,它们通常处于一个“集合”中,如

MyForm.cs   (place for YOUR code)
   MyForm.designer.cs  (Microsoft's sandbox area for designer stuff)
   MyForm.resx   (Resource file -- if used, specific to this form).

说到这里,如果您通过常规的“设计器”打开WinForm,并右键单击“查看代码”,它将显示MyForm.cs代码集。请注意,它是一个


PARTIAL PUBLIC CLASS MyForm : Window
{
   public MyForm()
   {
      InitializeComponent();
   }
}

"MyForm.Designer.cs"和"MyForm.cs"基本上是一起配合工作的。除了Microsoft的东西之外,还有你自己的东西。根据你想要做什么,你可以在这个整体表单的构造函数中添加功能。如果你需要准备一些数据连接、查询数据、填充列表或者其他用于表单的操作,你可以在这里进行(在之前或之后都可以)。
   public MyForm()
   {
      DoYourStuff();
      InitializeComponent();
      // or DoYourStuff here after designer controls are all initialized.
   }

   private void DoYourStuff()
   {  put it here }

有时候,您可能希望在整个表单加载完成后但在最终呈现给用户之前执行某些操作。有时,我实际上会在整个表单(包括表单和所有控件)的LOADED完成后放置一个挂钩。因此,我会做类似于以下的操作:

public MyForm()
{

   Load += MyAfterInitializeComponents;
   InitializeComponent();
}


private void MyAfterInitializeComponents(object sender, EventArgs e)
{  
   DoYourStuff(); 
}

如果您有特定的操作需求,可以提供一些示例代码,以帮助在您的基于窗口的代码中进行集成。

正如我在问题中所说,我没有修改.designer.cs文件——designer.cs文件自己进行了修改,以便不调用我的自定义控件的构造函数,这使得该控件无法显示。我将在我的代码上测试您的解决方案——结果发现我遇到的问题是一个重写的OnLoad函数,其中有一个DoStuff()引起了问题——我认为OnLoad只会在运行时发生;解决方案是将DoStuff放在if(!DesignMode)内。添加到Load的函数只有在!DesignMode下才会被调用? - trycatch
@trycatch... 你现在好了吗?从你的评论中有点不太清楚。我使用 hooks 通过 += 事件处理程序来执行正常操作,除此之外,我还想运行 += hook(根据我的示例)。 - DRapp
我目前正在使用if(!DesignMode)来包围我的代码,以避免它崩溃;这个方法虽然有效,但感觉有些笨拙。所以我一定会尝试一下你的Load += Foo()。我之前一直在使用override OnLoad(),但显然当你这样做并在设计视图中打开表单时,OnLoad会被调用。我需要测试一下Load+=是否不会在DesignMode下执行。 - trycatch
好的,我收回之前的话;两种方法都没有完全起作用。我的一个控件又出问题了。我添加了try/catch并尝试将控件添加到新对话框中 - 我正在打印堆栈跟踪,并且无论我使用哪种方式,它绝对会进入我的初始化代码。使用if !DesignMode,它在我的堆栈跟踪中说DesignMode.ToString()为false...使用Load +=它也会进入代码。到底发生了什么?这个函数在整个项目中没有被引用。 - trycatch
值得一提的是,我可以在设计模式下正常查看控件...? - trycatch
算了,不用理会。愚蠢的错误。我开始讨厌自定义控件了——太容易完全搞砸了。:/ - trycatch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接