Visual Studio のデザイナーで Windows フォーム フォームを開くと、コードにいくつかのエラーがスローされます。フォームが実際に実行されている場合よりもデザイナーによって開かれている場合は、コードを分岐して別の初期化を実行したいと思います。
フォームを開くデザイナーの一部としてコードが実行されているかどうかを実行時に判断するにはどうすればよいですか?
Visual Studio のデザイナーで Windows フォーム フォームを開くと、コードにいくつかのエラーがスローされます。フォームが実際に実行されている場合よりもデザイナーによって開かれている場合は、コードを分岐して別の初期化を実行したいと思います。
フォームを開くデザイナーの一部としてコードが実行されているかどうかを実行時に判断するにはどうすればよいですか?
「デザイン モード」になっているかどうかを確認するには:
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
{
// Design time logic
}
Control.DesignMode プロパティは、おそらく探しているものです。コントロールの親がデザイナーで開いているかどうかがわかります。
ほとんどの場合、うまく機能しますが、期待どおりに機能しない場合があります。まず、コントロール コンストラクターでは機能しません。次に、「孫」コントロールの場合、DesignMode は false です。たとえば、UserControl が親でホストされている場合、UserControl でホストされているコントロールの DesignMode は false を返します。
かなり簡単な回避策があります。次のようになります。
public bool HostedDesignMode
{
get
{
Control parent = Parent;
while (parent!=null)
{
if(parent.DesignMode) return true;
parent = parent.Parent;
}
return DesignMode;
}
}
私はそのコードをテストしていませんが、動作するはずです。
最も信頼できるアプローチは次のとおりです。
public bool isInDesignMode
{
get
{
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
bool res = process.ProcessName == "devenv";
process.Dispose();
return res;
}
}
これを行う最も確実な方法は、DesignMode プロパティを無視し、アプリケーションの起動時に設定される独自のフラグを使用することです。
クラス:
public static class Foo
{
public static bool IsApplicationRunning { get; set; }
}
Program.cs:
[STAThread]
static void Main()
{
Foo.IsApplicationRunning = true;
// ... code goes here ...
}
次に、必要な場所でフラグを確認します。
if(Foo.IsApplicationRunning)
{
// Do runtime stuff
}
else
{
// Do design time stuff
}
デザイナが独自のプロセスを持つようになったため、devenv アプローチは VS2012 で機能しなくなりました。これが私が現在使用しているソリューションです(「devenv」の部分はレガシーのために残されていますが、VS2010がないとテストできません)。
private static readonly string[] _designerProcessNames = new[] { "xdesproc", "devenv" };
private static bool? _runningFromVisualStudioDesigner = null;
public static bool RunningFromVisualStudioDesigner
{
get
{
if (!_runningFromVisualStudioDesigner.HasValue)
{
using (System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess())
{
_runningFromVisualStudioDesigner = _designerProcessNames.Contains(currentProcess.ProcessName.ToLower().Trim());
}
}
return _runningFromVisualStudioDesigner.Value;
}
}
System.Diagnostics.Debugger.IsAttached
using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess())
{
bool inDesigner = process.ProcessName.ToLower().Trim() == "devenv";
return inDesigner;
}
上記のコード (using ステートメントを追加) を試してみましたが、失敗する場合がありました。起動時にデザイナーが読み込まれるフォームに直接配置されたユーザーコントロールのコンストラクターでのテスト。しかし、他の場所で動作します。
すべての場所で私にとってうまくいったのは次のとおりです。
private bool isDesignMode()
{
bool bProcCheck = false;
using (System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess())
{
bProcCheck = process.ProcessName.ToLower().Trim() == "devenv";
}
bool bModeCheck = (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime);
return bProcCheck || DesignMode || bModeCheck;
}
少しやり過ぎかもしれませんが、機能するので、私には十分です。
上記の例での成功は bModeCheck であるため、おそらく DesignMode は余剰です。
ハックっぽいですが、VB.NETを使用していて、Visual Studio 内から実行している場合、まだデプロイしていないため、My.Application.Deployment.CurrentDeploymentは Nothing になります。C# で同等の値を確認する方法がわかりません。
プロジェクトを実行すると、その名前に「.vshost」が追加されます。
だから、私はこれを使用します:
public bool IsInDesignMode
{
get
{
Process p = Process.GetCurrentProcess();
bool result = false;
if (p.ProcessName.ToLower().Trim().IndexOf("vshost") != -1)
result = true;
p.Dispose();
return result;
}
}
わたしにはできる。
デザイン時にまったく必要のないプロパティを作成した場合は、DesignerSerializationVisibility属性を使用して Hidden に設定できます。例えば:
protected virtual DataGridView GetGrid()
{
throw new NotImplementedException("frmBase.GetGrid()");
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int ColumnCount { get { return GetGrid().Columns.Count; } set { /*Some code*/ } }
NotImplementedException()
フォームに変更を加えて保存しようとするたびに、Visual Studio がクラッシュするのを止めました。代わりに、Visual Studio は、このプロパティをシリアル化する必要がないことを認識しているため、スキップできます。フォームのプロパティ ボックスに奇妙な文字列が表示されるだけですが、無視しても問題ないようです。
この変更は、再構築するまで有効にならないことに注意してください。
UserControls で次のコードを使用すると、機能します。他のメンバーが指摘したように、カスタム ユーザー コントロールを使用するアプリでは、DesignMode のみを使用しても機能しません。
public bool IsDesignerHosted
{
get { return IsControlDesignerHosted(this); }
}
public bool IsControlDesignerHosted(System.Windows.Forms.Control ctrl)
{
if (ctrl != null)
{
if (ctrl.Site != null)
{
if (ctrl.Site.DesignMode == true)
return true;
else
{
if (IsControlDesignerHosted(ctrl.Parent))
return true;
else
return false;
}
}
else
{
if (IsControlDesignerHosted(ctrl.Parent))
return true;
else
return false;
}
}
else
return false;
}
基本的に、上記のロジックは次のように要約されます。
public bool IsControlDesignerHosted(System.Windows.Forms.Control ctrl)
{
if (ctrl == null) return false;
if (ctrl.Site != null && ctrl.Site.DesignMode) return true;
return IsControlDesignerHosted(ctrl.Parent);
}
デバッグ モードでの実行が実際と見なされるかどうかはわかりませんが、簡単な方法はif
、コードに をチェックするステートメントを含めることですSystem.Diagnostics.Debugger.IsAttached
。
コントロールのプロパティを確認しDesignMode
ます。
if (!DesignMode)
{
//Do production runtime stuff
}
コンポーネントがまだ初期化されていないため、これはコンストラクターでは機能しないことに注意してください。
この問題を解決するには、次のようにコーディングすることもできます。
private bool IsUnderDevelopment
{
get
{
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
if (process.ProcessName.EndsWith(".vshost")) return true;
else return false;
}
}
少なくとも以前のバージョンの Visual Studio では、DesignMode プロパティにバグがあることがわかりました。したがって、次のロジックを使用して独自に作成しました。
Process.GetCurrentProcess().ProcessName.ToLower().Trim() == "devenv";
ハックのようなものですが、うまく機能します。
System.ComponentModel.Component.DesignMode == true
ここに別のものがあります:
//Caters only to thing done while only in design mode
if (App.Current.MainWindow == null){ // in design mode }
//Avoids design mode problems
if (App.Current.MainWindow != null) { //applicaiton is running }
フォームまたはコントロールにいる場合は、DesignMode プロパティを使用できます。
if (DesignMode)
{
DesignMode Only stuff
}
/// <summary>
/// Whether or not we are being run from the Visual Studio IDE
/// </summary>
public bool InIDE
{
get
{
return Process.GetCurrentProcess().ProcessName.ToLower().Trim().EndsWith("vshost");
}
}
これは、コンパイルする場所や、現在のモードを気にするかどうかに適応できる柔軟な方法です。
string testString1 = "\\bin\\";
//string testString = "\\bin\\Debug\\";
//string testString = "\\bin\\Release\\";
if (AppDomain.CurrentDomain.BaseDirectory.Contains(testString))
{
//Your code here
}