我们开发WinForm应用程序的时候,经常在窗体设计器出现一些错误提示:
看上面的错误信息就知道其实在设计器时程序已经运行了拖进窗体的控件的构造函数和Load事件等。看网上好多资料都说是DesignMode属性的问题,试了下,感觉不行的。下面新建个用户控件,在构造函数里面处理看看是否是DesignMode:
public partial class TestControl : UserControl
{
public TestControl()
{
InitializeComponent();
if (DesignMode)
{
this.lblMsg.Text = "TRUE";
}
else
{
this.lblMsg.Text = "FALSE";
}
}
}
生成项目,VS工具箱出现用户控件TestControl
新建一个窗体,往窗体里面拖放TestControl控件,猜猜结果是TRUE还是FALSE?想当然程序还没运行,处于设计阶段应该是TRUE。
No,结果是False!
明显是设计阶段,应该是True才对,可结果是False!
关于DesignMode,MSDN的解释是:
网上还有说什么容器控件里面的子控件DesignMode为False之类的,试了下,都不靠谱,难道这是一个坑爹的BUG??
解决方法如下:
public static bool IsDesignMode()
{
bool returnFlag = false;
#if DEBUG
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
{
returnFlag = true;
}
else if (Process.GetCurrentProcess().ProcessName == "devenv")
{
returnFlag = true;
}
#endif
return returnFlag;
}
其实在设计器阶段调用的进程是VS的进程----即devenv,上面的方法才是判断当前控件是否处于设计模式。
更改后代码:
public partial class TestControl : UserControl
{
public TestControl()
{
InitializeComponent();
if (PublicFunction.IsDesignMode())
{
this.lblMsg.Text = "TRUE";
}
else
{
this.lblMsg.Text = "FALSE";
}
}
}
重新生成后再次在窗体的设计阶段拖放TestControl控件,这才是预料之中的DesignMode:
运行对比看看:
设计器时设计模式为TRUE,运行时设计模式为FALSE,符合预期结果。
因此,对应这种问题也就引刃而解了,根据错误信息找到对应的地方,往往是构造函数或者Load事件里面进行判断,若是处于设计模式就不执行指定的一些代码就OK。
private void ScannerControl_Load(object sender, EventArgs e)
{
if (!PublicFunction.IsDesignMode())
{
_初始化Twain();
}
}
上面的 _初始化Twain()方法要执行读取扫描仪和本地存储配置文件等一系列复杂操作,完全不用再设计器阶段执行代码。
重新生成后再次打开包含该用户控件的窗体,在设计阶段显示OK:
PS:自定义用户控件时在该控件所在文件不要写其他类,也就是一个用户控件只写该用户控件的类(同样适合于窗体),否则设计器也无法显示控件;再者,推荐用上面写的IsDesignMode()方法取代DesignMode属性,并最后不要在自定义控件或窗体的构造函数中处理设计器无法正常显示的代码,改放在Load事件中处理并用IsDesignMode()方法过滤。