创建应用自定义控件的WinForm工程
1.
在File菜单中点击New,然后点击Project。
2.
在左边的窗口中选择Visual
C# Projects。
3.
在右边的窗口中选择Window
Application(这个Application里将应用我们的例子)。
4.
将工程命名为DesignTimeDebugging。
5.
确定radio
button选择的是Add
to solution。
为工程添加我们的控件库的引用
1.
在我们的Host
App Project中,右击References,点击Add
Reference。
2.
在Projects属性页上,选择Immedient.Windows.Forms工程。
使用我们的自定义Form
1.
为了能够使用Microsoft
IntelliSense,我们重新编译我们的工程。
2.
使用下面的代码改变Form1的继承关系,改由我们自定义的Form派生。
C#
namespace
Immedient.Samples.HostApp.Windows
{
public class Form1 : Immedient.Windows.Forms.Form
{
3.
打开Form1,会发现我们自定义的属性出现在了属性页上。如果有错误发生,关闭所有代开的文件,然后Rebuild
Solution,再重新打开Form1。
设置控件库工程的属性
通常我们希望能够确定我们是否产生了VS.NET调试我们的代码所需的信息。当开始调试时,如果在断点上开到“?”符号,说明我们没有产生合适的符号文件。这可能是由于当前正处于Release模式下,或者工程设置被偶然改变了。应当确定Generate
Debugging Information属性被设为true。
Xml文档(C#
Only)
下面的设置只对C#有效,在VS.NET2002中,VB.NET并不能产生Xml文档。
为了从我们在C#代码中创建的Xml注释中受益,我们应当告诉VS.NET生成一个Xml文档。将XML
Documentation File属性设为与Assembly的名字加上xml后缀相同的值。
这里还用一个关于Xml文档的小窍门。你一旦设置了XML
Documentation File,VS.NET会帮你为每个没有Xml注释的public
interface产生警告。这些警告有时多的烦人。如果你还没有准备好处理所有public
interface的文档的话,你可以将Warning
Level设置为2,这样,任务列表就不会收集警告信息,直到你将所有的事情都准备妥当之后,在将它设回来即可。
开始调试
现在我们有了一些可以调试的代码,让我们开始吧。为了调试我们的代码,我们需要步入(step
into)容纳我们代码的应用程序中。在我们的示例中是VS.NET。
设置调试属性
在调试过程中,我们需要改变一些调试属性。它们在VB.NET和C#中有些许不同(译注:在此谨以C#为例)。
C#工程属性页
1.
右击Control
Library工程,选择Property。
2.
点击Configuration
Properties。
3.
将Debug
Mode改为Program。
4.
将Start
Application改为Visual
Studio .NET。默认的位置是:C:\Program
Files\Microsoft Visual Studio .NET\Common7\IDE\devenv.exe。
设置断点
在自定义属性的set中的if表达式上设置断点
最后一件事
确保Control
Library工程是启动工程。在Control
Library工程上右击选择Set
as Startup Project。
继续下去
1.
按F5开始调试过程。这时会有一个新的VS.NET实例被启动,我们的开发环境掌握此实例——pretty
cool。
2.
分辨哪个VS.NET是我们的调试环境的一个简便方法是看调试按钮。调试环境中的start
button是灰色无效的。
3.
当新的VS.NET启动之后,打开相同的solution:C:\DesignTimeDebugging\DesignTimeDebugging.sln
4.
在HostApp
Windows Forms工程中,双击Form1打开之。
5.
在属性页中,改变MyText属性的值为Good
bye。
6.
此时应当步入断点所在处。
7.
我们已经调试了我们的第一个.NET
design-time control。现在让我们看一看发生在后台的一系列事件。
事件链条
在使用设计时控件时,当你将一个控件拖到设计界面上时,明白在它背后发生了什么是很重要的。你肯定很想知道,当你创建一个从同样是你创建的另一个Form派生的Form是发生了什么。
当一个对象被在设计环境中打开时,这个对象所继承的那个类(不是新生成的类)被VS.NET构造。记住,这个被创建的控件激活(fire)它的构造函数,构造函数又激活了它的基类的构造函数中的InitializeComponent()方法。一旦派生类被构造,那个在新建类中具有神奇的名字的方法,InitializeComponent(),将被VS.NET一行一行地解析。这个方法唯一神奇的是它的名字,因为VS.NET知道寻找这个方法。
在VB.NET中,如果VS.NET不能解析某行代码,那么这一行将被删除。这时由于VB开发小组觉得保持设计时环境更重要。而C#开发小组认为保持代码更重要,因此在C#中,如果VS.NET不能解析InitializeComponent(),你将会得到一个描述异常的文本。
当InitializeComponent()运行时,属性的值将被改成你在属性页上所设置的值。在VS.NET中,对象的属性页只是InitializeComponent()方法的图形化表示而已。如果你的基类的构造函数要完成一些特殊的功能,要小心了,这些功能也同样会被设计环境执行。
有一个方法可以使这些代码在设计时不被执行。任何派生自Component类的class都具有一个DesignMode属性。当对象在VS.NET
designer中被构造时,这个属性被设为true。因此,你可以写一个if来包装你的代码,从而避免他们被执行。但是也没有更多的花招了,DesignMode不会再构造函数中设为true。记住,这里根本没有魔法。VS.NET通过解析InitializeComponent()方法来构造对象,一旦对象被构造,VS.NET将保持对对象的跟踪,并简单地设置:
newlyCreatedObject.DesignMode
= true
为了增加一些乐趣,同时了事都有哪些事件会发生,以及DesignMode何时会被设置,在你的Immedient.Windows.Forms.Form中添加如下代码(译注:请用VS.NET来添加事件,这可以保证事件被正确添加到InitializeComponent方法中)。为了能够获得VS.NET发出的事件,请关闭所有的Form,重新编译Solution。
private
void Form_Layout(object sender, System.Windows.Forms.LayoutEventArgs
e)
{
MessageBox.Show("Layout: DesignMode = " +
this.DesignMode.ToString());
}
private void Form_Load(object sender, System.EventArgs e)
{
if(this.DesignMode)
{
// Don't connected to database.
MessageBox.Show("Form load: DesignMode = " +
this.DesignMode.ToString());
}
else
{
// Make a connection to database and do something.
MessageBox.Show("Form load: DesignMode = " +
this.DesignMode.ToString());
}
}
private void Form_VisibleChanged(object sender,
System.EventArgs e)
{
MessageBox.Show("VisibleChanged: DesignMode = " +
this.DesignMode.ToString());
}
private void Form_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
MessageBox.Show("Paint: DesignMode = " +
this.DesignMode.ToString());
}
总结
在这篇文章里,我们在Windows
Form上使用了一个简单的属性。由此可以看出,在设计时环境中,任何东西的改变都是可以被调试的。我最初发现这个技巧,是在开发一个ASP.NET
Image HREF设计时控件的时候。同样的技巧也适用于系统组件控件,比如EventLog控件和显示于系统托盘里的Data控件。VS.NET为开发控件提供了一个丰富、高效的开发环境,在这里,创建和调试控件就如同毁灭他们一样简单。
关于作者
Steve
Lasker是Immedient公司的National
Director of Research & Development。Steve曾经为Windows
Forms,ASP.NET,和the
.NET Compact Framework开发过一些.NET控件和框架。Steve的邮件地址是Steve.Lasker@Immedient.com
|