91

コントロールを開発するときに、DesignMode の問題に対する有用な解決策を見つけた人はいますか?

問題は、コントロールをネストすると、DesignMode が最初のレベルでのみ機能することです。2 番目以降のレベルの DesignMode は、常に FALSE を返します。

標準的なハックは、実行中のプロセスの名前を調べることでした。それが「DevEnv.EXE」である場合、それはスタジオである必要があるため、DesignMode は本当に TRUE です。

ProcessName を探しているという問題は、レジストリやその他の奇妙な部分を介して回避され、ユーザーがプロセス名を表示するために必要な権限を持っていない可能性があります。さらに、この奇妙なルートは非常に遅いです。そのため、シングルトンを使用するために追加のハックを積み重ねる必要があり、プロセス名を尋ねるときにエラーがスローされた場合は、DesignMode が FALSE であると想定します。

DesignMode を決定するためのきれいな方法が整っています。Microsoftにフレームワークの内部で修正してもらうと、さらに良いでしょう!

4

13 に答える 13

84

この質問を再検討すると、これを行う 5 つの異なる方法が「発見」されました。

System.ComponentModel.DesignMode property

System.ComponentModel.LicenseManager.UsageMode property

private string ServiceString()
{
    if (GetService(typeof(System.ComponentModel.Design.IDesignerHost)) != null) 
        return "Present";
    else
        return "Not present";
}

public bool IsDesignerHosted
{
    get
    {
        Control ctrl = this;

        while(ctrl != null)
        {
            if((ctrl.Site != null) && ctrl.Site.DesignMode)
                return true;
            ctrl = ctrl.Parent;
        }
        return false;
    }
}
public static bool IsInDesignMode()
{
    return System.Reflection.Assembly.GetExecutingAssembly()
         .Location.Contains("VisualStudio"))
}

提案された 3 つのソリューションを試してみるために、3 つのプロジェクトで小さなテスト ソリューションを作成しました。

  • TestApp (winforms アプリケーション)、
  • サブコントロール (dll)
  • サブサブコントロール (dll)

次に、SubSubControl を SubControl に埋め込み、それぞれを TestApp.Form に埋め込みました。

このスクリーンショットは、実行時の結果を示しています。 実行中のスクリーンショット

このスクリーンショットは、Visual Studio でフォームを開いた結果を示しています。

実行されていないスクリーンショット

結論:リフレクションなしでは、コンストラクターで信頼できるのは LicenseUsage だけであり、コンストラクターの外部で信頼できるのは「IsDesignedHosted」だけです (以下のBlueRajaによる)。

PS: 以下のToolmakerSteveのコメントを参照してください (私はテストしていません):結果をキャッシュします。」

于 2009-04-02T07:02:22.477 に答える
36

このページから:

[2013年編集] @hoplaが提供するメソッドを使用して、コンストラクターで機能するように編集)

/// <summary>
/// The DesignMode property does not correctly tell you if
/// you are in design mode.  IsDesignerHosted is a corrected
/// version of that property.
/// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305
/// and http://stackoverflow.com/a/2693338/238419 )
/// </summary>
public bool IsDesignerHosted
{
    get
    {
        if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
            return true;

        Control ctrl = this;
        while (ctrl != null)
        {
            if ((ctrl.Site != null) && ctrl.Site.DesignMode)
                return true;
            ctrl = ctrl.Parent;
        }
        return false;
    }
}

マイクロソフトにバグレポートを提出しました。どこにでも行くとは思えませんが、これは明らかにバグであるため( 「設計による」かどうかにかかわらず)、とにかく投票してください。

于 2010-04-22T18:19:19.783 に答える
29

LicenseManager.UsageMode を確認してみてください。このプロパティは、値 LicenseUsageMode.Runtime または LicenseUsageMode.Designtime を持つことができます。

コードを実行時にのみ実行する場合は、次のコードを使用します。

if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
{
  bla bla bla...
}
于 2008-12-06T21:29:10.010 に答える
7

これは、フォーム内で使用する方法です。

    /// <summary>
    /// Gets a value indicating whether this instance is in design mode.
    /// </summary>
    /// <value>
    ///     <c>true</c> if this instance is in design mode; otherwise, <c>false</c>.
    /// </value>
    protected bool IsDesignMode
    {
        get { return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; }
    }

これにより、DesignMode または LicenseManager プロパティのいずれかが失敗した場合でも、結果は正しくなります。

