Определение режима разработки из конструктора Control


99

Исходя из этого вопроса , можно ли определить, находится ли объект в режиме разработки или во время выполнения, из конструктора объекта?

Я понимаю, что это может быть невозможно, и что мне придется изменить то, что я хочу, но пока меня интересует этот конкретный вопрос.

Ответы:


193

Вы можете использовать перечисление LicenceUsageMode в System.ComponentModelпространстве имен:

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

2
Элегантное решение, работает лучше, чем функциональность C # ISite.DesignMode.
56ka

10
@Filip Kunc: если это не работает в OnPaint, вы можете проверить это условие в конструкторе и сохранить его в поле класса.
IMil 06

3
Это также не работает при переопределении WndProc в пользовательском элементе управления. Должен использовать предложение @IMil
Мэтт Скелдон,

1
Помещение его в конструкцию - хорошая идея IMil, у меня это сработало .. Я попытался поместить его в поле статических классов, но (я думаю) поля статических классов инициализировались, когда вы их впервые вызывали, поэтому не безопасное решение ..
Ибрагим Оздемир

23

Вы ищете что-то вроде этого:

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

Вы также можете сделать это, проверив имя процесса:

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

4
Работает в OnPaint, производных классах, конструкторах и т. Д. Лучшее решение.
Филип Кунч

14
ИМХО, это выглядит некрасивым решением.
Камило Мартин

5
Внимание, возможная утечка памяти здесь. Процесс необходимо утилизировать.
nalply

7
Хотя я уверен, что в большинстве случаев это сработает нормально, у этого решения есть один принципиальный недостаток: Visual Studio (по крайней мере, теоретически) не единственный хост-дизайнер. Следовательно, это решение будет работать только в том случае, если ваш дизайнер размещен в приложении с именем devenv.
stakx - больше не вносит свой вклад

2
Работает на VS2013, в отличие от принятого в настоящее время ответа.
Moby Disk

9

Компонент ... насколько я знаю, не имеет свойства DesignMode. Это свойство предоставляется Control. Но проблема в том, что когда CustomControl находится в форме в конструкторе, этот CustomControl работает в режиме выполнения.

Я испытал, что свойство DesignMode правильно работает только в форме.


Спасибо за чаевые! Я никогда не осознавал этого раньше, но это имеет смысл. Использование метода LicenseManager, предоставляемого adrianbanks, отлично работает в тех случаях, когда элемент управления встроен в другой элемент управления / форму. +1 за каждого!
Джош Стриблинг

1
+1 Вы совершенно правы, это тоже был мой опыт. Когда вы помещаете пользовательский элемент управления в форму, если есть какие-либо события mouseenter или load, DesignMode все равно будет отображаться как false, потому что вы не находитесь в режиме дизайна для этого элемента управления. По моему опыту, из-за этого визуальная студия довольно сильно вылетает.
Kyle B

8

Органы управления (Формы, элементы управления UserControl и т.д.) унаследуют Component classкоторый имеет bool property DesignModeтак:

if(DesignMode)
{
  //If in design mode
}

4
Что не устанавливается при запуске конструктора, иначе говоря, первоначальная проблема OP. Первый момент, когда вы можете его использовать, - это в OnHandleCreated.
Рэй

8

ВАЖНЫЙ

Есть разница в использовании Windows Forms или WPF !!

У них разные дизайнеры и разные проверки . Кроме того, сложно смешивать элементы управления Forms и WPF. (например, элементы управления WPF внутри окна форм)

Если у вас только Windows Forms , используйте это:

Boolean isInWpfDesignerMode   = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);

Если у вас только WPF , используйте эту проверку:

Boolean isInFormsDesignerMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv");

Если вы используете смешанные формы и WPF, используйте следующую проверку:

Boolean isInWpfDesignerMode   = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
Boolean isInFormsDesignerMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv");

if (isInWpfDesignerMode || isInFormsDesignerMode)
{
    // is in any designer mode
}
else
{
    // not in designer mode
}

Чтобы увидеть текущий режим, вы можете показать MessageBox для отладки:

// show current mode
MessageBox.Show(String.Format("DESIGNER CHECK:  WPF = {0}   Forms = {1}", isInWpfDesignerMode, isInFormsDesignerMode));

Замечание:

Вам нужно добавить пространства имен System.ComponentModel и System.Diagnostics .


Я думаю, что ваше имя вводит в заблуждение. При использовании для WinForms имя - isInWpfDesignerMode, а для WPF - isInFormsDesignerMode
M Stoerzel

5

Вы должны использовать свойство Component.DesignMode. Насколько я знаю, это не следует использовать из конструктора.


7
Это не работает, если ваш элемент управления находится внутри другого разрабатываемого элемента управления или формы.
Эрик

1
На самом деле он неплохо работает в моих компонентах. Мне всегда приходилось добавлять if (!DesignMode)методы OnPaint, чтобы убедиться, что они не спамят во время разработки.
Bitterblue

4

В этом блоге описан еще один интересный метод: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or -usermode /

По сути, он проверяет, является ли выполняющаяся сборка статической ссылкой из входной сборки. Это позволяет избежать необходимости отслеживать имена сборок (devenv.exe, monodevelop.exe ..).

Однако он не работает во всех других сценариях, когда сборка загружается динамически (например, VSTO).


Ссылка (фактически) не работает. Вместо этого он перенаправляет на последнее сообщение в блоге (в настоящее время 2016-03).
Питер Мортенсен

3

В сотрудничестве с дизайнером ... Его можно использовать в элементах управления, компонентах и ​​везде.

    private bool getDesignMode()
    {
        IDesignerHost host;
        if (Site != null)
        {
            host = Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
            if (host != null)
            {
                if (host.RootComponent.Site.DesignMode) MessageBox.Show("Design Mode");
                else MessageBox.Show("Runtime Mode");
                return host.RootComponent.Site.DesignMode;
            }
        }
        MessageBox.Show("Runtime Mode");
        return false;
    }

MessageBox.Show(линии следует удалить. Это только убеждает меня, что он работает правильно.



1

Это метод, который я использовал в своем проекте:

//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
        ;
}

Внимание !!!: возвращенный код bool указывает НЕ в режиме разработки!


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

Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа.
Тьяго Мартинс Перес 李大仁

0

Решение LicenseManager не работает внутри OnPaint, как и this.DesignMode. Я прибег к тому же решению, что и @Jarek.

Вот кешированная версия:

    private static bool? isDesignMode;
    private static bool IsDesignMode()
    {
        if (isDesignMode == null)
            isDesignMode = (Process.GetCurrentProcess().ProcessName.ToLower().Contains("devenv"));

        return isDesignMode.Value;
    }

Имейте в виду, что это не удастся, если вы используете какую-либо стороннюю IDE или если Microsoft (или ваш конечный пользователь) решит изменить имя исполняемого файла VS на что-то другое, кроме devenv. Частота отказов будет очень низкой, просто убедитесь, что вы имеете дело с любыми возникающими ошибками, которые могут возникнуть в коде, который не работает в результате этого, и все будет в порядке.


0

Если вы хотите запустить несколько строк, когда он запущен, но не в конструкторе Visual Studio, вам следует реализовать свойство DesignMode следующим образом:

// this code is in the Load of my UserControl
if (this.DesignMode == false)
{
    // This will only run in run time, not in the designer.
    this.getUserTypes();
    this.getWarehouses();
    this.getCompanies();
}

0

Таймеры, которые включены по умолчанию, могут вызвать сбой при использовании настраиваемых / пользовательских элементов управления. Отключите их по умолчанию и включите только после проверки режима разработки

   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;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.