Bir Control'ün yapıcısından tasarım modunu algılama


99

Bu sorunun ardından , bir nesnenin kurucusunun içinden tasarım modunda mı yoksa çalışma zamanı modunda mı olduğunu tespit etmek mümkün müdür?

Bunun mümkün olmayabileceğinin farkındayım ve istediğimi değiştirmek zorunda kalacağım, ancak şimdilik bu özel soruyla ilgileniyorum.

Yanıtlar:


193

AdSystem.ComponentModel alanında LicenceUsageMode numaralandırmasını kullanabilirsiniz :

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

2
Zarif çözüm, C # işlevinden daha iyi çalışıyor ISite.DesignMode.
56ka

10
@Filip Kunc: Bu, OnPaint'te çalışmazsa, bu durumu yapıcıda kontrol edebilir ve bir sınıf alanında saklayabilirsiniz.
2016

3
Bu, bir kullanıcı denetiminde WndProc'u geçersiz kılarken de çalışmaz. @IMil önerisini kullanmak zorunda
Matt Skeldon

1
onu inşa etmek güzel bir fikir IMil, benim için işe yaradı .. Statik sınıflar alanına koymaya çalıştım ama (sanırım) statik sınıf alanları ilk çağırdığınızda başlatıldı, bu yüzden güvenli bir çözüm değil ..
İbrahim Özdemir

22

Bunun gibi bir şey mi arıyorsunuz:

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

İşlem adını kontrol ederek de yapabilirsiniz:

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

4
OnPaint'te, türetilmiş sınıflarda, kurucularda vb. Çalışır Şimdiye kadarki en iyi çözüm.
Filip Kunc

14
IMHO, bu çirkin bir çözüm gibi görünüyor.
Camilo Martin

5
Burada olası bellek sızıntısına dikkat edin. İşlem atılmalıdır.
nalply

7
Bunun çoğu kullanım durumunda iyi çalışacağından emin olsam da, bu çözümün bir ana kusuru var: Visual Studio (en azından teoride) tek tasarımcı ana bilgisayarı değil. Bu nedenle, bu çözüm yalnızca tasarımcınız adlı bir uygulama tarafından barındırılıyorsa işe yarayacaktır devenv.
stakx -

2
Şu anda kabul edilen cevabın aksine VS2013'te çalışır.
Moby Disk

9

Bileşen ... bildiğim kadarıyla DesignMode özelliğine sahip değil. Bu özellik, Control tarafından sağlanır. Ancak sorun, CustomControl tasarımcıdaki bir Formda bulunduğunda, bu CustomControl'ün çalışma zamanı modunda çalışmasıdır.

DesignMode özelliğinin yalnızca Form'da doğru çalıştığını deneyimledim.


Bahşiş için teşekkürler! Bunu daha önce hiç fark etmemiştim ama çok mantıklı. Adrianbanks tarafından sağlanan LicenseManager yöntemini kullanmak, kontrolün başka bir kontrol / forma gömülü olduğu bu durumlarda mükemmel çalışır. Her biri için +1!
Josh Stribling

1
+1 Kesinlikle haklısın, bu benim de deneyimim oldu. Bir forma bir kullanıcı denetimi yerleştirdiğinizde, herhangi bir fare girişi veya yükleme olayları varsa, bu denetim için tasarım modunda olmadığınız için DesignMode yine de yanlış olarak görünecektir. Deneyimlerime göre görsel stüdyonun oldukça sert çökmesine neden oluyor.
Kyle B

8

Kontroller (Formlar, Kullanıcı Kontrolleri vb.) Aşağıdakilere Component classsahip olanı devralır bool property DesignMode:

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

4
Yapıcı çalıştığında ayarlanmayan, yani OP'nin ilk sorunu. Kullanabileceğiniz ilk an geldi OnHandleCreated.
Ray

8

ÖNEMLİ

Windows Forms veya WPF kullanmanın bir farkı var !!

