如何判断Visual Studio设计器是否正在运行.NET代码

时间:2008-09-16 15:23:22

标签: visual-studio gui-designer

当我在Visual Studio的设计器中打开Windows窗体表单时,我的代码中出现了一些错误。我希望在我的代码中进行分支,如果表单由设计者打开,则执行不同的初始化,而不是实际运行。

如何在运行时确定代码是否作为设计人员打开表单的一部分执行?

24 个答案:

答案 0 :(得分:49)

要了解您是否处于“设计模式”:

  • Windows窗体组件(和控件)具有DesignMode属性。
  • Windows Presentation Foundation控件应使用IsInDesignMode附加属性。

答案 1 :(得分:47)

if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
{
  // Design time logic
}

答案 2 :(得分:19)

Control.DesignMode属性可能就是你要找的东西。它告诉您控件的父级是否在设计器中打开。

在大多数情况下,它运行良好,但有些情况下它无法按预期工作。首先,它在控件构造函数中不起作用。其次,DesignMode对于“孙子”控件是错误的。例如,当UserControl托管在父对象中时,UserControl中托管的控件上的DesignMode将返回false。

有一个非常简单的解决方法。它是这样的:

public bool HostedDesignMode
{
  get 
  {
     Control parent = Parent;
     while (parent!=null)
     {
        if(parent.DesignMode) return true;
        parent = parent.Parent;
     }
     return DesignMode;
  }
}

我没有测试过该代码,但工作。

答案 3 :(得分:15)

最可靠的方法是:

public bool isInDesignMode
{
    get
    {
        System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
        bool res = process.ProcessName == "devenv";
        process.Dispose();
        return res;
    }
}

答案 4 :(得分:13)

最可靠的方法是忽略DesignMode属性并使用在应用程序启动时设置的自己的标志。

类别:

public static class Foo
{
    public static bool IsApplicationRunning { get; set; }
}

的Program.cs:

[STAThread]
static void Main()
{
     Foo.IsApplicationRunning = true;
     // ... code goes here ...
}

然后只需在需要时检查标志。

if(Foo.IsApplicationRunning)
{
    // Do runtime stuff
}
else
{
    // Do design time stuff
}

答案 5 :(得分:5)

devenv方法在VS2012停止工作,因为设计师现在有自己的流程。这是我目前正在使用的解决方案('devenv'部分留给遗留,但没有VS2010,我无法测试它)

private static readonly string[] _designerProcessNames = new[] { "xdesproc", "devenv" };

private static bool? _runningFromVisualStudioDesigner = null;
public static bool RunningFromVisualStudioDesigner
{
  get
  {
    if (!_runningFromVisualStudioDesigner.HasValue)
    {
      using (System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess())
      {
        _runningFromVisualStudioDesigner = _designerProcessNames.Contains(currentProcess.ProcessName.ToLower().Trim());
      }
    }

    return _runningFromVisualStudioDesigner.Value;
  }
}

答案 6 :(得分:4)

我在Visual Studio Express 2013中遇到了同样的问题。我尝试了很多这里提出的解决方案,但是对我有用的解决方案是an answer to a different thread,我将在此处重复以防链接被破坏:< / p>

protected static bool IsInDesigner
{
    get { return (Assembly.GetEntryAssembly() == null); }
}

答案 7 :(得分:3)

/// <summary>
/// Are we in design mode?
/// </summary>
/// <returns>True if in design mode</returns>
private bool IsDesignMode() {
    // Ugly hack, but it works in every version
    return 0 == String.CompareOrdinal(
        "devenv.exe", 0,
        Application.ExecutablePath, Application.ExecutablePath.Length - 10, 10);
}

答案 8 :(得分:3)

using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess())
{
    bool inDesigner = process.ProcessName.ToLower().Trim() == "devenv";
    return inDesigner;
}

我尝试了上面的代码(添加了一个using语句),这在某些情况下对我来说会失败。在用户控件的构造函数中测试直接放置在设计器在启动时加载的表单中。但是可以在其他地方工作。

对我来说,在所有地方都有:

private bool isDesignMode()
{
    bool bProcCheck = false;
    using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess())
    {
        bProcCheck = process.ProcessName.ToLower().Trim() == "devenv";
    }

    bool bModeCheck = (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime);

    return bProcCheck || DesignMode || bModeCheck;
}

也许有点矫枉过正,但它确实有效,所以对我来说已经足够了。

上述示例中的成功是bModeCheck,因此DesignMode可能是多余的。

答案 9 :(得分:2)

这是hack-ish,但如果您正在使用VB.NET,并且当您从Visual Studio My.Application.Deployment.CurrentDeployment 中运行时将是Nothing,因为您没有尚未部署它。我不确定如何检查C#中的等效值。

答案 10 :(得分:1)

我不确定在调试模式下运行是否算真实,但一种简单的方法是在代码中包含if语句,以检查System.Diagnostics.Debugger.IsAttached

答案 11 :(得分:1)

如果您在设计时创建了根本不需要的属性,则可以使用 DesignerSerializationVisibility 属性并将其设置为“隐藏”。例如:

