Rilevamento della modalità di progettazione dal costruttore di un controllo


99

A seguito di questa domanda , è possibile rilevare se si è in modalità progettazione o runtime dall'interno del costruttore di un oggetto?

Mi rendo conto che questo potrebbe non essere possibile e che dovrò cambiare quello che voglio, ma per ora sono interessato a questa domanda specifica.

Risposte:


193

È possibile utilizzare l' enumerazione LicenceUsageMode nello System.ComponentModelspazio dei nomi:

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

2
Soluzione elegante, funziona meglio della funzionalità C # ISite.DesignMode.
56ka

10
@Filip Kunc: se questo non funziona in OnPaint, puoi controllare questa condizione nel costruttore e memorizzarla in un campo di classe.
IMil

3
Anche questo non funziona quando si sovrascrive WndProc in un controllo utente. Deve usare il suggerimento di @IMil
Matt Skeldon

1
metterlo nella costruzione è una bella idea IMil, ha funzionato per me .. ho provato a metterlo in un campo di classi statiche, ma (penso) i campi di classi statiche inizializzati quando li hai chiamati per la prima volta, quindi non una soluzione sicura ..
Ibrahim Ozdemir

22

Stai cercando qualcosa di simile:

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

Puoi farlo anche controllando il nome del processo:

if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv")
   return true;

4
Funziona in OnPaint, classi derivate, costruttori, ecc. La migliore soluzione ancora.
Filip Kunc

14
IMHO, questa sembra una brutta soluzione.
Camilo Martin

5
Attenzione possibile perdita di memoria qui. Il processo deve essere smaltito.
nalply

7
Anche se sono sicuro che funzionerà bene nella maggior parte dei casi d'uso, questa soluzione ha un difetto principale: Visual Studio non è (almeno in teoria) l'unico host di progettazione. Pertanto, questa soluzione funzionerà solo se il tuo designer è ospitato da un'applicazione chiamata devenv.
stakx - non contribuisce più

2
Funziona su VS2013, a differenza della risposta attualmente accettata.
Moby Disk

9

Componente ... per quanto ne so non ha la proprietà DesignMode. Questa proprietà è fornita da Control. Ma il problema è che quando CustomControl si trova in un form nella finestra di progettazione, questo CustomControl è in esecuzione in modalità runtime.

Ho riscontrato che la proprietà DesignMode funziona correttamente solo in Form.


Grazie per il consiglio! Non l'avevo mai capito prima, ma ha perfettamente senso. L'utilizzo del metodo LicenseManager fornito da adrianbanks funziona perfettamente in questi casi, in cui il controllo è incorporato in un altro controllo / modulo. +1 per ciascuno!
Josh Stribling

1
+1 Hai perfettamente ragione, questa è stata anche la mia esperienza. Quando si posiziona un controllo utente su un modulo, se sono presenti eventi mouseenter o caricamento, DesignMode verrà comunque visualizzato come falso perché non si è in modalità di progettazione per questo controllo. Nella mia esperienza fa sì che lo studio visivo si blocchi piuttosto duramente.
Kyle B

8

I controlli (moduli, controlli utente ecc.) Ereditano Component classche ha bool property DesignModecosì:

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

4
Che non è impostato quando viene eseguito il costruttore, ovvero il problema iniziale dell'OP. Il primo momento in cui puoi usarlo è dentro OnHandleCreated.
Ray

8

IMPORTANTE

C'è una differenza nell'usare Windows Form o WPF !!

Hanno designer diversi e necessitano di controlli diversi . Inoltre è complicato quando si combinano moduli e controlli WPF. (es. controlli WPF all'interno di una finestra Forms)

Se hai solo Windows Form , usa questo:

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

Se hai solo WPF , usa questo controllo:

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

Se hai un utilizzo misto di Moduli e WPF, usa un controllo come questo:

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
}

Per vedere la modalità corrente puoi mostrare un MessageBox per il debug:

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

Nota:

È necessario aggiungere gli spazi dei nomi System.ComponentModel e System.Diagnostics .


Penso che il tuo nome sia fuorviante. Quando si utilizza per WinForms la denominazione è 'isInWpfDesignerMode' e per WPF è 'isInFormsDesignerMode'
M Stoerzel

5

È necessario utilizzare la proprietà Component.DesignMode. Per quanto ne so, questo non dovrebbe essere usato da un costruttore.


7
Questo non funziona quando il controllo si trova all'interno di un altro controllo o modulo in fase di progettazione.
Eric,

1
In realtà funziona abbastanza bene nei miei componenti. Ho sempre dovuto aggiungere if (!DesignMode)metodi di OnPaint per assicurarmi che non inviasse il tempo di progettazione.
Bitterblue

4

Un altro metodo interessante è descritto su quel blog: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or -usermode /

Fondamentalmente, verifica l'assembly in esecuzione a cui si fa riferimento staticamente dall'assembly di ingresso. Evita la necessità di tenere traccia dei nomi degli assembly ('devenv.exe', 'monodevelop.exe' ..).

Tuttavia, non funziona in tutti gli altri scenari, in cui l'assembly viene caricato dinamicamente (VSTO è un esempio).


Il collegamento è (effettivamente) interrotto. Ora reindirizza invece all'ultimo post del blog (attualmente 2016-03).
Peter Mortensen

3

Con la collaborazione del progettista ... Può essere utilizzato in Controlli, Componenti, in tutti i luoghi

    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(le linee dovrebbero essere rimosse. Mi fa solo essere sicuro che funzioni correttamente.


3

Puoi usarlo

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

Questa risposta è per WPF, la domanda riguarda WinForms.
Rhys Jones,

1

Questo è il metodo che ho usato nel mio progetto:

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

Attenzione !!!: Il codice bool restituito indica NON in modalità progettazione!


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

Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo su come e / o perché risolve il problema migliorerebbe il valore a lungo termine della risposta.
Tiago Martins Peres 李大仁

0

La soluzione LicenseManager non funziona all'interno di OnPaint, e nemmeno this.DesignMode. Ho fatto ricorso alla stessa soluzione di @Jarek.

Ecco la versione cache:

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

        return isDesignMode.Value;
    }

Tieni presente che questo fallirà se stai utilizzando un IDE di terze parti o se Microsoft (o il tuo utente finale) decide di cambiare il nome dell'eseguibile VS con qualcosa di diverso da "devenv". Il tasso di errore sarà molto basso, assicurati solo di gestire eventuali errori risultanti che potrebbero verificarsi nel codice che non riesce a causa di ciò e starai bene.


0

Se desideri eseguire alcune righe quando è in esecuzione ma non nella finestra di progettazione di Visual Studio, devi implementare la proprietà DesignMode come segue:

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

I timer abilitati per impostazione predefinita possono causare arresti anomali quando si utilizzano controlli personalizzati / utente. Disabilitarli per impostazione predefinita e abilitarli solo dopo il controllo della modalità di progettazione

   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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.