Mendeteksi mode desain dari konstruktor Kontrol

99

Setelah pertanyaan ini , apakah mungkin untuk mendeteksi apakah seseorang dalam mode desain atau runtime dari dalam konstruktor objek?

Saya menyadari bahwa ini mungkin tidak dapat dilakukan, dan saya harus mengubah apa yang saya inginkan, tetapi untuk saat ini saya tertarik dengan pertanyaan khusus ini.

nwahmaet
sumber

Jawaban:

193

Anda dapat menggunakan pencacahan LicenceUsageMode di System.ComponentModelnamespace:

bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
adrianbanks
sumber
2
Solusi elegan, ini bekerja lebih baik daripada fungsionalitas C # ISite.DesignMode.
56ka
10
@Filip Kunc: jika ini tidak berfungsi di OnPaint, Anda dapat memeriksa kondisi ini dalam konstruktor dan menyimpannya di bidang kelas.
IMil
3
Ini juga tidak berfungsi saat mengganti WndProc di kontrol pengguna. Harus menggunakan saran @IMil
Matt Skeldon
1
memasukkannya ke dalam konstruksi adalah ide yang bagus IMil, itu berhasil untuk saya .. saya mencoba meletakkannya di bidang kelas statis, tetapi (menurut saya) bidang kelas statis diinisialisasi ketika Anda pertama kali memanggil mereka, jadi bukan solusi yang aman ..
Ibrahim Ozdemir
22

Apakah Anda mencari sesuatu seperti ini:

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

Anda juga dapat melakukannya dengan memeriksa nama proses:

if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv")
   return true;
Jarek
sumber
4
Bekerja di OnPaint, kelas turunan, konstruktor, dll. Solusi terbaik.
Filip Kunc
14
IMHO, ini sepertinya solusi yang buruk.
Camilo Martin
5
Perhatikan kemungkinan kebocoran memori di sini. Proses harus dibuang.
Nalply
7
Meskipun saya yakin ini akan berfungsi dengan baik di sebagian besar kasus penggunaan, solusi ini memiliki satu kelemahan utama: Visual Studio (setidaknya dalam teori) bukan satu-satunya host desainer. Oleh karena itu, solusi ini hanya akan berfungsi jika desainer Anda dihosting oleh aplikasi bernama devenv.
stakx - tidak lagi berkontribusi
2
Berfungsi pada VS2013, tidak seperti jawaban yang diterima saat ini.
Moby Disk
9

Komponen ... sejauh yang saya tahu tidak memiliki properti DesignMode. Properti ini disediakan oleh Control. Namun masalahnya adalah ketika CustomControl terletak di Formulir di desainer, CustomControl ini berjalan dalam mode runtime.

Saya telah mengalami bahwa properti DesignMode hanya berfungsi dengan benar dalam Formulir.

Vaclav Svara
sumber
Terima kasih atas tipnya! Saya tidak pernah menyadarinya sebelumnya, tetapi itu masuk akal. Menggunakan metode LicenseManager yang disediakan oleh adrianbanks berfungsi sempurna dalam kasus ini, di mana kontrol disematkan di kontrol / formulir lain. 1 untuk masing-masing!
Josh Stribling
1
+1 Anda benar sekali, ini juga pengalaman saya. Saat Anda menempatkan kontrol pengguna pada formulir, jika ada mouseenter atau memuat peristiwa DesignMode masih akan muncul sebagai salah karena Anda tidak dalam designmode untuk kontrol ini. Menurut pengalaman saya, hal itu menyebabkan studio visual mengalami crash cukup keras.
Kyle B
8

Kontrol (Formulir, UserControls, dll.) Mewarisi Component classyang memiliki bool property DesignMode:

if(DesignMode)
{
  //If in design mode
}
formatc
sumber
4
Yang tidak disetel saat konstruktor dijalankan, alias masalah awal OP. Saat pertama Anda dapat menggunakannya adalah dalam OnHandleCreated.
Ray
8

PENTING

Ada perbedaan dalam menggunakan Formulir Windows atau WPF !!

Mereka memiliki desainer yang berbeda dan membutuhkan pemeriksaan yang berbeda . Selain itu, sulit saat Anda mencampur formulir dan kontrol WPF. (misalnya kontrol WPF di dalam jendela Formulir)

