Windows 窗体设计器中的设计时错误
在用 VS.NET进行窗体设计的时候,经常会遇到这样的问题:我们需要在构造函数或者在OnLoad事件中进行自己的一些初始化操作,比如连接一个数据库、调用一个资源文件或者后期绑定一个组件。如果代码通过编译,在运行时会执行得相当如你所愿。然而,当我们用窗体设计器打开这样一个窗体或者继承的窗体,IDE环境会抛出非常令人不愉快的异常,比如(NullReferenceException )。
究其原因,主要是窗体设计器在载入窗体时会自动初始化该对象,自动执行诸如构造函数、OnLoad方法和InitializeComponent方法,目的在于能使窗体设计器展现出可视化的编辑操作环境。(一些第三方控件也就是利用这个时机弹出注册认证的)。
现在大家明白了,原来我们通过窗体设计器打开一个窗体类或控件类时,IDE环境已经悄悄地在宿主进程中实例化了我们的类。
如果我们在构造函数中写了这样的代码:
- public class MyClass : System.WIndows.Forms.Form
- {
- public MyClass(string fileName)
- {
- InitializeComponent();
- FileStream myFile = File.Open( filename ); // 窗体设计器可能抛出异常!
- //…
- }
- //…
- }
问题便由此产生,fileName参数的值是程序在运行时传递的,设计时当然无从获得。所以,窗体设计器在打开此窗体类时,必然会抛出异常,同时窗体将无法正常显示。
解决这种问题的办法网上其他朋友说了很多,归纳起来好像主要有以下三种途径:
一、判断 this.DesignMode 属性
这是让人一眼看过去就觉得最直接最有效的方法,绝对有一种踏破铁蹄无觅处,得来全不费功夫的欣快感——可惜的是,用起来一点不奏效。因为如果该窗体是个独立窗体或控件,那一点问题都没有,DesignMode的值如你所愿为true,但是如果它是包含在其他控件中被拖拽到设计器中(例如,把设计好的控件拖入新的WinForms窗体),那么那个接受拖拽的窗体才处于设计模式,而它不是,它已鬼使神差地进入了RunTime模式,然后如我所愿,抛出异常J。
这是让人一眼看过去就觉得最直接最有效的方法,绝对有一种踏破铁蹄无觅处,得来全不费功夫的欣快感——可惜的是,用起来一点不奏效。因为如果该窗体是个独立窗体或控件,那一点问题都没有,DesignMode的值如你所愿为true,但是如果它是包含在其他控件中被拖拽到设计器中(例如,把设计好的控件拖入新的WinForms窗体),那么那个接受拖拽的窗体才处于设计模式,而它不是,它已鬼使神差地进入了RunTime模式,然后如我所愿,抛出异常J。
二、利用 Assembly.GetEntryAssembly()方法
判断执行程序入口的组件是不是我们预想的,如果不是,那么必然是IDE的窗体设计器调用的——问题解决——只是有点大炮打蚊子的感觉。
三、定义一个静态成员,指示程序所处的模式
此方法我认为最好。具体做法是写一个全局类,也就是构造函数为 private 限制的类,里面的成员都为static静态类型。这样的一个类由于构造函数是私有的,所以不可能自任何地方任何外部代码中实例化,从而保证了其内成员的唯一性。然后,在程序的入口处,把此类的一个用于表示运行模式的静态成员标识为“运行时”,下面….一切都好说了,看代码吧:
此方法我认为最好。具体做法是写一个全局类,也就是构造函数为 private 限制的类,里面的成员都为static静态类型。这样的一个类由于构造函数是私有的,所以不可能自任何地方任何外部代码中实例化,从而保证了其内成员的唯一性。然后,在程序的入口处,把此类的一个用于表示运行模式的静态成员标识为“运行时”,下面….一切都好说了,看代码吧:
- //全局类
- public class GlobalClass
- {
- //私有构造器,防止实例化
- private GlobalClass(){}
- //用于标识运行时/设计时的bool型静态成员,初始值设为false
- public static bool RunTimeMode = false;
- }
- //包含程序入口的类
- Public class Entry
- {
- …
- //主线程入口点,窗体设计器绝不会执行此方法
- static void Main(string[] args)
- {
- //置为true
- GlobalClass.RunTimeMode = true;
- //…..
- }
- //…
- }
- //某个窗体类
- public class MyForm : System.Windows.Forms.Form
- {
- public MyForm()
- {
- //窗体设计器必须调用的
- InitializeComponent();
- //判断运行模式
- If( GlobalClass.RunTimeMode )
- {
- //在此处做一些窗体设计器会报错的事情
- }
- //…
- }
- //…
- }
如果大家有什么更好的办法解决所述问题,记得分享哦 :)
- public class MyClass : System.WIndows.Forms.Form
- {
- public MyClass(string fileName)
- {
- InitializeComponent();
- FileStream myFile = File.Open( filename ); // 窗体设计器可能抛出异常!
- //…
- }
- //…
- }
问题便由此产生,fileName参数的值是程序在运行时传递的,设计时当然无从获得。所以,窗体设计器在打开此窗体类时,必然会抛出异常,同时窗体将无法正常显示。
解决这种问题的办法网上其他朋友说了很多,归纳起来好像主要有以下三种途径:
一、判断 this.DesignMode 属性
这是让人一眼看过去就觉得最直接最有效的方法,绝对有一种踏破铁蹄无觅处,得来全不费功夫的欣快感——可惜的是,用起来一点不奏效。因为如果该窗体是个独立窗体或控件,那一点问题都没有,DesignMode的值如你所愿为true,但是如果它是包含在其他控件中被拖拽到设计器中(例如,把设计好的控件拖入新的WinForms窗体),那么那个接受拖拽的窗体才处于设计模式,而它不是,它已鬼使神差地进入了RunTime模式,然后如我所愿,抛出异常J。
这是让人一眼看过去就觉得最直接最有效的方法,绝对有一种踏破铁蹄无觅处,得来全不费功夫的欣快感——可惜的是,用起来一点不奏效。因为如果该窗体是个独立窗体或控件,那一点问题都没有,DesignMode的值如你所愿为true,但是如果它是包含在其他控件中被拖拽到设计器中(例如,把设计好的控件拖入新的WinForms窗体),那么那个接受拖拽的窗体才处于设计模式,而它不是,它已鬼使神差地进入了RunTime模式,然后如我所愿,抛出异常J。
二、利用 Assembly.GetEntryAssembly()方法
判断执行程序入口的组件是不是我们预想的,如果不是,那么必然是IDE的窗体设计器调用的——问题解决——只是有点大炮打蚊子的感觉。
三、定义一个静态成员,指示程序所处的模式
此方法我认为最好。具体做法是写一个全局类,也就是构造函数为 private 限制的类,里面的成员都为static静态类型。这样的一个类由于构造函数是私有的,所以不可能自任何地方任何外部代码中实例化,从而保证了其内成员的唯一性。然后,在程序的入口处,把此类的一个用于表示运行模式的静态成员标识为“运行时”,下面….一切都好说了,看代码吧:
此方法我认为最好。具体做法是写一个全局类,也就是构造函数为 private 限制的类,里面的成员都为static静态类型。这样的一个类由于构造函数是私有的,所以不可能自任何地方任何外部代码中实例化,从而保证了其内成员的唯一性。然后,在程序的入口处,把此类的一个用于表示运行模式的静态成员标识为“运行时”,下面….一切都好说了,看代码吧:
- //全局类
- public class GlobalClass
- {
- //私有构造器,防止实例化
- private GlobalClass(){}
- //用于标识运行时/设计时的bool型静态成员,初始值设为false
- public static bool RunTimeMode = false;
- }
- //包含程序入口的类
- Public class Entry
- {
- …
- //主线程入口点,窗体设计器绝不会执行此方法
- static void Main(string[] args)
- {
- //置为true
- GlobalClass.RunTimeMode = true;
- //…..
- }
- //…
- }
- //某个窗体类
- public class MyForm : System.Windows.Forms.Form
- {
- public MyForm()
- {
- //窗体设计器必须调用的
- InitializeComponent();
- //判断运行模式
- If( GlobalClass.RunTimeMode )
- {
- //在此处做一些窗体设计器会报错的事情
- }
- //…
- }
- //…
- }
如果大家有什么更好的办法解决所述问题,记得分享哦
- public class MyClass : System.WIndows.Forms.Form
- {
- public MyClass(string fileName)
- {
- InitializeComponent();
- FileStream myFile = File.Open( filename ); // 窗体设计器可能抛出异常!
- //…
- }
- //…
- }
问题便由此产生,fileName参数的值是程序在运行时传递的,设计时当然无从获得。所以,窗体设计器在打开此窗体类时,必然会抛出异常,同时窗体将无法正常显示。
解决这种问题的办法网上其他朋友说了很多,归纳起来好像主要有以下三种途径:
一、判断 this.DesignMode 属性
这是让人一眼看过去就觉得最直接最有效的方法,绝对有一种踏破铁蹄无觅处,得来全不费功夫的欣快感——可惜的是,用起来一点不奏效。因为如果该窗体是个独立窗体或控件,那一点问题都没有,DesignMode的值如你所愿为true,但是如果它是包含在其他控件中被拖拽到设计器中(例如,把设计好的控件拖入新的WinForms窗体),那么那个接受拖拽的窗体才处于设计模式,而它不是,它已鬼使神差地进入了RunTime模式,然后如我所愿,抛出异常J。
这是让人一眼看过去就觉得最直接最有效的方法,绝对有一种踏破铁蹄无觅处,得来全不费功夫的欣快感——可惜的是,用起来一点不奏效。因为如果该窗体是个独立窗体或控件,那一点问题都没有,DesignMode的值如你所愿为true,但是如果它是包含在其他控件中被拖拽到设计器中(例如,把设计好的控件拖入新的WinForms窗体),那么那个接受拖拽的窗体才处于设计模式,而它不是,它已鬼使神差地进入了RunTime模式,然后如我所愿,抛出异常J。
二、利用 Assembly.GetEntryAssembly()方法
判断执行程序入口的组件是不是我们预想的,如果不是,那么必然是IDE的窗体设计器调用的——问题解决——只是有点大炮打蚊子的感觉。
三、定义一个静态成员,指示程序所处的模式
此方法我认为最好。具体做法是写一个全局类,也就是构造函数为 private 限制的类,里面的成员都为static静态类型。这样的一个类由于构造函数是私有的,所以不可能自任何地方任何外部代码中实例化,从而保证了其内成员的唯一性。然后,在程序的入口处,把此类的一个用于表示运行模式的静态成员标识为“运行时”,下面….一切都好说了,看代码吧:
此方法我认为最好。具体做法是写一个全局类,也就是构造函数为 private 限制的类,里面的成员都为static静态类型。这样的一个类由于构造函数是私有的,所以不可能自任何地方任何外部代码中实例化,从而保证了其内成员的唯一性。然后,在程序的入口处,把此类的一个用于表示运行模式的静态成员标识为“运行时”,下面….一切都好说了,看代码吧:
- //全局类
- public class GlobalClass
- {
- //私有构造器,防止实例化
- private GlobalClass(){}
- //用于标识运行时/设计时的bool型静态成员,初始值设为false
- public static bool RunTimeMode = false;
- }
- //包含程序入口的类
- Public class Entry
- {
- …
- //主线程入口点,窗体设计器绝不会执行此方法
- static void Main(string[] args)
- {
- //置为true
- GlobalClass.RunTimeMode = true;
- //…..
- }
- //…
- }
- //某个窗体类
- public class MyForm : System.Windows.Forms.Form
- {
- public MyForm()
- {
- //窗体设计器必须调用的
- InitializeComponent();
- //判断运行模式
- If( GlobalClass.RunTimeMode )
- {
- //在此处做一些窗体设计器会报错的事情
- }
- //…
- }
- //…
- }
如果大家有什么更好的办法解决所述问题,记得分享哦 :)