10

スレッドを開始し、ファイルを開き、他のクラスからの入力を待機するオブジェクトがあります。入力を受け取ると、それをディスクに書き込みます。基本的に、これはスレッドセーフなデータ ロギング クラスです...

ここが奇妙な部分です。オブジェクトを使用するデザイナー (Visual Studio 2008) でフォームを開くと、ファイルが作成されます。明らかに設計時の vhost プロセスで実行されています...

奇妙なことに、別のプロジェクトで問題を再現できませんでした。デザイナーで実行されるコードと実行されないコードのルールが何であるかはわかりません。たとえば、Windows フォーム コンストラクターでファイルを作成しても、実際には設計時にファイルが作成されません。

説明は何ですか?参照はありますか?

4

5 に答える 5

13

コントロールまたはフォームのコンストラクターは、デザイナーでそのクラスを編集するときに実行されません (また、OnLoad も呼び出されません)。私はときどきこれを使用して、デザイナーで 1 つの値を設定しました (たとえば、その子コントロールをデザイナーですべて表示可能にする) が、コンストラクターでそれらのいくつかを別の既定値にオーバーライドします (たとえば、表示のみを行う特定の子コントロールを非表示にします)。ステータス バーのインジケーターなど、特定の状況で)。

ただし、コントロールがデザイナーの別のコントロールまたはフォームの子として配置されている場合、コンストラクターは実行されます。OnLoad も実行されます。これは、ロギング コードがデザイナーで誤ってトリガーされた方法である可能性があります。

デザインとランタイムを検出するために、別の質問への回答には、いくつかの一般的なアプローチによって返される値を示すいくつかの経験的テストのスクリーンショットがあります。デザイナーで編集されているフォームまたはコントロールの子コントロール (2 レベル下) の子コントロールは、独自の DesignMode == false を参照しているように見えるため、通常のプロパティ チェックではコードを保護できません (たとえば、OnLoad メソッド内)。 ) デザイナーで追加されたコントロール内にネストされたコントロールの場合。予想どおりに DesignMode をチェックしていた場合、そのチェックを回避する原因となったのはネストである可能性があります。また、コンストラクター内では常に DesignMode == false と見なされます。

また、LicenseManager.UsageMode チェックでは、コンストラクター内の DesignTimeのみが確認されることに注意してください。OnLoad が呼び出されると、RunTime LicenseContext 内にあります。最も完全な解決策は、コントロールまたはフォーム (またはコンポーネント) のコンストラクターで LicenseManager.UsageMode をチェックし、設定をメンバー変数またはプロパティに保存して、デザイナーで実行してはならないコードの実行を回避することです。ネストされている場合でも。ネストを説明するが、コンストラクターの外部でのみ機能する他の質問に対する別の回答には、別のアプローチもあります。

于 2011-02-18T21:41:29.463 に答える
11

LicenseManager の UsageMode をチェックして、コードが設計時かどうかを確認できます。

System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime

簡単な例を次に示します。

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace Test
{
    public class ComponentClass : Component
    {
        public ComponentClass()
        {
            MessageBox.Show("Runtime!");
        }
    }
}

このコンポーネントがデザイナーのフォームに追加されると、すぐにメッセージ ボックスが表示されます。

これを防ぐには、単純な if ステートメントを追加して、コードが設計時にないかどうかを確認します。

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace Test
{
    public class ComponentClass : Component
    {
        public ComponentClass()
        {
            if (LicenseManager.UsageMode != LicenseUsageMode.Designtime)
            {
                MessageBox.Show("Runtime!");
            }
        }
    }
}

if ステートメントを追加した後、コンポーネントがデザイナー経由でフォームに追加されたときに、メッセージ ボックスが表示されなくなりました。

于 2008-11-11T21:57:12.713 に答える
2

まあ、これはとにかく復活したので、デザインモードかどうかを判断するために使用する関数は次のとおりです。

public static bool IsAnyInDesignMode(Control control){
    while(control != null){
        if(control.Site != null && control.Site.DesignMode)
            return true;
        control = control.Parent;
    }
    return false;
}

これは、コントロールが別のコントロールによって作成された子である場合を処理します。このDesignModeプロパティは、デザイナー自体によって作成されたコントロールに対してのみ設定されます。

于 2011-02-19T04:06:24.647 に答える
2

これを使用して、Visual Studio Designer がコードを実行しているかどうかを確認することもできます。

public static bool DesignMode
{
    get {  return (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv"); }
}

次に Form_Load で:

if (!DesignMode)
{
    // Run code that breaks in Visual Studio Designer (like trying to get a DB connection)
}

ただし、これは を使用するよりも洗練されていませんLicensManager.UsageModeが、機能します (Microsoft が Visual Studio を実行するプロセスの名前を変更するまで)。

于 2009-06-16T08:20:58.113 に答える
0

デザイナーと一緒にやってはいけないことがいくつかあります。確固たる証拠はありませんが、Windows フォーム デザイナーは、既定のコンストラクターを削除することを嫌うことがわかりました。先に進んで新しいオーバーロードを作成しますが、空のコンストラクターはそのままにしておきます。

またForm_Load、継承元の基本クラスでイベントを実行しないようにしてください。

于 2008-11-11T20:24:16.397 に答える