Wykrywanie trybu projektowania z konstruktora Control

99

Kontynuując to pytanie , czy możliwe jest wykrycie, czy jest się w trybie projektowania lub wykonywania z poziomu konstruktora obiektu?

Zdaję sobie sprawę, że może to nie być możliwe i że będę musiał zmienić to, co chcę, ale na razie interesuje mnie to konkretne pytanie.

nwahmaet
źródło

Odpowiedzi:

193

Możesz użyć wyliczenia LicenceUsageMode w System.ComponentModelprzestrzeni nazw:

bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
adrianbanks
źródło
2
Eleganckie rozwiązanie, działa lepiej niż funkcjonalność C # ISite.DesignMode.
56ka
10
@Filip Kunc: jeśli to nie działa w OnPaint, możesz sprawdzić ten warunek w konstruktorze i zapisać go w polu klasy.
IMil
3
Nie działa to również w przypadku zastępowania WndProc w kontrolce użytkownika. Musi skorzystać z sugestii @IMil
Matt Skeldon
1
umieszczenie go w konstrukcji jest fajnym pomysłem IMil, zadziałało dla mnie .. Próbowałem umieścić to na statycznym polu klas, ale (myślę), że pola klas statycznych zostały zainicjowane przy ich pierwszym wywołaniu, więc nie jest to bezpieczne rozwiązanie ..
Ibrahim Ozdemir
22

Szukasz czegoś takiego:

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

Możesz to również zrobić, sprawdzając nazwę procesu:

if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv")
   return true;
Jarek
źródło
4
Działa w OnPaint, klasach pochodnych, konstruktorach itp. Najlepsze rozwiązanie.
Filip Kunc
14
IMHO, to wygląda na brzydkie rozwiązanie.
Camilo Martin
5
Uwaga na możliwy wyciek pamięci. Proces należy usunąć.
nalply
7
Chociaż jestem pewien, że zadziała to dobrze w większości przypadków użycia, to rozwiązanie ma jedną zasadniczą wadę: Visual Studio nie jest (przynajmniej w teorii) jedynym hostem projektanta. Dlatego to rozwiązanie będzie działać tylko wtedy, gdy projektant jest hostowany przez aplikację o nazwie devenv.
stakx - już nie publikuje
2
Działa na VS2013, w przeciwieństwie do obecnie akceptowanej odpowiedzi.
Moby Disk
9

Komponent ... o ile wiem, nie ma właściwości DesignMode. Ta właściwość jest udostępniana przez Control. Ale problem polega na tym, że CustomControl znajduje się w formularzu w projektancie, to CustomControl działa w trybie środowiska uruchomieniowego.

Doświadczyłem, że właściwość DesignMode działa poprawnie tylko w Form.

Vaclav Svara
źródło
Dzięki za wskazówkę! Nigdy wcześniej nie zdawałem sobie z tego sprawy, ale ma to sens. Korzystanie z metody LicenseManager dostarczanej przez adrianbanks sprawdza się doskonale w tych przypadkach, gdy kontrolka jest osadzona w innej kontrolce / formularzu. +1 za każdego!
Josh Stribling
1
+1 Masz absolutną rację, takie też było moje doświadczenie. Po umieszczeniu formantu użytkownika w formularzu, jeśli wystąpią jakiekolwiek zdarzenia myszy lub zdarzenia ładowania, DesignMode nadal będzie wyświetlany jako fałszywy, ponieważ nie jesteś w trybie projektowania dla tej kontrolki. Z mojego doświadczenia wynika, że ​​powoduje to dość poważne awarie Visual Studio.
Kyle B
8

Kontrolki (formularze, kontrolki użytkownika itp.) Dziedziczą, Component classco ma bool property DesignMode:

if(DesignMode)
{
  //If in design mode
}
format c
źródło
4
Które nie jest ustawione, gdy konstruktor działa, czyli pierwsze wydanie OP. Pierwsza chwila, w której możesz go użyć, jest w OnHandleCreated.
Ray
8

WAŻNY

Istnieje różnica w używaniu Windows Forms lub WPF !!

Mają różnych projektantów i wymagają różnych kontroli . Ponadto jest to trudne w przypadku mieszania formantów Forms i WPF. (np. kontrolki WPF w oknie formularzy)

