Как определить, выполняется ли .NET-код дизайнером Visual Studio
Я получаю некоторые ошибки, возникшие в моем коде, когда я открываю форму Windows Forms в дизайнере Visual Studio. Я хотел бы включить в свой код и выполнить другую инициализацию, если форма открывается дизайнером, чем если бы она выполнялась по-настоящему.
Как я могу определить во время выполнения, если код выполняется как часть конструктора, открывающего форму?
Ответы
Ответ 1
Чтобы узнать, находитесь ли вы в "режиме разработки":
- Компоненты Windows Forms (и элементы управления) имеют свойство DesignMode.
- Элементы управления Windows Presentation Foundation должны использовать прикрепленное свойство IsInDesignMode.
Ответ 2
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
{
// Design time logic
}
Ответ 3
Свойство Control.DesignMode, вероятно, является тем, что вы ищете. Он сообщает, открыт ли родительский элемент управления в дизайнере.
В большинстве случаев он отлично работает, но есть случаи, когда он работает не так, как ожидалось. Во-первых, он не работает в конструкторе элементов управления. Во-вторых, DesignMode является ложным для элементов "grandchild". Например, DesignMode на элементах управления, размещенных в UserControl, вернет false, если UserControl размещен в родительском объекте.
Существует довольно простое решение. Это происходит примерно так:
public bool HostedDesignMode
{
get
{
Control parent = Parent;
while (parent!=null)
{
if(parent.DesignMode) return true;
parent = parent.Parent;
}
return DesignMode;
}
}
Я не тестировал этот код, но он должен работать.
Ответ 4
Самый надежный способ:
public bool isInDesignMode
{
get
{
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
bool res = process.ProcessName == "devenv";
process.Dispose();
return res;
}
}
Ответ 5
Самый надежный способ сделать это - игнорировать свойство 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
}
Ответ 6
Подход 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;
}
}
Ответ 7
У меня была такая же проблема в Visual Studio Express 2013. Я пробовал много предлагаемых решений, но тот, который работал у меня, был ответом на другой поток, который я буду повторять здесь, если связь когда-либо сломана:
protected static bool IsInDesigner
{
get { return (Assembly.GetEntryAssembly() == null); }
}
Ответ 8
using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess())
{
bool inDesigner = process.ProcessName.ToLower().Trim() == "devenv";
return inDesigner;
}
Я попробовал приведенный выше код (добавлен оператор using), и это может не срабатывать в некоторых случаях для меня. Тестирование в конструкторе usercontrol помещается непосредственно в форму с загрузкой конструктора при запуске. Но будет работать в других местах.
Что работало для меня во всех местах:
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
/// <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);
}
Ответ 10
System.Diagnostics.Debugger.IsAttached
Ответ 11
Я не уверен, что работа в режиме отладки считается реальной, но простой способ - включить в свой код инструкцию if
, которая проверяет System.Diagnostics.Debugger.IsAttached
.
Ответ 12
Это hack-ish, но если вы используете VB.NET и когда вы работаете из Visual Studio My.Application.Deployment.CurrentDeployment будет Nothing, потому что вы еще не развернули его. Я не уверен, как проверить эквивалентное значение в С#.
Ответ 13
Вы проверяете свойство DesignMode
вашего элемента управления:
if (!DesignMode)
{
//Do production runtime stuff
}
Обратите внимание, что это не будет работать в вашем конструкторе, потому что компоненты еще не инициализированы.
Ответ 14
System.ComponentModel.Component.DesignMode == true
Ответ 15
Мы используем следующий код в 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;
}
Ответ 16
При запуске проекта его имя добавляется с помощью ".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;
}
}
Это работает для меня.
Ответ 17
Если вы создали свойство, которое вам вообще не нужно во время разработки, вы можете использовать атрибут DesignerSerializationVisibility и установить его в Hidden. Например:
protected virtual DataGridView GetGrid()
{
throw new NotImplementedException("frmBase.GetGrid()");
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int ColumnCount { get { return GetGrid().Columns.Count; } set { /*Some code*/ } }
Это остановило мою работу в Visual Studio каждый раз, когда я внес изменения в форму с помощью NotImplementedException()
и попытался сохранить. Вместо этого Visual Studio знает, что я не хочу сериализовать это свойство, поэтому он может пропустить его. Он отображает только некоторую странную строку в окне свойств формы, но, похоже, ее можно игнорировать.
Обратите внимание, что это изменение не вступает в силу до восстановления.
Ответ 18
Если вы находитесь в форме или управлении, вы можете использовать свойство DesignMode:
if (DesignMode)
{
DesignMode Only stuff
}
Ответ 19
Я нашел свойство DesignMode ошибочным, по крайней мере, в предыдущих версиях Visual Studio. Следовательно, я сделал свой собственный, используя следующую логику:
Process.GetCurrentProcess().ProcessName.ToLower().Trim() == "devenv";
Вид хака, я знаю, но он работает хорошо.
Ответ 20
Чтобы решить эту проблему, вы также можете ввести код, как показано ниже:
private bool IsUnderDevelopment
{
get
{
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
if (process.ProcessName.EndsWith(".vshost")) return true;
else return false;
}
}
Ответ 21
Здесь еще один:
//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 }
Ответ 22
После тестирования большинства ответов здесь, к сожалению, ничего не работало для меня (VS2015).
Поэтому я добавил немного поворота в ответ JohnV, который не работал из коробки, поскольку DesignMode является защищенным свойством в классе Control.
Сначала я сделал метод расширения, который возвращает значение свойства DesignMode через Reflection:
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, и в то время как отражение не следует использовать легкомысленно, в этом случае все это имело значение!;)
EDIT:
Вы также можете сделать вторую функцию методом расширения следующим образом:
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();
}
Ответ 23
/// <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");
}
}
Ответ 24
Здесь гибкий способ, который можно адаптировать к тому, где вы компилируете, а также независимо от того, заботите ли вы, в каком режиме вы находитесь.
string testString1 = "\\bin\\";
//string testString = "\\bin\\Debug\\";
//string testString = "\\bin\\Release\\";
if (AppDomain.CurrentDomain.BaseDirectory.Contains(testString))
{
//Your code here
}