Farklı tasarımcıları var ve farklı kontrollere ihtiyaçları var . Ek olarak, Formlar ve WPF denetimlerini karıştırdığınızda zordur. (örneğin, Formlar penceresinin içindeki WPF kontrolleri)

Yalnızca Windows Formlarınız varsa , şunu kullanın:

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

Yalnızca WPF'niz varsa , bu kontrolü kullanın:

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

Forms ve WPF'nin karışık kullanımına sahipseniz, aşağıdaki gibi bir onay kullanın:

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
}

Geçerli modu görmek için hata ayıklama için bir MessageBox gösterebilirsiniz:

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

Açıklama:

System.ComponentModel ve System.Diagnostics ad alanlarını eklemeniz gerekir .


Adınızın yanıltıcı olduğunu düşünüyorum. WinForms için kullanırken, adlandırma 'isInWpfDesignerMode' ve WPF için 'isInFormsDesignerMode'
M Stoerzel

5

Component.DesignMode özelliğini kullanmalısınız. Bildiğim kadarıyla, bu bir kurucu tarafından kullanılmamalıdır.


7
Bu, kontrolünüz tasarlanan başka bir kontrolün veya formun içindeyken çalışmaz.
Eric

1
Aslında bileşenlerimde oldukça iyi çalışıyor. if (!DesignMode)Tasarım zamanını spam etmediğinden emin olmak için her zaman OnPaint yöntemlerine eklemek zorunda kaldım.
Bitterblue

4

Bu blogda başka bir ilginç yöntem açıklanmıştır: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or -Kullanıcı modu/

Temel olarak, çalıştırılan derlemenin giriş derlemesinden statik olarak başvurulduğunu test eder. Derleme adlarını ('devenv.exe', 'monodevelop.exe' ..) izleme ihtiyacını ortadan kaldırır.

Ancak, derlemenin dinamik olarak yüklendiği diğer tüm senaryolarda çalışmaz (VSTO bir örnektir).


Bağlantı (etkili bir şekilde) kopmuştur. Artık bunun yerine en son blog gönderisine (şu anda 2016-03) yönlendiriyor.
Peter Mortensen

3

Tasarımcının işbirliği ile ... Kontrollerde, Komponentlerde, her yerde kullanılabilir.

    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(çizgiler kaldırılmalıdır. Sadece doğru çalıştığından emin olmamı sağlıyor.



1

Projemde kullandığım yöntem bu:

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

Dikkat !!!: Kod döndürdü bool belirten DEĞİL tasarım modunda!


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

Bu kod soruyu yanıtlayabilirken, sorunun nasıl ve / veya neden çözüldüğüne ilişkin ek içerik sağlamak, yanıtın uzun vadeli değerini artıracaktır.
Tiago Martins Peres 李大仁

0

LicenseManager çözümü OnPaint içinde çalışmaz, bu da çalışmaz. DesignMode. @ Jarek ile aynı çözüme başvurdum.

İşte önbelleğe alınmış sürüm:

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

        return isDesignMode.Value;
    }

Herhangi bir üçüncü taraf IDE kullanıyorsanız veya Microsoft (veya son kullanıcınız) VS yürütülebilir dosyasının adını 'devenv' dışında bir adla değiştirmeye karar verirse, bunun başarısız olacağını unutmayın. Başarısızlık oranı çok düşük olacaktır, bunun sonucu olarak başarısız olan kodda meydana gelebilecek herhangi bir hatayı hallettiğinizden emin olun ve sorun olmayacaktır.


0

Çalışırken bazı satırları çalıştırmak istiyor ancak Visual Studio tasarımcısında çalıştırmıyorsanız, DesignMode özelliğini aşağıdaki gibi uygulamalısınız:

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

Varsayılan olarak etkinleştirilen zamanlayıcılar, özel / kullanıcı kontrollerini kullanırken çökmeye neden olabilir. Bunları varsayılan olarak devre dışı bırakın ve yalnızca tasarım modu kontrolünden sonra etkinleştirin

   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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.