태그 보관물: user-controls

user-controls

중첩 된 컨트롤이있는 DesignMode 프로세스의 이름을 확인하는 것이 었으며

컨트롤을 개발할 때 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;
        }
    }
}