Detecting design mode from a Control's constructor

Viewed 75314

Following-on from this question, is it possible to detect whether one is in design or runtime mode from within an object's constructor?

I realise that this may not be possible, and that I'll have to change what I want, but for now I'm interested in this specific question.

17 Answers

You can use the LicenceUsageMode enumeration in the System.ComponentModel namespace:

bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);

Are you looking for something like this:

public static bool IsInDesignMode()
{
    if (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1)
    {
        return true;
    }
    return false;
}

You can also do it by checking process name:

if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv")
   return true;

You should use Component.DesignMode property. As far as I know, this shouldn't be used from a constructor.

You can use this

if (DesignerProperties.GetIsInDesignMode(this))
{
...
}

Like many others, I have had this problem several times already when designing Windows Forms UserControls.
But today, I had a situation where none of the mentioned solutions worked for me.
The problem is, that LicenseManager.UsageMode only works reliably in the constructor, while DesignMode only works outside the constructor and not always. This is my experience, and this is what is said in a discussion on GitHub.
And another problem comes with inheritance, and embedding user controls in another user controls in another user controls. At the latest in the 2nd level of embedding a user controls, both ways fail!

This can be shown in the UserControls that I created for this test. Every UC has 3 labels:

  1. its (project name) and type name

  2. The values of

    • DesignMode (true: "DM=1"),
    • LicenseManager.UsageMode == LicenseUsageMode.Designtime, queried locally, (true: "local_LM-DT=1")
    • LicenseManager.UsageMode == LicenseUsageMode.Designtime, queried from a private field that was written in the constructor (true: "ctor_LM-DT=1")

    all taken inside the constructor ("CTOR") and inside a method that was called from the constructor ("CFCtor")

  3. The same values as in 2)
    all taken inside the Load event ("Load()") and inside a method that was called from the Load event ("CFLoad")

The UserControls and the Form that I created are (all screenshots shown them in the WinForms Designer):

  • UserControl1:

    • contains 3 labels

    enter image description here
    The Designer does not execute the construtor or events, therefore the labels are not filled.

  • UserControl1a:

    • inherits from UserControl1
    • contains 2 more labels

    enter image description here
    The Designer executes the construtor and events of the parent UserControl.

  • UserControl2: contains

    • contains 3 labels
    • contains 1 UserControl1
    • contains 1 UserControl1a

    enter image description here
    The Designer executes the construtors and events of the embedded UserControls.
    Only 1 level of embedding.

  • UserControl3:

    • contains 3 labels
    • contains 1 UserControl2

    enter image description here
    The Designer executes the construtors and events of the embedded UserControls.
    2 level of embedding: The values inside the UserControl at 2nd embedding level are wrong.

  • Form1:

    • contains 3 labels
    • contains 1 UserControl1
    • contains 1 UserControl1a
    • contains 1 UserControl2
    • contains 1 UserControl3.

    enter image description here The Designer executes the construtors and events of the embedded UserControls.
    3 level of embedding: The values inside the UserControl at 2nd and 3rd embedding level are wrong.

As you can see from the screenshots, "ctor_LM-DT" is always 1.
This means, that storing the value from the LicenseManager in a member field is necessary to get a valid status of the Designer usage:

private LicenseUsageMode m_ctorLMUsageMode = LicenseManager.UsageMode;

For the sake of completeness, here's some of my code that can be used to reproduce the test:

public static string CreateText(bool i_isInDesignMode, LicenseUsageMode i_localLicenseUsageMode, LicenseUsageMode i_ctorLicenseUsageMode)
{
  return $"DM={(i_isInDesignMode ? 1 : 0)} local_LM-DT={(i_localLicenseUsageMode == LicenseUsageMode.Designtime ? 1 : 0)} ctor_LM-DT={(i_ctorLicenseUsageMode == LicenseUsageMode.Designtime ? 1 : 0)}";
}

The other UserControls are identical or similar:

public partial class UserControl1 : UserControl
{
  private LicenseUsageMode m_ctorLMUsageMode = LicenseManager.UsageMode;

  public UserControl1()
  {
    InitializeComponent();

    label2.Text = $"CTOR: {CInitTester.CreateText (DesignMode, LicenseManager.UsageMode, m_ctorLMUsageMode)}";
    CalledFromCtor();
  }

