Control의 생성자에서 디자인 모드 감지


99

이 질문 에 이어 객체의 생성자 내에서 디자인 모드인지 런타임 모드인지 감지 할 수 있습니까?

나는 이것이 가능하지 않을 수 있으며 내가 원하는 것을 변경해야 할 것임을 알고 있지만 지금은이 특정 질문에 관심이 있습니다.

답변:


192

네임 스페이스 에서 LicenceUsageMode 열거를 사용할 수 있습니다 System.ComponentModel.

bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);

2
우아한 솔루션, C # 기능보다 더 잘 작동합니다 ISite.DesignMode.
56ka

10
@Filip Kunc : OnPaint에서 작동하지 않는 경우 생성자에서이 조건을 확인하고 클래스 필드에 저장할 수 있습니다.
IMil

3
사용자 정의 컨트롤에서 WndProc를 재정의 할 때도 작동하지 않습니다. 사용 @IMil 제안한다
매트 스켈 던

1
그것을 건설에 넣는 것은 좋은 생각입니다 IMil, 그것은 나를 위해 일했습니다 .. 나는 그것을 정적 클래스 필드에 넣으려고했지만 (내 생각에) 정적 클래스 필드를 처음 호출했을 때 초기화되었으므로 안전한 솔루션이 아닙니다 ..
Ibrahim Ozdemir

22

다음과 같은 것을 찾고 있습니까?

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;

4
OnPaint, 파생 클래스, 생성자 등에서 작동합니다. 아직 최고의 솔루션입니다.
Filip Kunc 2010

14
IMHO, 이것은 추악한 해결책처럼 보입니다.
Camilo Martin 2011

5
여기에서 메모리 누수가 발생할 수 있습니다. 프로세스를 폐기해야합니다.
nalply

7
대부분의 사용 사례에서 이것이 잘 작동 할 것이라고 확신하지만이 솔루션에는 한 가지 주요 결함이 있습니다. Visual Studio는 (적어도 이론적으로는) 유일한 디자이너 호스트가 아닙니다. 따라서이 솔루션은 디자이너가라는 응용 프로그램에서 호스팅되는 경우에만 작동합니다 devenv.
stakx-더 이상

2
현재 허용되는 답변과 달리 VS2013에서 작동합니다.
Moby Disk

9

구성 요소 ... 내가 아는 한 DesignMode 속성이 없습니다. 이 속성은 Control에서 제공합니다. 그러나 문제는 CustomControl이 디자이너의 Form에있을 때이 CustomControl이 런타임 모드에서 실행된다는 것입니다.

DesignMode 속성이 Form에서만 올바르게 작동한다는 것을 경험했습니다.


팁 고마워! 나는 그것을 전에 결코 깨닫지 못했지만 그것은 완벽하게 이해됩니다. adrianbanks에서 제공하는 LicenseManager 방법을 사용하면 컨트롤이 다른 컨트롤 / 양식에 포함 된 이러한 경우에 완벽하게 작동합니다. 각각 +1!
Josh Stribling

1
+1 당신이 절대적으로 옳습니다. 이것은 제 경험이기도합니다. 폼에 사용자 정의 컨트롤을 배치 할 때 mouseenter 또는로드 이벤트가있는 경우이 컨트롤에 대한 디자인 모드가 아니기 때문에 DesignMode는 여전히 false로 표시됩니다. 내 경험상 Visual Studio가 꽤 세게 충돌합니다.
Kyle B

8

컨트롤 (Forms, UserControls 등)은 다음 Component class을 상속합니다 bool property DesignMode.

if(DesignMode)
{
  //If in design mode
}

4
생성자가 실행될 때 설정되지 않는 OP의 초기 문제입니다. 사용할 수있는 첫 번째 순간은 OnHandleCreated.
Ray

8

중대한

Windows Forms 또는 WPF 사용에는 차이가 있습니다 !!

그들은 다른 디자이너를 가지고 있고 다른 수표 가 필요 합니다 . 또한 Forms와 WPF 컨트롤을 혼합하면 까다 롭습니다. (예 : Forms 창 내부의 WPF 컨트롤)

Windows Forms 만 있는 경우 다음을 사용하십시오.

Boolean isInWpfDesignerMode   = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);

당신이있는 경우 에만 WPF를 ,이 검사를 사용합니다 :

Boolean isInFormsDesignerMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv");

Forms와 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.ComponentModelSystem.Diagnostics 네임 스페이스를 추가해야합니다 .


이름이 잘못된 것 같습니다. WinForms에 사용하는 경우 이름은 'isInWpfDesignerMode'이고 WPF의 경우 'isInFormsDesignerMode'입니다
M Stoerzel

5

Component.DesignMode 속성을 사용해야합니다. 내가 아는 한 이것은 생성자에서 사용해서는 안됩니다.


7
컨트롤이 디자인중인 다른 컨트롤 또는 폼 내부에 있으면 작동하지 않습니다.
Eric

1
실제로 내 구성 요소에서 꽤 잘 작동합니다. if (!DesignMode)디자인 타임을 스팸하지 않도록 항상 OnPaint 메서드 를 추가 해야했습니다.
Bitterblue 2013

4

또 다른 흥미로운 방법은 해당 블로그에 설명되어 있습니다. 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가 한 예임).


링크가 (효과적으로) 끊어졌습니다. 이제 대신 최신 블로그 게시물 (현재 2016-03)로 리디렉션됩니다.
Peter Mortensen

3

디자이너의 협력으로 ... 모든 곳에서 Controls, Components에서 사용 가능

    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(줄을 제거해야합니다. 제대로 작동하는지 확인할뿐입니다.


3

이것을 사용할 수 있습니다

if (DesignerProperties.GetIsInDesignMode(this))
{
...
}

이 답변은 WPF에 대한 것이며 질문은 WinForms에 관한 것입니다.
Rhys Jones

1

이것은 내 프로젝트에서 사용한 방법입니다.

//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's output assembly info
        Assembly.GetExecutingAssembly().ToString(), //always return your project's output assembly info
    });
    //*/

    //LicenseManager.UsageMode will return RunTime if LicenseManager.context is not present.
    //So you can not return true by judging it's 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's process name if you detected by log from above
        ;
}

주의 !!! : 반환 된 bool 코드 는 디자인 모드가 아님 을 나타냅니다 !


1
    private void CtrlSearcher_Load(object sender, EventArgs e)
    {
           if(!this.DesignMode) InitCombos();
    }

이 코드는 질문에 답할 수 있지만 문제를 해결하는 방법 및 / 또는 이유에 대한 추가 컨텍스트를 제공하면 답변의 장기적인 가치가 향상됩니다.
Tiago Martins Peres 李大仁

0

LicenseManager 솔루션은 OnPaint 내에서 작동하지 않으며 this.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'가 아닌 다른 이름으로 변경하기로 결정한 경우이 작업이 실패합니다. 실패율은 매우 낮을 것입니다. 이로 인해 실패한 코드에서 발생할 수있는 결과 오류를 처리해야합니다. 그러면 괜찮을 것입니다.


0

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();
}

0

기본적으로 활성화 된 타이머는 사용자 지정 / 사용자 컨트롤을 사용할 때 충돌을 일으킬 수 있습니다. 기본적으로 비활성화하고 디자인 모드 확인 후에 만 ​​활성화

   public chartAdapter()
    {
        try
        {

            //Initialize components come here
            InitializeComponent();

            //Design mode check
            bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
            if (designMode)
                return;

            //Enable timers ONLY after designmode check, or else crash
            timerAutoConnect.Enabled = timerDraw.Enabled = true;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.