I created a class derived from System.Windows.Forms.ContextMenuStrip class, not as a user control, just a plain .cs class with a constructor and one event handler.
我创建了一个派生自System.Windows.Forms.ContextMenuStrip类的类,而不是用户控件,只是一个带有构造函数和一个事件处理程序的普通.cs类。
When I drag this class from the Toolbox onto the designer, it creates a private member for it and a couple of properties, but does not instantiate an object.
当我将这个类从工具箱拖到设计器上时,它会为它创建一个私有成员和几个属性,但不会实例化一个对象。
Thus, at runtime I get "Object reference not set to an instance of an object.", because the designer never generates the line:
因此,在运行时我得到“对象引用未设置为对象的实例。”,因为设计者从不生成该行:
this.searchGridContextMenu1 = new SearchGridContextMenu();
this.searchGridContextMenu1 = new SearchGridContextMenu();
inside InitializeComponent.
It used to generate this line, as a matter of fact, I keep putting it back in from my Vault repository, but the designer just "eats it" again.
它曾用于生成这一行,事实上,我一直把它从我的Vault存储库中重新插入,但设计师只是“再次”使用它。
Update: I now tried creating a User Control using the same class and it has the same problem just doing that.
更新:我现在尝试使用相同的类创建用户控件,它只是这样做有同样的问题。
5 个解决方案
#1
I cross-posted this comment on another question but since this is related here it is again.
我在另一个问题上交叉发表了这条评论,但由于这与此相关,因此它又是。
When a User Control won't load into the Visual Studio designer here is what you need to do. These instruction are for vb.net project but c# should be similar. Also, before doing this close all open windows (or at least the source and designer files of the control you are working on.)
当用户控件无法加载到Visual Studio设计器中时,您需要执行此操作。这些指令适用于vb.net项目,但c#应该类似。此外,在此之前关闭所有打开的窗口(或至少您正在处理的控件的源和设计器文件。)
One last thing. The FIRST thing you should do is ensure that restarting visual studio doesn't fix the problem. If not you can try the steps that follow. These instructions assume that the errant user controls are in control library project in visual studio. If not you should be able to adjust the directions a bit to get it to work but it is much easier when the control is in its own project.
最后一件事。您应该做的第一件事是确保重新启动visual studio不能解决问题。如果没有,您可以尝试以下步骤。这些说明假定错误的用户控件位于visual studio中的控件库项目中。如果没有,你应该能够稍微调整方向以使其工作,但是当控件在自己的项目中时更容易。
Do the following:
请执行下列操作:
- Make the control library your startup project.
- Open the properties for the control library project and click on the debug tab.
- Under Start Action click the Start external program option and browse to the Visual Studio executable.
使控件库成为您的启动项目。
打开控件库项目的属性,然后单击调试选项卡。
在“开始操作”下,单击“启动外部程序”选项并浏览到Visual Studio可执行文件。
NOTE: what this means is that when you run your solution it will fire up another instance of Visual Studio instead of actually running your solution. The First Instance of Visual Studion (INSTANCE_1) will "host" a second instance of visual studio (INSTANCE_2) when you run it.
注意:这意味着当您运行解决方案时,它将启动另一个Visual Studio实例,而不是实际运行您的解决方案。 Visual Studion的第一个实例(INSTANCE_1)将在您运行时“托管”Visual Studio的第二个实例(INSTANCE_2)。
- Run your solution. INSTANCE_2 will load.
- Switch back to INSTANCE_1.
- In INSTANCE_1 hit CTRL-ALT-E. This will open up the exceptions dialog box. Check On the THROWN column checkbox next to Common Language Runtime Exceptions.
运行您的解决方案INSTANCE_2将加载。
切换回INSTANCE_1。
在INSTANCE_1中按CTRL-ALT-E。这将打开例外对话框。选中Common Language Runtime Exceptions旁边的THROWN列复选框。
NOTE: This will ensure that INSTANCE_1 will BREAK at ANY runtime error even if it is hit in a try block.
注意:这将确保INSTANCE_1在任何运行时错误都会发生故障,即使它在try块中命中也是如此。
- Switch to INSTANCE_2. In Solution Explorer double-click to open the errant user control.
切换到INSTANCE_2。在解决方案资源管理器中,双击以打开错误的用户控件。
You should find that INSTANCE_1 OF Visual Studio should have stopped at the line of code that caused the designer to not load the control. Fix the code (which usually means testing for IsNot Nothing before references an object properties...but could mean other things.)
您应该会发现,INSTANCE_1 OF Visual Studio应停止在导致设计器无法加载控件的代码行中。修复代码(这通常意味着在引用对象属性之前测试IsNot Nothing ......但可能意味着其他事情。)
Also, sometimes I find that the control WILL load in INSTANCE_2 instead of breaking on an error in INSTANCE_1. In that case just stop debugging...close INSTANCE_2. Save/Restart INSTANCE_1 and your problem will often have gone away.
此外,有时我发现控件将在INSTANCE_2中加载,而不是在INSTANCE_1中打破错误。在这种情况下,只需停止调试...关闭INSTANCE_2。保存/重新启动INSTANCE_1,您的问题通常会消失。
The lesson is this. User Control MUST be able to load/reference all objects and their members in order to load it into the designer. So for User Controls that will be placed onto other containers I will usually design events to notify the parent rather than trying to push objects into the child control.
教训就是这样。用户控件必须能够加载/引用所有对象及其成员,以便将其加载到设计器中。因此,对于将放置在其他容器上的用户控件,我通常会设计事件来通知父级而不是尝试将对象推送到子控件中。
Hope this helps for future reference on this old question.
希望这有助于将来参考这个老问题。
Seth
#2
Did I read this right? Visual Studio deletes the line that constructs the instance of your control?
我读过这个吗? Visual Studio是否删除构造控件实例的行?
Is your constructor public? At some point I changed the accessibility of my constructor from public to internal - trying to be good, stop the pesky users from accessing things they shouldn't - but then I suffered from the same effects that you describe, I kept having to add my constructor back into InitializeComponent.
你的构造函数是公开的吗?在某些时候,我将构造函数的可访问性从公共更改为内部 - 试图变得更好,阻止讨厌的用户访问他们不应该访问的东西 - 但后来我遭受了与您描述的相同的影响,我不得不添加我的构造函数回到InitializeComponent。
It took me months to realise my mistake...just kept thinking it was a bug in Visual Studio. Changed it back to public and no problems.
我花了几个月才意识到自己的错误......只是一直认为这是Visual Studio中的一个错误。将其更改回公众并没有问题。
#3
Inheriting from the control isn't enough. This is the bare minimum that I had to implement to make it work:
继承控制是不够的。这是我必须实现的最低限度才能使其工作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WinForms
{
class Foo : System.Windows.Forms.ContextMenuStrip
{
public Foo()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}
#4
This problem occurs when InitializeComponent () crosses with base and inherited components. Solution is call the component's designer's method. Otherwise the base method will be called.
当InitializeComponent()与基本和继承的组件交叉时,会发生此问题。解决方案是调用组件的设计者方法。否则将调用基本方法。
public Form() { this.InitializeComponent(); // base.InitializeComponent <-- default one is thisone }
#5
changing my parameterless constructor from internal to public has solved the problem
将无参数构造函数从内部更改为公共已解决了该问题
#1
I cross-posted this comment on another question but since this is related here it is again.
我在另一个问题上交叉发表了这条评论,但由于这与此相关,因此它又是。
When a User Control won't load into the Visual Studio designer here is what you need to do. These instruction are for vb.net project but c# should be similar. Also, before doing this close all open windows (or at least the source and designer files of the control you are working on.)
当用户控件无法加载到Visual Studio设计器中时,您需要执行此操作。这些指令适用于vb.net项目,但c#应该类似。此外,在此之前关闭所有打开的窗口(或至少您正在处理的控件的源和设计器文件。)
One last thing. The FIRST thing you should do is ensure that restarting visual studio doesn't fix the problem. If not you can try the steps that follow. These instructions assume that the errant user controls are in control library project in visual studio. If not you should be able to adjust the directions a bit to get it to work but it is much easier when the control is in its own project.
最后一件事。您应该做的第一件事是确保重新启动visual studio不能解决问题。如果没有,您可以尝试以下步骤。这些说明假定错误的用户控件位于visual studio中的控件库项目中。如果没有,你应该能够稍微调整方向以使其工作,但是当控件在自己的项目中时更容易。
Do the following:
请执行下列操作:
- Make the control library your startup project.
- Open the properties for the control library project and click on the debug tab.
- Under Start Action click the Start external program option and browse to the Visual Studio executable.
使控件库成为您的启动项目。
打开控件库项目的属性,然后单击调试选项卡。
在“开始操作”下,单击“启动外部程序”选项并浏览到Visual Studio可执行文件。
NOTE: what this means is that when you run your solution it will fire up another instance of Visual Studio instead of actually running your solution. The First Instance of Visual Studion (INSTANCE_1) will "host" a second instance of visual studio (INSTANCE_2) when you run it.
注意:这意味着当您运行解决方案时,它将启动另一个Visual Studio实例,而不是实际运行您的解决方案。 Visual Studion的第一个实例(INSTANCE_1)将在您运行时“托管”Visual Studio的第二个实例(INSTANCE_2)。
- Run your solution. INSTANCE_2 will load.
- Switch back to INSTANCE_1.
- In INSTANCE_1 hit CTRL-ALT-E. This will open up the exceptions dialog box. Check On the THROWN column checkbox next to Common Language Runtime Exceptions.
运行您的解决方案INSTANCE_2将加载。
切换回INSTANCE_1。
在INSTANCE_1中按CTRL-ALT-E。这将打开例外对话框。选中Common Language Runtime Exceptions旁边的THROWN列复选框。
NOTE: This will ensure that INSTANCE_1 will BREAK at ANY runtime error even if it is hit in a try block.
注意:这将确保INSTANCE_1在任何运行时错误都会发生故障,即使它在try块中命中也是如此。
- Switch to INSTANCE_2. In Solution Explorer double-click to open the errant user control.
切换到INSTANCE_2。在解决方案资源管理器中,双击以打开错误的用户控件。
You should find that INSTANCE_1 OF Visual Studio should have stopped at the line of code that caused the designer to not load the control. Fix the code (which usually means testing for IsNot Nothing before references an object properties...but could mean other things.)
您应该会发现,INSTANCE_1 OF Visual Studio应停止在导致设计器无法加载控件的代码行中。修复代码(这通常意味着在引用对象属性之前测试IsNot Nothing ......但可能意味着其他事情。)
Also, sometimes I find that the control WILL load in INSTANCE_2 instead of breaking on an error in INSTANCE_1. In that case just stop debugging...close INSTANCE_2. Save/Restart INSTANCE_1 and your problem will often have gone away.
此外,有时我发现控件将在INSTANCE_2中加载,而不是在INSTANCE_1中打破错误。在这种情况下,只需停止调试...关闭INSTANCE_2。保存/重新启动INSTANCE_1,您的问题通常会消失。
The lesson is this. User Control MUST be able to load/reference all objects and their members in order to load it into the designer. So for User Controls that will be placed onto other containers I will usually design events to notify the parent rather than trying to push objects into the child control.
教训就是这样。用户控件必须能够加载/引用所有对象及其成员,以便将其加载到设计器中。因此,对于将放置在其他容器上的用户控件,我通常会设计事件来通知父级而不是尝试将对象推送到子控件中。
Hope this helps for future reference on this old question.
希望这有助于将来参考这个老问题。
Seth
#2
Did I read this right? Visual Studio deletes the line that constructs the instance of your control?
我读过这个吗? Visual Studio是否删除构造控件实例的行?
Is your constructor public? At some point I changed the accessibility of my constructor from public to internal - trying to be good, stop the pesky users from accessing things they shouldn't - but then I suffered from the same effects that you describe, I kept having to add my constructor back into InitializeComponent.
你的构造函数是公开的吗?在某些时候,我将构造函数的可访问性从公共更改为内部 - 试图变得更好,阻止讨厌的用户访问他们不应该访问的东西 - 但后来我遭受了与您描述的相同的影响,我不得不添加我的构造函数回到InitializeComponent。
It took me months to realise my mistake...just kept thinking it was a bug in Visual Studio. Changed it back to public and no problems.
我花了几个月才意识到自己的错误......只是一直认为这是Visual Studio中的一个错误。将其更改回公众并没有问题。
#3
Inheriting from the control isn't enough. This is the bare minimum that I had to implement to make it work:
继承控制是不够的。这是我必须实现的最低限度才能使其工作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WinForms
{
class Foo : System.Windows.Forms.ContextMenuStrip
{
public Foo()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}
#4
This problem occurs when InitializeComponent () crosses with base and inherited components. Solution is call the component's designer's method. Otherwise the base method will be called.
当InitializeComponent()与基本和继承的组件交叉时,会发生此问题。解决方案是调用组件的设计者方法。否则将调用基本方法。
public Form() { this.InitializeComponent(); // base.InitializeComponent <-- default one is thisone }
#5
changing my parameterless constructor from internal to public has solved the problem
将无参数构造函数从内部更改为公共已解决了该问题