  private void UserControl1_Load(object sender, EventArgs e)
  {
    label3.Text = $"Load(): {CInitTester.CreateText(DesignMode, LicenseManager.UsageMode, m_ctorLMUsageMode)}";
    CalledFromLoad();
  }

  private void CalledFromCtor()
  {
    label2.Text += $"\r\nCFCtor: {CInitTester.CreateText (DesignMode, LicenseManager.UsageMode, m_ctorLMUsageMode)}";
  }

  private void CalledFromLoad()
  {
    label3.Text += $"\r\nCFLoad: {CInitTester.CreateText (DesignMode, LicenseManager.UsageMode, m_ctorLMUsageMode)}";
  }
}

This is the method I used in my project:

//use a Property or Field for keeping the info to avoid runtime computation
public static bool NotInDesignMode { get; } = IsNotInDesignMode();
private static bool IsNotInDesignMode()
{
    /*
    File.WriteAllLines(@"D:\1.log", new[]
    {
        LicenseManager.UsageMode.ToString(), //not always reliable, e.g. WPF app in Blend this will return RunTime
        Process.GetCurrentProcess().ProcessName, //filename without extension
        Process.GetCurrentProcess().MainModule.FileName, //full path
        Process.GetCurrentProcess().MainModule.ModuleName, //filename
        Assembly.GetEntryAssembly()?.Location, //null for WinForms app in VS IDE
        Assembly.GetEntryAssembly()?.ToString(), //null for WinForms app in VS IDE
        Assembly.GetExecutingAssembly().Location, //always return your project's output assembly info
        Assembly.GetExecutingAssembly().ToString(), //always return your project's output assembly info
    });
    //*/

    //LicenseManager.UsageMode will return RunTime if LicenseManager.context is not present.
    //So you can not return true by judging it's value is RunTime.
    if (LicenseUsageMode.Designtime == LicenseManager.UsageMode) return false;
    var procName = Process.GetCurrentProcess().ProcessName.ToLower();
    return "devenv" != procName //WinForms app in VS IDE
        && "xdesproc" != procName //WPF app in VS IDE/Blend
        && "blend" != procName //WinForms app in Blend
        //other IDE's process name if you detected by log from above
        ;
}

Attention!!!: The code returned bool is indicating NOT in design mode!

I wasn't able to get any of these solutions to work for me in Visual Studio 2019 when creating a WinForms app on .NET Core 3.1.

Both Appllication.ProcessName and Process.ProcessName are returning "DesignToolsServer" for me and LicenseManager.UsageMode returns LicenseUsageMode.Runtime when the Control is in another control or just on a form itself.

I did get it to work using Application.ProcessName == "DesignToolsServer".

Yes, you can check for whether you're in "design mode" from within an object's constructor. But using the WinForms DesignMode property doesn't always work as expected. An alternative:

This is my technique to check DesignMode in C# using Visual Studio and it does work in constructors.

// add this class...
public static class Globals
{
    static Globals() => DesignMode = true;
    public static bool DesignMode { get; set; }
}

// and modify your existing class...
public static class Program
{
    public static void Main()
    {
        Globals.DesignMode = false;
        // ...
        // ... and then the rest of your program
        //
        //  in any of your code you can check Globals.DesignMode for
        //  the information you want.
    }
}

This solution is lightweight and simple. The downside is that you have to remember to clear the flag in your Main code.

When checking for "design mode," we're essentially checking for whether our code is being executed because our whole program is being run or because parts of our code are being executed by the VS designer. With this solution, the flag only gets set to false when the whole program is being run.

    private void CtrlSearcher_Load(object sender, EventArgs e)
    {
           if(!this.DesignMode) InitCombos();
    }

Timers that are enabled by default can cause crash when using custom/user controls. Disable them by default, and enable only after design mode check

   public chartAdapter()
    {
        try
        {

            //Initialize components come here
            InitializeComponent();

            //Design mode check
            bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
            if (designMode)
                return;

            //Enable timers ONLY after designmode check, or else crash
            timerAutoConnect.Enabled = timerDraw.Enabled = true;
Related