コントロールのコンストラクターからのデザインモードの検出


99

この質問に続き、オブジェクトのコンストラクター内からデザインモードかランタイムモードかを検出できますか?

これは不可能かもしれないし、私が望むものを変更しなければならないことに気づきましたが、今はこの特定の質問に興味があります。

回答:


191

名前空間でLicenceUsageMode列挙を使用できSystem.ComponentModelます。

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

2
エレガントなソリューションで、C#機能よりも優れていますISite.DesignMode
56ka 2014年

10
@Filip Kunc:これがOnPaintで機能しない場合は、コンストラクターでこの条件を確認し、クラスフィールドに格納できます。
IMil

3
これは、ユーザーコントロールでWndProcをオーバーライドする場合にも機能しません。@IMil提案を使用する必要があります
Matt

1
それを構築に入れるのはいい考えです。私にとってはうまくいきました。静的クラスフィールドに配置しようとしましたが、静的クラスフィールドを最初に呼び出したときに初期化されているため、安全な解決策ではありません。
イブラヒムオズデミール2017

22

あなたはこのようなものを探していますか?

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

プロセス名を確認することでも実行できます。

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

4
OnPaint、派生クラス、コンストラクターなどで動作します。最高のソリューションです。
フィリップクンク、2010

14
私見、これは醜い解決策のように見えます。
Camilo Martin

5
ここでメモリリークの可能性に注意してください。プロセスを破棄する必要があります。
nalply 2013年

7
これはほとんどのユースケースで正常に機能すると確信していますが、このソリューションには1つの主要な欠陥があります。VisualStudioは(少なくとも理論上は)唯一のデザイナーホストではありません。したがって、このソリューションは、デザイナーがというアプリケーションでホストされている場合にのみ機能しますdevenv
stakx-2013年

2
現在受け入れられている回答とは異なり、VS2013で動作します。
Moby Disk、

9

コンポーネント...私が知る限り、DesignModeプロパティはありません。このプロパティはControlによって提供されます。しかし、問題は、CustomControlがデザイナのフォームにある場合、このCustomControlがランタイムモードで実行されていることです。

DesignModeプロパティはFormでのみ正しく機能することを経験しました。


先端をありがとう!今まで気づかなかったが、それは完全に理にかなっている。adrianbanksが提供するLicenseManagerメソッドの使用は、コントロールが別のコントロール/フォームに埋め込まれているこれらの場合に完全に機能します。それぞれに+1!
Josh Stribling 2013年

1
+1あなたはまったく正しいです。これも私の経験です。ユーザーコントロールをフォームに配置するときに、mouseenterイベントまたはloadイベントがある場合、このコントロールのデザインモードではないため、DesignModeはfalseとして表示されます。私の経験では、ビジュアルスタジオがかなり激しくクラッシュします。
カイルB

8

コントロール(フォーム、ユーザーコントロールなど)は継承Component classしますbool property DesignMode

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

4
これは、コンストラクターの実行時に設定されません。別名、OPの最初の問題です。それを使用できる最初の瞬間はですOnHandleCreated
Ray

8

重要

Windows フォームまたはWPFの使用には違いがあります!!

彼らは異なるデザイナーがいて、異なるチェックが必要です。さらに、フォームコントロールとWPFコントロールを混在させる場合は注意が必要です。(例:フォームウィンドウ内のWPFコントロール)

Windows フォームのみの場合は、これを使用します。

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

WPFのみの場合は、次のチェックを使用します。

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

FormsとWPF を混合して使用している場合は、次のようなチェックを使用します。

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
}

現在のモードを確認するには、デバッグ用のメッセージボックスを表示します。

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

リマーク:

名前空間System.ComponentModelおよびSystem.Diagnosticsを追加する必要があります。


あなたの命名は誤解を招くと思います。WinFormsで使用する場合、命名は「isInWpfDesignerMode」であり、WPFは「isInFormsDesignerMode」です
M Stoerzel

5

Component.DesignModeプロパティを使用する必要があります。私の知る限り、これはコンストラクターから使用しないでください。


7
これは、コントロールがデザインされている別のコントロールまたはフォームの内部にある場合は機能しません。
エリック

1
実際、私のコンポーネントではかなりうまくいきます。if (!DesignMode)OnPaintメソッドを追加して、設計時のスパムにならないようにする必要がありました。
Bitterblue 2013

4

別の興味深い方法がそのブログで説明されています:http : //www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or -usermode /

基本的には、エントリアセンブリから静的に参照されている実行中のアセンブリをテストします。アセンブリ名( 'devenv.exe'、 'monodevelop.exe' ..)を追跡する必要性を回避します。

ただし、アセンブリが動的に読み込まれる他のすべてのシナリオでは機能しません(VSTOが1つの例です)。


リンクは(事実上)切断されています。代わりに、最新のブログ投稿(現在2016-03)にリダイレクトされるようになりました。
Peter Mortensen

3

設計者の協力を得て...コントロール、コンポーネント、あらゆる場所で使用できます

    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(行を削除する必要があります。それが正しく動作することを確認するだけです。



1

これは私のプロジェクトで使用した方法です。

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

注意!!!:ブール値が返されたコードは、デザインモードではないことを示しています!


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

このコードは質問に答えることがありますが、問題を解決する方法および/または理由に関する追加のコンテキストを提供すると、回答の長期的な価値が向上します。
Tiago Martins Peres李大仁

0

LicenseManagerソリューションはOnPaint内では機能せず、this.DesignModeでも機能しません。私は@Jarekと同じソリューションを使用しました。

キャッシュバージョンは次のとおりです。

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

        return isDesignMode.Value;
    }

サードパーティのIDEを使用している場合、またはMicrosoft(またはエンドユーザー)がVS実行可能ファイルの名前を「devenv」以外の名前に変更する場合は、これが失敗することに注意してください。失敗率は非常に低くなります。この結果として失敗するコードで発生する可能性のあるエラーに対処することを確認してください。問題はありません。


0

Visual Studioデザイナーではなく、実行中にいくつかの行を実行する場合は、次のようにDesignModeプロパティを実装する必要があります。

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

デフォルトで有効になっているタイマーは、カスタム/ユーザーコントロールの使用時にクラッシュを引き起こす可能性があります。既定では無効にして、デザインモードチェック後にのみ有効にする

   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;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.