Erkennen des Entwurfsmodus vom Konstruktor eines Steuerelements


98

Ist es im Anschluss an diese Frage möglich, innerhalb des Konstruktors eines Objekts zu erkennen, ob sich jemand im Entwurfs- oder Laufzeitmodus befindet?

Mir ist klar, dass dies möglicherweise nicht möglich ist und ich ändern muss, was ich will, aber im Moment interessiert mich diese spezielle Frage.

Antworten:


190

Sie können die LicenceUsageMode- Enumeration im System.ComponentModelNamespace verwenden:

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

2
Elegante Lösung, es funktioniert besser als C # -Funktionalität ISite.DesignMode.
56ka

10
@Filip Kunc: Wenn dies in OnPaint nicht funktioniert, können Sie diese Bedingung im Konstruktor überprüfen und in einem Klassenfeld speichern.
IMil

3
Dies funktioniert auch nicht, wenn WndProc in einem Benutzersteuerelement überschrieben wird. Muss @ IMil Vorschlag verwenden
Matt Skeldon

1
es in die Konstruktion zu setzen ist eine nette Idee IMil, es hat bei mir funktioniert. Ich habe versucht, es in ein statisches Klassenfeld zu setzen, aber (ich denke) statische Klassenfelder wurden initialisiert, als Sie sie zum ersten Mal aufgerufen haben, also keine sichere Lösung.
Ibrahim Ozdemir

22

Suchen Sie so etwas:

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

Sie können dies auch tun, indem Sie den Prozessnamen überprüfen:

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

4
Funktioniert in OnPaint, abgeleiteten Klassen, Konstruktoren usw. Die bisher beste Lösung.
Filip Kunc

14
IMHO, das sieht nach einer hässlichen Lösung aus.
Camilo Martin

5
Achtung möglicher Speicherverlust hier. Prozess muss entsorgt werden.
Nalply

7
Obwohl ich sicher bin, dass dies in den meisten Anwendungsfällen gut funktioniert, weist diese Lösung einen Hauptfehler auf: Visual Studio ist (zumindest theoretisch) nicht der einzige Designer-Host. Daher funktioniert diese Lösung nur, wenn Ihr Designer von einer Anwendung namens gehostet wird devenv.
stakx - nicht mehr beitragen

2
Funktioniert auf VS2013 im Gegensatz zur derzeit akzeptierten Antwort.
Moby Disk

9

Komponente ... hat meines Wissens nicht die DesignMode-Eigenschaft. Diese Eigenschaft wird von Control bereitgestellt. Das Problem ist jedoch, dass CustomControl im Laufzeitmodus ausgeführt wird, wenn sich CustomControl in einem Formular im Designer befindet.

Ich habe festgestellt, dass die DesignMode-Eigenschaft nur in Form korrekt funktioniert.


Danke für den Tipp! Das habe ich noch nie bemerkt, aber es macht vollkommen Sinn. Die Verwendung der von adrianbanks bereitgestellten LicenseManager-Methode funktioniert in diesen Fällen einwandfrei, in denen das Steuerelement in ein anderes Steuerelement / Formular eingebettet ist. +1 für jeden!
Josh Stribling

1
+1 Sie haben absolut Recht, das war auch meine Erfahrung. Wenn Sie ein Benutzersteuerelement in ein Formular einfügen und Mausereignisse oder Ladeereignisse vorhanden sind, wird DesignMode weiterhin als falsch angezeigt, da Sie sich für dieses Steuerelement nicht im Entwurfsmodus befinden. Nach meiner Erfahrung stürzt das Visual Studio ziemlich stark ab.
Kyle B

8

Steuerelemente (Formulare, Benutzersteuerungen usw.) erben, Component classdie Folgendes haben bool property DesignMode:

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

4
Was nicht festgelegt wird, wenn der Konstruktor ausgeführt wird, auch bekannt als die erste Ausgabe des OP. Der erste Moment, in dem Sie es verwenden können, ist in OnHandleCreated.
Ray

8

WICHTIG

Es gibt einen Unterschied bei der Verwendung von Windows Forms oder WPF !!

