.NET Windows 窗体设计时规则

发布于 2024-07-08 21:54:52 字数 309 浏览 7 评论 0原文

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

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

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

解释是什么? 有参考吗?

I have an object that starts a thread, opens a file, and waits for input from other classes. As it receives input, it writes it to disk. Basically, it's a thread safe data logging class...

Here's the weird part. When I open a form in the designer (Visual Studio 2008) that uses the object the file gets created. It's obviously running under the design time vhost process...

The odd thing is I've not been able to reproduce the issue in another project. I'm not sure what the rules are for code that gets executed in the designer and code that does not. For example, creating a file in a Windows Forms constructor doesn't actually create the file at design time...

What is the explanation? Is there a reference?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

翻身的咸鱼 2024-07-15 21:54:53

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

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

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

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

The constructor of a control or form does not get executed when editing that class in the designer (nor does OnLoad get called). I've occasionally used this to set one value in the designer (eg. making its child controls all Visible in the designer) but override some of them to a different default value in the constructor (eg. hiding certain child controls which will only show in certain circumstances, such as an indicator on a status bar).

However, the constructor does get executed if the control is placed as a child on another control or form in the designer. OnLoad gets executed as well. This may be how your logging code was getting accidentally triggered in the designer.

For detecting design vs runtime, an answer to another question has screenshots of some emperical tests showing the values returned by some common approaches. It appears that a child control of a child control (two levels down) of the form or control being edited in the designer sees its own DesignMode == false, so the normal property check will fail to protect code (eg. in the OnLoad method) for controls nested within a control added in the designer. If you were checking DesignMode as one would expect, it could be the nesting which caused it to get around that check. It also always sees DesignMode == false within the constructor.

Also, note that the LicenseManager.UsageMode check only sees DesignTime within the constructor; when OnLoad is called it is within a RunTime LicenseContext. The most complete solution seems to be to check LicenseManager.UsageMode in the constructor of the control or form (or component) and save the setting to a member variable or property which you can check later to avoid running code that should never run in the designer even when nested. There's also another approach in another answer to that other question which accounts for nesting but only works outside the constructor.

人生百味 2024-07-15 21:54:53

您可以检查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 语句后,当通过设计器将组件添加到表单时,消息框不再出现。

You can check the UsageMode of the LicenseManager, to check if the code is in design time or not.

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

Here is a quick example:

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

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

When this component gets add to your form in the designer, you will immediatly get a message box.

To prevent this you can add a simple if statement to check if the code is not in design time

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!");
            }
        }
    }
}

After adding the if statement, the messagebox no longer appears when the component is added to the form via the designer.

↘人皮目录ツ 2024-07-15 21:54:53

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

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

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

Well, since this has been resurrected anyway, here's the function I use to determine whether I'm in design mode:

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

This handles the case where the control is a child created by another control. The DesignMode property is only set for controls created by the designer itself.

月下伊人醉 2024-07-15 21:54:53

您还可以使用它来检查 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 优雅,但它可以工作(直到 Microsoft 更改名称) Visual Studio 运行的进程的名称)。

You could also use this to check if the Visual Studio Designer is running the code:

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

Then in Form_Load:

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

However, this is less elegant than using the LicensManager.UsageMode, but it works (until Microsoft changes the name of the process Visual Studio runs under).

牵强ㄟ 2024-07-15 21:54:53

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

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

There are some things you shouldn't do with the designer. I don't have any hard evidence, but I found that the Windows Forms designer hates it when you take away the default constructor from it. Just go ahead and create new overloads, but leave the empty constructor in place.

Also try to avoid doing Form_Load events in base classes you inherit from.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文