Ответ 1
Вы можете использовать перечисление LicenceUsageMode в пространстве имен System.ComponentModel
:
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
Следуя этому вопросу, можно ли определить, находится ли в дизайне или режиме выполнения внутри конструктора объекта?
Я понимаю, что это может быть невозможно, и что мне придется изменить то, что я хочу, но на данный момент меня интересует этот конкретный вопрос.
Вы можете использовать перечисление LicenceUsageMode в пространстве имен System.ComponentModel
:
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
Вы ищете что-то вроде этого:
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;
Компонент... насколько мне известно, не имеет свойства DesignMode. Это свойство предоставляется Control. Но проблема в том, что CustomControl находится в форме в конструкторе, этот CustomControl работает в режиме исполнения.
Я испытал, что свойство DesignMode работает корректно только в форме.
ВАЖНО
Существует разница в использовании Windows Формы или WPF!!
У них разные дизайнеры и нужны разные проверки. Кроме того, это сложно, когда вы смешиваете элементы управления Forms и WPF. (например, WPF контролирует внутри окна Forms)
Если у вас Windows Только формы, используйте это:
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.
Вы должны использовать свойство Component.DesignMode. Насколько я знаю, это не должно использоваться из конструктора.
В этом блоге описан еще один интересный метод: 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 является одним из примеров).
Элементы управления (Forms, UserControls и т.д.) наследуют Component class
, который имеет bool property DesignMode
так:
if(DesignMode)
{
//If in design mode
}
В сотрудничестве с дизайнером... Он может использоваться в элементах управления, компонентов, во всех местах
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(
должны быть удалены. Это только делает меня уверенным, что он работает правильно.
Решение LicenseManager не работает внутри OnPaint, и это does.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". Частота отказов будет очень низкой, просто убедитесь, что вы справляетесь с любыми возникающими ошибками, которые могут возникнуть в коде, который не работает в результате этого, и все будет в порядке.
Если вы хотите запускать некоторые строки при запуске, но не в дизайнере 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();
}
Это метод, который я использовал в своем проекте:
//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 output assembly info
Assembly.GetExecutingAssembly().ToString(), //always return your project output assembly info
});
//*/
//LicenseManager.UsageMode will return RunTime if LicenseManager.context is not present.
//So you can not return true by judging it 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 process name if you detected by log from above
;
}
Внимание !!!: Возвращенный код bool указывает NOT в режиме разработки!
private void CtrlSearcher_Load(object sender, EventArgs e)
{
if(!this.DesignMode) InitCombos();
}