10

我有一个对象,它启动一个线程,打开一个文件,并等待来自其他类的输入。当它接收到输入时,它会将其写入磁盘。基本上,它是一个线程安全的数据记录类......

这是奇怪的部分。当我在使用该对象的设计器 (Visual Studio 2008) 中打开一个表单时,该文件被创建。它显然是在设计时虚拟主机进程下运行的......

奇怪的是我无法在另一个项目中重现该问题。我不确定在设计器中执行的代码和不执行的代码的规则是什么。例如,在 Windows 窗体构造函数中创建文件实际上并没有在设计时创建文件......

解释是什么?有参考吗?

4

5 回答 5

13

在设计器中编辑该类时不会执行控件或表单的构造函数(也不会调用 OnLoad)。我偶尔使用它在设计器中设置一个值(例如,使其子控件在设计器中全部可见),但在构造函数中将其中一些覆盖为不同的默认值(例如,隐藏某些只会显示的子控件在某些情况下,例如状态栏上的指示器)。

但是,如果控件作为子控件放置在设计器中的另一个控件或窗体上,则构造函数会被执行OnLoad 也被执行。这可能是您的日志记录代码在设计器中意外触发的方式。

为了检测设计与运行时,另一个问题的答案有一些经验测试的屏幕截图,显示了一些常见方法返回的值。似乎在设计器中正在编辑的表单或控件的子控件(向下两层)的子控件看到自己的 DesignMode == false,因此正常的属性检查将无法保护代码(例如在 OnLoad 方法中) 用于嵌套在设计器中添加的控件中的控件。如果您按照预期检查 DesignMode,则可能是嵌套导致它绕过该检查。它也总是在构造函数中看到 DesignMode == false。

另外,请注意 LicenseManager.UsageMode 检查在构造函数中看到 DesignTime;当调用 OnLoad 时,它位于 RunTime LicenseContext 中。最完整的解决方案似乎是在控件或表单(或组件)的构造函数中检查 LicenseManager.UsageMode 并将设置保存到成员变量或属性中,您可以稍后检查以避免运行不应在设计器中运行的代码即使嵌套。在另一个问题的另一个答案中还有另一种方法,它解释了嵌套,但只能在构造函数之外工作。

于 2011-02-18T21:41:29.463 回答
11

您可以检查 LicenseManager 的 UsageMode,以检查代码是否在设计时。

System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime

这是一个简单的例子:

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace Test
{
    public class ComponentClass : Component
    {
        public ComponentClass()
        {
            MessageBox.Show("Runtime!");
        }
    }
}

当此组件在设计器中添加到您的表单时,您将立即获得一个消息框。

为了防止这种情况,您可以添加一个简单的 if 语句来检查代码是否不在设计时

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace Test
{
    public class ComponentClass : Component
    {
        public ComponentClass()
        {
            if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
            {
                MessageBox.Show("Runtime!");
            }
        }
    }
}

添加 if 语句后,通过设计器将组件添加到表单时不再出现消息框。

于 2008-11-11T21:57:12.713 回答
2

您还可以使用它来检查 Visual Studio 设计器是否正在运行代码:

public static bool DesignMode
{
    get {  return (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv"); }
}

然后在 Form_Load 中:

if (!DesignMode)
{
    // Run code that breaks in Visual Studio Designer (like trying to get a DB connection)
}

但是,这不如使用LicensManager.UsageMode.

于 2009-06-16T08:20:58.113 回答
2

好吧,既然这已经复活了,这是我用来确定我是否处于设计模式的函数:

public static bool IsAnyInDesignMode(Control control){
    while(control != null){
        if(control.Site != null && control.Site.DesignMode)
            return true;
        control = control.Parent;
    }
    return false;
}

这可以处理控件是由另一个控件创建的子控件的情况。该DesignMode属性仅为设计器本身创建的控件设置。

于 2011-02-19T04:06:24.647 回答
0

有些事情你不应该和设计师一起做。我没有任何确凿的证据,但我发现当您从中删除默认构造函数时,Windows 窗体设计者讨厌它。继续创建新的重载,但保留空的构造函数。

还要尽量避免在Form_Load您继承的基类中执行事件。

于 2008-11-11T20:24:16.397 回答