Sie haben unterschiedliche Designer und benötigen unterschiedliche Prüfungen . Außerdem ist es schwierig, Formulare und WPF-Steuerelemente zu mischen. (zB WPF-Steuerelemente in einem Formularfenster)

Wenn Sie nur Windows Forms haben , verwenden Sie Folgendes:

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

Wenn Sie nur WPF haben , verwenden Sie diese Prüfung:

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

Wenn Sie Forms und WPF gemischt verwenden , verwenden Sie eine Prüfung wie folgt:

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
}

Um den aktuellen Modus anzuzeigen, können Sie eine MessageBox zum Debuggen anzeigen:

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

Anmerkung:

Sie müssen die Namespaces System.ComponentModel und System.Diagnostics hinzufügen .


Ich denke, Ihre Benennung ist irreführend. Bei Verwendung für WinForms lautet der Name "isInWpfDesignerMode" und für WPF "isInFormsDesignerMode"
M Stoerzel

5

Sie sollten die Component.DesignMode-Eigenschaft verwenden. Soweit ich weiß, sollte dies nicht von einem Konstruktor verwendet werden.


7
Dies funktioniert nicht, wenn sich Ihr Steuerelement in einem anderen Steuerelement oder Formular befindet, das gerade entworfen wird.
Eric

1
Eigentlich funktioniert es in meinen Komponenten ziemlich gut. Ich musste immer if (!DesignMode)OnPaint-Methoden hinzufügen , um sicherzustellen, dass die Entwurfszeit nicht durch Spam beeinträchtigt wird.
Bitterblue

4

Eine weitere interessante Methode wird in diesem Blog beschrieben: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or -Benutzermodus/

Grundsätzlich wird geprüft, ob die ausführende Assembly statisch von der Eintragsassembly referenziert wird. Es umgeht die Notwendigkeit, Baugruppennamen zu verfolgen ('devenv.exe', 'monodevelop.exe' ..).

Es funktioniert jedoch nicht in allen anderen Szenarien, in denen die Assembly dynamisch geladen wird (VSTO ist ein Beispiel).


Die Verbindung ist (effektiv) unterbrochen. Stattdessen wird jetzt zum neuesten Blog-Beitrag (derzeit 2016-03) weitergeleitet.
Peter Mortensen

3

In Zusammenarbeit mit dem Designer ... Kann in Steuerelementen, Komponenten, an allen Orten verwendet werden

    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(Linien sollten entfernt werden. Es macht mich nur sicher, dass es richtig funktioniert.


3

Sie können dies verwenden

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

Diese Antwort ist für WPF, die Frage bezieht sich auf WinForms.
Rhys Jones

1

Dies ist die Methode, die ich in meinem Projekt verwendet habe:

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

Achtung !!!: Der zurückgegebene Code bool zeigt NICHT im Designmodus an!


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

Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Tiago Martins Peres 22

0

Die LicenseManager-Lösung funktioniert weder in OnPaint noch in this.DesignMode. Ich habe auf die gleiche Lösung wie @Jarek zurückgegriffen.

Hier ist die zwischengespeicherte Version:

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

        return isDesignMode.Value;
    }

Beachten Sie, dass dies fehlschlägt, wenn Sie eine IDE eines Drittanbieters verwenden oder wenn Microsoft (oder Ihr Endbenutzer) beschließt, den Namen der ausführbaren VS-Datei in einen anderen Namen als "devenv" zu ändern. Die Fehlerrate ist sehr niedrig. Stellen Sie nur sicher, dass Sie sich mit allen resultierenden Fehlern befassen, die im Code auftreten können, der als Folge davon fehlschlägt, und es wird Ihnen gut gehen.


0

Wenn Sie einige Zeilen ausführen möchten, während sie ausgeführt werden, jedoch nicht im Visual Studio-Designer, sollten Sie die DesignMode-Eigenschaft wie folgt implementieren:

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

Standardmäßig aktivierte Timer können bei Verwendung von benutzerdefinierten Steuerelementen / Benutzersteuerelementen zum Absturz führen. Deaktivieren Sie sie standardmäßig und aktivieren Sie sie erst nach Überprüfung des Entwurfsmodus

   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;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.