Detectando o modo de design de um construtor de controle

99

Seguindo com esta pergunta , é possível detectar se alguém está no modo de design ou tempo de execução de dentro do construtor de um objeto?

Sei que isso pode não ser possível e que terei que mudar o que desejo, mas por enquanto estou interessado nesta questão específica.

nwahmaet
fonte

Respostas:

192

Você pode usar a enumeração LicenceUsageMode no System.ComponentModelnamespace:

bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
Adrianbanks
fonte
2
Solução elegante, funciona melhor do que a funcionalidade C # ISite.DesignMode.
56ka
10
@Filip Kunc: se isso não funcionar no OnPaint, você pode verificar esta condição no construtor e armazená-la em um campo de classe.
IMil
3
Isso também não funciona ao substituir WndProc em um controle de usuário. Tem que usar a sugestão @IMil
Matt Skeldon
1
colocá-lo na construção é uma boa ideia IMil, funcionou para mim .. tentei colocá-lo em um campo de classes estáticas, mas (eu acho) campos de classes estáticas inicializados quando você os chamou pela primeira vez, então não é uma solução segura.
Ibrahim Ozdemir
22

Você está procurando algo parecido com isto:

public static bool IsInDesignMode()
{
    if (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1)
    {
        return true;
    }
    return false;
}

Você também pode fazer isso verificando o nome do processo:

if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv")
   return true;
Jarek
fonte
4
Funciona em OnPaint, classes derivadas, construtores, etc. Melhor solução ainda.
Filip Kunc
14
IMHO, isso parece uma solução feia.
Camilo Martin
5
Atenção possível vazamento de memória aqui. O processo deve ser descartado.
basicamente
7
Embora eu tenha certeza de que funcionará bem na maioria dos casos de uso, essa solução tem uma falha principal: o Visual Studio (pelo menos em teoria) não é o único host de designer. Portanto, esta solução só funcionará se o seu designer estiver hospedado por um aplicativo chamado devenv.
stakx - não contribuindo mais
2
Funciona no VS2013, ao contrário da resposta aceita atualmente.
Moby Disk
9

Componente ... até onde eu sei, não tem a propriedade DesignMode. Esta propriedade é fornecida por Control. Mas o problema é que quando CustomControl está localizado em um Form no designer, esse CustomControl está rodando em modo runtime.

Eu percebi que a propriedade DesignMode funciona corretamente apenas no Form.

Vaclav Svara
fonte
Obrigado pela dica! Eu nunca percebi isso antes, mas faz todo o sentido. Usar o método LicenseManager fornecido por adrianbanks funciona perfeitamente nesses casos, onde o controle está embutido em outro controle / formulário. 1 para cada!
Josh Stribling
1
+1 Você está absolutamente certo, esta tem sido minha experiência também. Quando você coloca um controle de usuário em um formulário, se houver qualquer mouseenter ou eventos de carregamento, o DesignMode ainda aparecerá como falso porque você não está no modo de design para este controle. Na minha experiência, isso faz com que o Visual Studio trave muito.
Kyle B,
8

Os controles (formulários, controles do usuário etc.) herdam o Component classque tem bool property DesignMode:

if(DesignMode)
{
  //If in design mode
}
formatc
fonte
4
Que não é definido quando o construtor é executado, também conhecido como o problema inicial do OP. O primeiro momento em que você pode usá-lo é em OnHandleCreated.
Ray
8

IMPORTANTE

Existe uma diferença de usar Windows Forms ou WPF !!

Eles têm designers diferentes e precisam de verificações diferentes . Além disso, é complicado quando você mistura controles de formulários e WPF. (por exemplo, controles WPF dentro de uma janela do Formulários)

Se você tiver apenas Windows Forms , use este:

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

Se você tiver apenas WPF , use esta verificação:

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

Se você misturou o uso de formulários e WPF, use uma verificação como esta:

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
}

Para ver o modo atual, você pode mostrar uma MessageBox para depuração:

// show current mode
MessageBox.Show(String.Format("DESIGNER CHECK:  WPF = {0}   Forms = {1}", isInWpfDesignerMode, isInFormsDesignerMode));

Observação:

Você precisa adicionar os namespaces System.ComponentModel e System.Diagnostics .

Beleza
fonte
Eu acho que sua nomenclatura é enganosa. Ao usar para WinForms, a nomenclatura é 'isInWpfDesignerMode' e para WPF é 'isInFormsDesignerMode'
M Stoerzel
5

Você deve usar a propriedade Component.DesignMode. Pelo que eu sei, isso não deve ser usado por um construtor.

Ula Krukar
fonte
7
Isso não funciona quando seu controle está dentro de outro controle ou formulário que está sendo projetado.
Eric
1
Na verdade, funciona muito bem em meus componentes. Sempre tive que adicionar if (!DesignMode)métodos do OnPaint para ter certeza de que não era spam o tempo de design.
Bitterblue de
4

Outro método interessante é descrito nesse blog: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or -modo de usuário/

Basicamente, ele testa o assembly em execução sendo referenciado estaticamente no assembly de entrada. Ele contorna a necessidade de rastrear nomes de assemblies ('devenv.exe', 'monodevelop.exe' ..).

No entanto, ele não funciona em todos os outros cenários, nos quais o assembly é carregado dinamicamente (o VSTO é um exemplo).

user492238
fonte
O link está (efetivamente) quebrado. Agora, ele redireciona para a última postagem do blog (atualmente 2016-03).
Peter Mortensen de
3

Com a cooperação do designer ... Pode ser usado em Controles, Componentes, em todos os lugares

    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(linhas devem ser removidas. Isso só me garante que funciona corretamente.

Vaclav Svara
fonte
3

Você pode usar isso

if (DesignerProperties.GetIsInDesignMode(this))
{
...
}
Derek Tremblay
fonte
Esta resposta é para WPF, a pergunta é sobre WinForms.
Rhys Jones
1

Este é o método que usei em meu projeto:

//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
        ;
}

Atenção !!!: O código retornado bool está indicando NÃO no modo de design!

qaqz111
fonte
1
    private void CtrlSearcher_Load(object sender, EventArgs e)
    {
           if(!this.DesignMode) InitCombos();
    }
Ángel Ibáñez
fonte
Embora este código possa responder à pergunta, fornecer contexto adicional sobre como e / ou por que ele resolve o problema melhoraria o valor da resposta a longo prazo.
Tiago Martins Peres李大仁
0

A solução LicenseManager não funciona dentro do OnPaint, nem this.DesignMode. Recorri à mesma solução de @Jarek.

Esta é a versão em cache:

    private static bool? isDesignMode;
    private static bool IsDesignMode()
    {
        if (isDesignMode == null)
            isDesignMode = (Process.GetCurrentProcess().ProcessName.ToLower().Contains("devenv"));

        return isDesignMode.Value;
    }

Esteja ciente de que isso irá falhar se você estiver usando qualquer IDE de terceiros ou se a Microsoft (ou seu usuário final) decidir alterar o nome do executável do VS para algo diferente de 'devenv'. A taxa de falha será muito baixa, apenas certifique-se de lidar com quaisquer erros resultantes que possam ocorrer no código que falha como resultado disso e você ficará bem.

Roubar
fonte
0

Se você deseja executar algumas linhas enquanto está sendo executado, mas não no designer do Visual Studio, você deve implementar a propriedade DesignMode da seguinte maneira:

// 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();
}
Giovanny Farto M.
fonte
0

Os temporizadores ativados por padrão podem causar travamento ao usar controles personalizados / do usuário. Desative-os por padrão e ative somente após a verificação do modo de design

   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;
Ayson Baxter
fonte