protected virtual DataGridView GetGrid()
{
    throw new NotImplementedException("frmBase.GetGrid()");
}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int ColumnCount { get { return GetGrid().Columns.Count; } set { /*Some code*/ } }

每当我使用NotImplementedException()对表单进行更改并尝试保存时,它就会停止我的Visual Studio崩溃。相反,Visual Studio知道我不想序列化此属性,因此它可以跳过它。它只在表单的属性框中显示一些奇怪的字符串,但忽略它似乎是安全的。

请注意,重建后此更改才会生效。

答案 12 :(得分:1)

运行项目时,其名称后附有“.vshost”。

所以,我用这个:

    public bool IsInDesignMode
    {
        get
        {
            Process p = Process.GetCurrentProcess();
            bool result = false;

            if (p.ProcessName.ToLower().Trim().IndexOf("vshost") != -1)
                result = true;
            p.Dispose();

            return result;
        }
    }

它对我有用。

答案 13 :(得分:1)

我们在UserControls中使用以下代码并完成工作。仅使用DesignMode将无法在您的应用程序中使用,如其他成员所指出的那样使用您的自定义用户控件。

    public bool IsDesignerHosted
    {
        get { return IsControlDesignerHosted(this); }
    }

    public bool IsControlDesignerHosted(System.Windows.Forms.Control ctrl)
    {
        if (ctrl != null)
        {
            if (ctrl.Site != null)
            {
                if (ctrl.Site.DesignMode == true)
                    return true;
                else
                {
                    if (IsControlDesignerHosted(ctrl.Parent))
                        return true;
                    else
                        return false;
                }
            }
            else
            {
                if (IsControlDesignerHosted(ctrl.Parent))
                    return true;
                else
                    return false;
            }
        }
        else
            return false;
    }

答案 14 :(得分:1)

System.ComponentModel.Component.DesignMode == true

答案 15 :(得分:1)

您检查控件的DesignMode属性:

if (!DesignMode)
{
//Do production runtime stuff
}

请注意,这在构造函数中不起作用,因为组件尚未初始化。

答案 16 :(得分:1)

System.Diagnostics.Debugger.IsAttached

答案 17 :(得分:0)

我发现DesignMode属性有问题,至少在Visual Studio的早期版本中是这样。因此,我使用以下逻辑自己创建:

Process.GetCurrentProcess().ProcessName.ToLower().Trim() == "devenv";

有点黑客,我知道,但它运作良好。

答案 18 :(得分:0)

如果您在表单或控件中,则可以使用DesignMode属性:

if (DesignMode)
{
        DesignMode Only stuff
}

答案 19 :(得分:0)

要解决此问题,您还可以按如下方式编码:

private bool IsUnderDevelopment
{
    get
    {
        System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
        if (process.ProcessName.EndsWith(".vshost")) return true;
        else return false;
    }

}

答案 20 :(得分:0)

这是另一个:

        //Caters only to thing done while only in design mode
        if (App.Current.MainWindow == null){ // in design mode  }

        //Avoids design mode problems
        if (App.Current.MainWindow != null) { //applicaiton is running }

答案 21 :(得分:0)

在这里测试了大部分答案后,遗憾的是没有任何对我有用(VS2015)。 所以我对JohnV's answer添加了一些小问题,它没有开箱即用,因为DesignMode是Control类中的受保护属性。

首先,我创建了一个扩展方法,它通过Reflection:

返回DesignMode的Property值
public static Boolean GetDesignMode(this Control control)
{
    BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static;
    PropertyInfo prop = control.GetType().GetProperty("DesignMode", bindFlags);
    return (Boolean)prop.GetValue(control, null);
}

然后我做了一个像JohnV这样的函数:

public bool HostedDesignMode
{
    get
    {
        Control parent = Parent;
        while (parent != null)
        {
            if (parent.GetDesignMode()) return true;
            parent = parent.Parent;
        }
        return DesignMode;
    }
}

这是唯一对我有用的方法,避免了所有的ProcessName混乱,虽然不应该轻易使用反射,在这种情况下它完全有所不同! ;)

修改

您还可以将第二个函数设为这样的扩展方法:

public static Boolean IsInDesignMode(this Control control)
{
    Control parent = control.Parent;
    while (parent != null)
    {
        if (parent.GetDesignMode())
        {
            return true;
        }
        parent = parent.Parent;
    }
    return control.GetDesignMode();
}

答案 22 :(得分:-2)

    /// <summary>
    ///  Whether or not we are being run from the Visual Studio IDE
    /// </summary>
    public bool InIDE
    {
        get
        {
            return Process.GetCurrentProcess().ProcessName.ToLower().Trim().EndsWith("vshost");
        }
    }

答案 23 :(得分:-2)

这是一种灵活的方式,可以适应您编译的位置,以及您是否关心您所处的模式。

string testString1 = "\\bin\\";
//string testString = "\\bin\\Debug\\";
//string testString = "\\bin\\Release\\";

if (AppDomain.CurrentDomain.BaseDirectory.Contains(testString))
{
    //Your code here
}