于 2010-09-29T14:46:37.217 に答える
6

LicenseManager メソッドを使用しますが、コンストラクターからの値をキャッシュして、インスタンスの存続期間全体で使用できるようにします。

public MyUserControl()
{
    InitializeComponent();
    m_IsInDesignMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
}

private bool m_IsInDesignMode = true;
public bool IsInDesignMode { get { return m_IsInDesignMode; } }

VB バージョン:

Sub New()
    InitializeComponent()

    m_IsInDesignMode = (LicenseManager.UsageMode = LicenseUsageMode.Designtime)
End Sub

Private ReadOnly m_IsInDesignMode As Boolean = True
Public ReadOnly Property IsInDesignMode As Boolean
    Get
        Return m_IsInDesignMode
    End Get
End Property
于 2010-05-17T13:08:10.143 に答える
3

私の提案は @blueraja-danny-pflughoeft replyの最適化です。このソリューションは毎回結果を計算するのではなく、初回のみ計算します (オブジェクトは UsageMode をデザインからランタイムに変更できません)。

private bool? m_IsDesignerHosted = null; //contains information about design mode state
/// <summary>
/// The DesignMode property does not correctly tell you if
/// you are in design mode.  IsDesignerHosted is a corrected
/// version of that property.
/// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305
/// and https://stackoverflow.com/a/2693338/238419 )
/// </summary>
[Browsable(false)]
public bool IsDesignerHosted
{
    get
    {
        if (m_IsDesignerHosted.HasValue)
            return m_IsDesignerHosted.Value;
        else
        {
            if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
            {
                m_IsDesignerHosted = true;
                return true;
            }
            Control ctrl = this;
            while (ctrl != null)
            {
                if ((ctrl.Site != null) && ctrl.Site.DesignMode)
                {
                    m_IsDesignerHosted = true;
                    return true;
                }
                ctrl = ctrl.Parent;
            }
            m_IsDesignerHosted = false;
            return false;
        }
    }
}
于 2016-01-27T15:37:12.203 に答える
3

このコードを使用して成功します。

public static bool IsRealDesignerMode(this Control c)
{
  if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
    return true;
  else
  {
    Control ctrl = c;

    while (ctrl != null)
    {
      if (ctrl.Site != null && ctrl.Site.DesignMode)
        return true;
      ctrl = ctrl.Parent;
    }

    return System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv";
  }
}
于 2012-09-21T07:56:55.067 に答える
3

信頼できるメソッド (DesignMode、LicenseManager) または効率的なメソッド (プロセス、再帰チェック) がないためpublic static bool Runtime { get; private set }、プログラム レベルで を使用し、Main() メソッド内で明示的に設定しています。

于 2011-09-02T09:58:23.550 に答える
2

私はこれに引っかかったことがありませんが、コントロールから親チェーンに戻って、DesignMode があなたの上に設定されているかどうかを確認することはできませんか?

于 2008-08-29T16:47:03.593 に答える
1

Parent.DesignModeを呼び出せないことに気づいていませんでした(C#でも「保護」について何かを学びました...)

これがリフレクティブバージョンです:(designModePropertyを静的フィールドにすることでパフォーマンス上の利点があると思います)

static bool IsDesignMode(Control control)
{
    PropertyInfo designModeProperty = typeof(Component).
      GetProperty("DesignMode", BindingFlags.Instance | BindingFlags.NonPublic);

    while (designModeProperty != null && control != null)
    {
        if((bool)designModeProperty.GetValue(control, null))
        {
            return true;
        }
        control = control.Parent;
    }
    return false;
}
于 2008-08-29T17:43:57.027 に答える
1

DesignMode はプライベート プロパティです (私が知る限り)。答えは、DesignMode プロパティを公開するパブリック プロパティを提供することです。次に、非ユーザー コントロールまたはデザイン モードのコントロールに遭遇するまで、ユーザー コントロールのチェーンをカスケード バックアップできます。このようなもの....

  public bool RealDesignMode()
  {
     if (Parent is MyBaseUserControl)
     {
        return (DesignMode ? true : (MyBaseUserControl) Parent.RealDesignMode;
     }

     return DesignMode;
  }

すべての UserControls が MyBaseUserControl から継承する場所。あるいは、「RealDeisgnMode」を公開するインターフェースを実装することもできます。

このコードはライブ コードではないことに注意してください。:)

于 2008-08-29T16:59:22.063 に答える