컨트롤을 개발할 때 DesignMode 문제에 대한 유용한 솔루션을 찾은 사람이 있습니까?
문제는 컨트롤을 중첩하면 DesignMode가 첫 번째 수준에서만 작동한다는 것입니다. 두 번째 및 하위 수준 DesignMode는 항상 FALSE를 반환합니다.
표준 해킹은 실행중인 프로세스의 이름을 확인하는 것이 었으며 “DevEnv.EXE”인 경우 스튜디오 여야하므로 DesignMode는 실제로 TRUE입니다.
ProcessName을 찾는 문제는 레지스트리 및 기타 이상한 부분을 통해 작동하며 사용자가 프로세스 이름을 보는 데 필요한 권한이 없을 수도 있습니다. 또한이 이상한 경로는 매우 느립니다. 그래서 우리는 싱글 톤을 사용하기 위해 추가 핵을 쌓아야했고 프로세스 이름을 요청할 때 오류가 발생하면 DesignMode가 FALSE라고 가정합니다.
DesignMode를 결정하는 좋은 방법은 순서입니다. Microsoft가 내부적으로 프레임 워크에 수정하도록하는 것이 훨씬 더 좋습니다!
답변
이 질문을 다시 살펴보면서 나는 다음과 같은 5 가지 방법을 ‘발견’했습니다.
System.ComponentModel.DesignMode property
System.ComponentModel.LicenseManager.UsageMode property
private string ServiceString()
{
if (GetService(typeof(System.ComponentModel.Design.IDesignerHost)) != null)
return "Present";
else
return "Not present";
}
public bool IsDesignerHosted
{
get
{
Control ctrl = this;
while(ctrl != null)
{
if((ctrl.Site != null) && ctrl.Site.DesignMode)
return true;
ctrl = ctrl.Parent;
}
return false;
}
}
public static bool IsInDesignMode()
{
return System.Reflection.Assembly.GetExecutingAssembly()
.Location.Contains("VisualStudio"))
}
제안 된 세 가지 솔루션에 대해 알아보기 위해 세 가지 프로젝트로 작은 테스트 솔루션을 만들었습니다.
- TestApp (winforms 애플리케이션),
- SubControl (dll)
- SubSubControl (dll)
그런 다음 SubControl에 SubSubControl을 삽입 한 다음 TestApp.Form에 각각 하나씩 삽입했습니다.
이 스크린 샷은 실행시 결과를 보여줍니다.
이 스크린 샷은 Visual Studio에서 열린 양식의 결과를 보여줍니다.
결론 : 리플렉션없이 생성자 내 에서 신뢰할 수있는 유일한 것은 LicenseUsage이고 생성자 외부 에서 신뢰할 수있는 유일한 것은 ‘IsDesignedHosted'( 아래 BlueRaja에 의해 ) 인 것으로 보입니다.
추신 : 아래 ToolmakerSteve의 의견을 참조하십시오 (내가 테스트하지 않았습니다) : ” IsDesignerHosted 답변이 LicenseUsage를 포함하도록 업데이트되었으므로 이제 테스트는 단순히 (IsDesignerHosted) 일 수 있습니다. 대체 접근 방식은 생성자에서 LicenseManager를 테스트 하는 것입니다. 결과를 캐시합니다 . “
답변
에서 이 페이지 :
( [Edit 2013] @hopla에서 제공하는 방법을 사용하여 생성자에서 작업하도록 편집)
/// <summary>
/// The DesignMode property does not correctly tell you if
/// you are in design mode. IsDesignerHosted is a corrected
/// version of that property.
/// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305
/// and http://stackoverflow.com/a/2693338/238419 )
/// </summary>
public bool IsDesignerHosted
{
get
{
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
return true;
Control ctrl = this;
while (ctrl != null)
{
if ((ctrl.Site != null) && ctrl.Site.DesignMode)
return true;
ctrl = ctrl.Parent;
}
return false;
}
}
Microsoft에 버그 보고서 를 제출 했습니다 . 나는이 (그것의 여부 버그 분명히으로는, 어디든 갈하지만 어쨌든 그것을 투표 의심 “디자인은” ).
답변
LicenseManager.UsageMode를 확인하지 않는 이유는 무엇입니까? 이 속성은 LicenseUsageMode.Runtime 또는 LicenseUsageMode.Designtime 값을 가질 수 있습니다.
코드를 런타임에서만 실행하려면 다음 코드를 사용하십시오.
if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
{
bla bla bla...
}
답변
이것은 양식 내부에서 사용하는 방법입니다.
/// <summary>
/// Gets a value indicating whether this instance is in design mode.
/// </summary>
/// <value>
/// <c>true</c> if this instance is in design mode; otherwise, <c>false</c>.
/// </value>
protected bool IsDesignMode
{
get { return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; }
}
이렇게하면 DesignMode 또는 LicenseManager 속성 중 하나가 실패하더라도 결과가 정확합니다.
답변
LicenseManager 메서드를 사용하지만 인스턴스 수명 내내 사용할 수 있도록 생성자의 값을 캐시합니다.
public MyUserControl()
{
InitializeComponent();
m_IsInDesignMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
}
private bool m_IsInDesignMode = true;
public bool IsInDesignMode { get { return m_IsInDesignMode; } }
VB 버전 :
Sub New()
InitializeComponent()
m_IsInDesignMode = (LicenseManager.UsageMode = LicenseUsageMode.Designtime)
End Sub
Private ReadOnly m_IsInDesignMode As Boolean = True
Public ReadOnly Property IsInDesignMode As Boolean
Get
Return m_IsInDesignMode
End Get
End Property
답변
이 코드를 성공적으로 사용합니다.
public static bool IsRealDesignerMode(this Control c)
{
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
return true;
else
{
Control ctrl = c;
while (ctrl != null)
{
if (ctrl.Site != null && ctrl.Site.DesignMode)
return true;
ctrl = ctrl.Parent;
}
return System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv";
}
}
답변
내 제안은 @ blueraja-danny-pflughoeft 회신 최적화입니다 . 이 솔루션은 매번 결과를 계산하지 않고 처음에만 계산합니다 (객체는 디자인에서 런타임으로 UsageMode를 변경할 수 없음).
private bool? m_IsDesignerHosted = null; //contains information about design mode state
/// <summary>
/// The DesignMode property does not correctly tell you if
/// you are in design mode. IsDesignerHosted is a corrected
/// version of that property.
/// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305
/// and https://stackoverflow.com/a/2693338/238419 )
/// </summary>
[Browsable(false)]
public bool IsDesignerHosted
{
get
{
if (m_IsDesignerHosted.HasValue)
return m_IsDesignerHosted.Value;
else
{
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
{
m_IsDesignerHosted = true;
return true;
}
Control ctrl = this;
while (ctrl != null)
{
if ((ctrl.Site != null) && ctrl.Site.DesignMode)
{
m_IsDesignerHosted = true;
return true;
}
ctrl = ctrl.Parent;
}
m_IsDesignerHosted = false;
return false;
}
}
}