Visual Studio 디자이너에서 Windows Forms 양식을 열면 코드에 오류가 발생합니다. 디자이너가 폼을 실제로 실행하는 경우와 달리 폼에서 코드를 분기하고 다른 초기화를 수행하고 싶습니다.
양식을 여는 디자이너의 일부로 코드가 실행되고 있는지 런타임에 어떻게 확인할 수 있습니까?
"디자인 모드"인지 확인하려면 :
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
{
// Design time logic
}
Control.DesignMode 속성은 아마도 당신이 찾고있는 것입니다. 컨트롤의 부모가 디자이너에서 열려 있는지 알려줍니다.
대부분의 경우 잘 작동하지만 예상대로 작동하지 않는 경우가 있습니다. 첫째, 컨트롤 생성자에서 작동하지 않습니다. 둘째, "손자"컨트롤의 경우 DesignMode가 false입니다. 예를 들어 UserControl에서 호스팅되는 컨트롤의 DesignMode는 UserControl이 부모에서 호스팅 될 때 false를 반환합니다.
매우 쉬운 해결 방법이 있습니다. 다음과 같이 진행됩니다.
public bool HostedDesignMode
{
get
{
Control parent = Parent;
while (parent!=null)
{
if(parent.DesignMode) return true;
parent = parent.Parent;
}
return DesignMode;
}
}
그 코드를 테스트하지는 않았지만 should 작동합니다.
가장 안정적인 방법은 다음과 같습니다.
public bool isInDesignMode
{
get
{
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
bool res = process.ProcessName == "devenv";
process.Dispose();
return res;
}
}
가장 안정적인 방법은 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
}
디자이너는 이제 자체 프로세스를 가지고 있기 때문에 VS2012에서 devenv 접근 방식이 작동을 멈췄습니다. 여기에 현재 사용중인 솔루션이 있습니다 ( '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;
}
}
Visual Studio Express 2013에서도 동일한 문제가 발생했습니다. 여기에서 제안한 많은 솔루션을 시도했지만 저에게 도움이 된 솔루션은 다른 스레드에 대한 답변 입니다. 이제까지 깨진 :
protected static bool IsInDesigner
{
get { return (Assembly.GetEntryAssembly() == null); }
}
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가 잉여 일 수 있습니다.
/// <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);
}
해킹 적이지만 VB.NET 을 사용하고 Visual Studio에서 실행중인 경우 My.Application.Deployment.CurrentDeployment 아무것도 아님 아직 배포하지 않았기 때문입니다. C #에서 동등한 값을 확인하는 방법을 잘 모르겠습니다.
System.Diagnostics.Debugger.IsAttached
디버그 모드에서 실행하는 것이 실제 카운트인지 확실하지 않지만 쉬운 방법은 코드에 System.Diagnostics.Debugger.IsAttached
를 확인하는 if
문을 포함시키는 것입니다.
프로젝트를 실행할 때 이름에 ".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;
}
}
그것은 나를 위해 작동합니다.
디자인 타임에 전혀 필요하지 않은 속성을 만든 경우 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는이 속성을 serialize하고 싶지 않다는 것을 알고 있으므로 건너 뛸 수 있습니다. 양식의 속성 상자에 이상한 문자열 만 표시되지만 무시하는 것이 안전합니다.
이 변경 사항은 다시 빌드 할 때까지 적용되지 않습니다.
우리는 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;
}
컨트롤의 DesignMode
속성을 확인하십시오.
if (!DesignMode)
{
//Do production runtime stuff
}
구성 요소가 아직 초기화되지 않았으므로 생성자에서 작동하지 않습니다.
System.ComponentModel.Component.DesignMode == true
다른 하나는 다음과 같습니다.
//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 }
폼이나 컨트롤에있는 경우 DesignMode 속성을 사용할 수 있습니다.
if (DesignMode)
{
DesignMode Only stuff
}
적어도 이전 버전의 Visual Studio에서는 DesignMode 속성이 버그가 있음을 알았습니다. 따라서 다음 논리를 사용하여 직접 만들었습니다.
Process.GetCurrentProcess().ProcessName.ToLower().Trim() == "devenv";
해킹의 종류, 나는 알고 있지만 잘 작동합니다.
여기서 대부분의 답변을 테스트 한 후 불행히도 아무것도 도움이되지 않았습니다 (VS2015). 그래서 DesignMode는 Control 클래스의 보호 속성이므로 JohnV 's answer 에 약간의 왜곡을가했습니다.
먼저 Reflection을 통해 DesignMode의 속성 값을 반환하는 확장 메서드를 만들었습니다.
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();
}
이 문제를 해결하기 위해 다음과 같이 코딩 할 수도 있습니다.
private bool IsUnderDevelopment
{
get
{
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
if (process.ProcessName.EndsWith(".vshost")) return true;
else return false;
}
}