之前已经发生了很多次,但我从来没有费心去弄清楚原因,现在我已经厌倦了:
例如,我从RichTextBox或Panel派生了一个类,我重建了我的项目以将该类添加到VS设计器工具箱中,然后我拖动&将自定义用户控件拖放到窗体。一切正常,我可以运行我的项目......
当我通过设计器编辑Form或自定义用户控件的属性时出现问题。有时,设计器会从其代码隐藏中删除初始化行,从而导致设计器和可执行文件中出现异常,因为控件仍然未初始化。
换句话说,从Form1.Designer.cs中删除以下行:
this.customRichTextBox1=new CustomRichTextBox();
没有其他行从代码隐藏中删除,因此自定义控件的属性仍然设置,尽管变量保持未初始化。
我的解决方案一直是在设计器代码隐藏中手动初始化我的用户控件,但设计师最终会再次删除它。
我相信当我通过设计器构建自定义UserControl时不会发生这种情况(但我并不完全确定)。只有当我手动定义类似下面的内容时才会发生这种情况:
class CustomRichTextBox:RichTextBox{}
这太烦人了。我做错了什么?
正如@Cody所要求的,以下是重现问题的步骤。我正在使用VS2010,但我认为自2005年以来我遇到了这个问题。
步骤1.创建新的Windows窗体应用程序,任何框架
步骤2.在主Form类下面添加以下类:(恰好这次是这个导致我出现此问题的控件。)
class CustomRichTextBox : RichTextBox
{
Timer tt = new Timer();
internal CustomRichTextBox()
{
tt.Tick += new EventHandler(tt_Tick);
tt.Interval = 200;
}
protected override void OnTextChanged(EventArgs e)
{
tt.Stop();
tt.Start();
}
void tt_Tick(object sender, EventArgs e)
{
System.Diagnostics.Trace.WriteLine("Hello world!");
}
}
步骤3.按F6重建。
步骤4.通过从工具箱中拖放,将CustomRichTextBox控件添加到表单。
步骤5.如果您愿意,可以按F5测试应用程序,但它应该可以工作。关闭正在运行的应用程序。
步骤6.按F6重建,此时,设计人员应该崩溃并显示以下消息:“变量'customRichTextBox1'未声明或从未分配过。” (在一种情况下,整个VS完全崩溃,但错误通常包含在设计者中。)
步骤7.要解决问题,请进入代码隐藏并初始化变量,但下次重建时,初始化行将消失。
答案 0 :(得分:14)
感谢所有尝试回答我的问题并发表评论的人,帮助我诊断和解决问题。
在控件的构造函数中使用“internal”关键字时会出现问题。将其更改为“公共”可以解决问题。这种行为的原因可能是Designer自己的类无法看到构造函数,因为它们不在我的类的命名空间内,除非它被标记为public。这一切都有道理,我将从现在开始使用public关键字。
该类不需要位于其自己的单个文件中,也不需要作为其他答案建议的文件中的第一个声明的类。
以下类运行良好,因为构造函数的关键字已更改为public。
class CustomRichTextBox : RichTextBox
{
Timer tt = new Timer();
public CustomRichTextBox()
{
tt.Tick += new EventHandler(tt_Tick);
tt.Interval = 200;
}
protected override void OnTextChanged(EventArgs e)
{
tt.Stop();
tt.Start();
}
void tt_Tick(object sender, EventArgs e)
{
System.Diagnostics.Trace.WriteLine("Hello world!");
}
}
答案 1 :(得分:0)
您的构建设置为Debug还是Release? 我认为它是发行版,因为我认为编译器会优化代码并删除设计器生成的行。
答案 2 :(得分:0)
您是否尝试将控制代码放在自己的文件中?我甚至在使用表单设计器时遇到了问题,因为设计器代码不是文件中的第一类。
答案 3 :(得分:0)
我有一个类似的问题,这个帖子帮我解决了。我有一个扩展ComboBox的CustomControl,该类包含一个内部私有类YearItem。我试图强调仅理解问题和解决方案所需的代码。
public class YearsCbo : ComboBox //Inherits ComboBox
{
public YearsCbo() {
fill();
}
private void fill() { // <<<=== THIS METHOD ADDED ITEMS TO THE COMBOBOX
for(int idx = 0; idx < 25; idx++) {
this.Items.Add(new YearItem());
}
}
// Other code not shown
private class YearItem {} // <<<=== The VS designer can't access this class and yet
// it generated code to try to do so. That code then fails to compile.
// The compiler error rightfully says it is unable to access
// the private class YearItem
}
我可以将控制YearsCbo拖放到表单上并且它正常工作,但在我返回并编辑表单后,VS设计器生成了无法编译的代码。违规代码是这样的:
Dim YearItem1 As my.ns.YearsCbo.YearItem = New my.ns.YearsCbo.YearItem()
Dim YearItem2 As my.ns.YearsCbo.YearItem = New my.ns.YearsCbo.YearItem()
// This was repeated 25 times because in my constructor I created 25 of these
Me.YearsCbo1.Items.AddRange(New Object() {YearItem1, 2, 3, ..., YearItem25 });
请注意,设计者生成了试图访问私有类的代码。它不需要这样做,但由于某种原因它确实如此。
通过反复试验和帖子:How to tell if .NET code is being run by Visual Studio designer提出了一个解决方案:
我添加了一个属性来判断我是否在设计师中运行。
public bool HostedDesignMode
{
get
{
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
return true;
else
return false;
}
}
我还更改了构造函数,使其不调用fill(),因此当设计器运行时,ComboBox中没有项目,因此设计人员不需要手动创建这些项目。
“固定”代码如下所示:
public class YearsCbo : ComboBox //Inherits ComboBox
{
public YearsCbo() {
if ( ! HostedDesignMode ) {
fill();
}
}
private class YearItem {} // <<<=== Now the VS Designer does not try to access this
}
此代码是在Win7x64操作系统上使用VS2012 Premium编写的(如果重要的话)。