Jika Anda hanya memiliki Formulir Windows , gunakan ini:

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

Jika Anda hanya memiliki WPF , gunakan pemeriksaan ini:

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

Jika Anda memiliki penggunaan campuran Formulir dan WPF, gunakan tanda centang seperti ini:

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
}

Untuk melihat mode saat ini, Anda dapat menampilkan MessageBox untuk debugging:

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

Ucapan:

Anda perlu menambahkan ruang nama System.ComponentModel dan System.Diagnostics .

Kecantikan
sumber
Saya pikir penamaan Anda menyesatkan. Saat menggunakan untuk WinForms penamaannya adalah 'isInWpfDesignerMode' dan untuk WPF adalah 'isInFormsDesignerMode'
M Stoerzel
5

Anda harus menggunakan properti Component.DesignMode. Sejauh yang saya tahu, ini tidak boleh digunakan dari konstruktor.

Ula Krukar
sumber
7
Ini tidak berfungsi saat kontrol Anda berada di dalam kontrol atau formulir lain yang sedang dirancang.
Eric
1
Sebenarnya ini bekerja cukup baik di komponen saya. Saya selalu harus menambahkan if (!DesignMode)metode OnPaint untuk memastikannya tidak mengirim spam waktu desain.
Bitterblue
4

Metode lain yang menarik dijelaskan di blog itu: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or -mode pengguna/

Pada dasarnya, ini menguji rakitan pelaksana yang direferensikan secara statis dari rakitan entri. Ini menghindari kebutuhan untuk melacak nama assembly ('devenv.exe', 'monodevelop.exe' ..).

Namun, itu tidak bekerja di semua skenario lain, di mana rakitan dimuat secara dinamis (VSTO menjadi salah satu contoh).

pengguna492238
sumber
Tautan (secara efektif) rusak. Sekarang beralih ke posting blog terbaru (saat ini 2016-03) sebagai gantinya.
Peter Mortensen
3

Dengan kerja sama perancang ... Dapat digunakan di Kontrol, Komponen, di semua tempat

    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(garis harus dihapus. Itu hanya membuat saya yakin itu berfungsi dengan benar.

Vaclav Svara
sumber
3

Anda bisa menggunakan ini

if (DesignerProperties.GetIsInDesignMode(this))
{
...
}
Derek Tremblay
sumber
Jawaban ini untuk WPF, pertanyaannya tentang WinForms.
Rhys Jones
1

Ini adalah metode yang saya gunakan dalam proyek saya:

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

Perhatian !!!: Kode yang dikembalikan bool menunjukkan TIDAK dalam mode desain!

qaqz111
sumber
1
    private void CtrlSearcher_Load(object sender, EventArgs e)
    {
           if(!this.DesignMode) InitCombos();
    }
Ángel Ibáñez
sumber
Meskipun kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan / atau mengapa kode ini memecahkan masalah akan meningkatkan nilai jangka panjang jawaban.
Tiago Martins Peres 李大仁
0

Solusi LicenseManager tidak berfungsi di dalam OnPaint, begitu pula this.DesignMode. Saya menggunakan solusi yang sama dengan @Jarek.

Berikut versi cache:

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

        return isDesignMode.Value;
    }

Ketahuilah bahwa ini akan gagal jika Anda menggunakan IDE pihak ketiga atau jika Microsoft (atau pengguna akhir Anda) memutuskan untuk mengubah nama VS yang dapat dieksekusi menjadi sesuatu selain 'devenv'. Tingkat kegagalan akan sangat rendah, cukup pastikan Anda menangani kesalahan yang dihasilkan yang mungkin terjadi dalam kode yang gagal sebagai akibatnya dan Anda akan baik-baik saja.

rampok
sumber
0

Jika Anda ingin menjalankan beberapa baris saat sedang berjalan tetapi tidak di desainer Visual Studio, Anda harus menerapkan properti DesignMode sebagai berikut:

// 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.
sumber
0

Pengatur waktu yang diaktifkan secara default dapat menyebabkan kerusakan saat menggunakan kontrol kustom / pengguna. Nonaktifkan mereka secara default, dan aktifkan hanya setelah pemeriksaan mode desain

   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
sumber