Jeśli masz tylko Windows Forms , użyj tego:

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

Jeśli masz tylko WPF , użyj tego sprawdzenia:

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

Jeśli masz mieszane użycie formularzy i WPF, użyj takiego sprawdzenia:

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
}

Aby zobaczyć bieżący tryb, możesz wyświetlić MessageBox do debugowania:

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

Uwaga:

Musisz dodać przestrzenie nazw System.ComponentModel i System.Diagnostics .

Piękno
źródło
Myślę, że twoje nazewnictwo jest mylące. W przypadku używania dla WinForms nazewnictwo to „isInWpfDesignerMode”, a dla WPF „isInFormsDesignerMode”
M Stoerzel
5

Należy użyć właściwości Component.DesignMode. O ile wiem, nie powinno to być używane przez konstruktora.

Ula Krukar
źródło
7
To nie działa, gdy kontrolka znajduje się wewnątrz innej kontrolki lub formularza, który jest projektowany.
Eric
1
Właściwie to działa całkiem nieźle w moich komponentach. Zawsze musiałem dodawać if (!DesignMode)metody OnPaint, aby upewnić się, że nie spamuje czasu projektowania.
Bitterblue
4

Inna ciekawa metoda jest opisana na tym blogu: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or -tryb użytkownika/

Zasadniczo sprawdza, czy zestaw wykonawczy jest statycznie przywoływany z zestawu wejścia. Zapobiega to konieczności śledzenia nazw zestawów („devenv.exe”, „monodevelop.exe”…).

Jednak nie działa we wszystkich innych scenariuszach, w których zestaw jest ładowany dynamicznie (jednym z przykładów jest VSTO).

user492238
źródło
Link jest (faktycznie) uszkodzony. Zamiast tego przekierowuje do najnowszego posta na blogu (obecnie 2016-03).
Peter Mortensen
3

Przy współpracy projektanta ... Może być stosowany w Sterownikach, Komponenty, w każdym miejscu

    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(linie powinny zostać usunięte. To tylko upewnia mnie, że działa poprawnie.

Vaclav Svara
źródło
3

Możesz tego użyć

if (DesignerProperties.GetIsInDesignMode(this))
{
...
}
Derek Tremblay
źródło
Ta odpowiedź dotyczy WPF, pytanie dotyczy WinForms.
Rhys Jones
1

Oto metoda, którą zastosowałem w swoim projekcie:

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

Uwaga !!!: Zwrócony kod bool oznacza NIE w trybie projektowania!

qaqz111
źródło
1
    private void CtrlSearcher_Load(object sender, EventArgs e)
    {
           if(!this.DesignMode) InitCombos();
    }
Ángel Ibáñez
źródło
Chociaż ten kod może odpowiedzieć na pytanie, dostarczenie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
Tiago Martins Peres 李大仁
0

Rozwiązanie LicenseManager nie działa wewnątrz OnPaint, podobnie jak this.DesignMode. Sięgnąłem po to samo rozwiązanie co @Jarek.

Oto wersja z pamięci podręcznej:

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

        return isDesignMode.Value;
    }

Należy pamiętać, że to się nie powiedzie, jeśli używasz środowiska IDE innej firmy lub jeśli Microsoft (lub Twój użytkownik końcowy) zdecyduje się zmienić nazwę pliku wykonywalnego VS na inną niż „devenv”. Wskaźnik awaryjności będzie bardzo niski, po prostu upewnij się, że poradzisz sobie z wynikającymi z tego błędami, które mogą wystąpić w kodzie, który z tego powodu zawodzi, a wszystko będzie dobrze.

Obrabować
źródło
0

Jeśli chcesz uruchomić niektóre wiersze, gdy jest uruchomiony, ale nie w projektancie programu Visual Studio, należy zaimplementować właściwość DesignMode w następujący sposób:

// 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.
źródło
0

Timery, które są domyślnie włączone, mogą powodować awarie podczas korzystania z elementów sterujących niestandardowych / użytkownika. Wyłącz je domyślnie i włącz dopiero po sprawdzeniu trybu projektowania

   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
źródło