デザイン時開発のトラブルシューティング
Windows フォームのコンポーネントおよびコントロールでカスタムのデザイン時操作を作成する際には、次のような一般的な問題が発生する場合があります。
コンパイルできない
デザイン時にデバッグできない
コンパイル エラー : "型または名前空間名 '型名' が見つかりませんでした。"
デザイン時エラー : "コンポーネント 'コンポーネント名' を生成できませんでした。"
デバッグ エラー : "有効ではないスレッド間の操作 : コントロールが作成されたスレッド以外のスレッドからコントロール 'コントロール名' がアクセスされました。"
デザイン時エラー : "ファイル内のクラスが視覚的にデザインできるクラスから継承されていないため、このファイル用にデザイナーを開くことはできません。"
コンポーネントの削除後にグリフが残る
既定のデザイナーの動作がカスタムの動作によって無効になった
デザイナーのイベントが予期しない方法で発生した
コレクションをシリアル化できない
デザイナーが UndoEngine 参照を取得できない
デザイン環境でコンポーネントのプロパティの変更が認識されない
コンポーネントまたはデザイナーの変更後のデザイン環境の更新
新しく生成された Windows フォームの FxCop 警告 : DoNotInitializeUnnecessarily
部分クラスおよび Windows フォーム デザイナー
レガシ カスタム コントロールが原因でデザイナーで予期しない動作が発生する
ホストされているデザイナーのスマート タグによって例外が発生する
コンポーネント アイコンがツールボックスに表示されない
コンパイルできない
デザイン時開発の重要な部分として、デザイン時アセンブリ System.Design.dll への参照を追加する必要があります。このアセンブリは、.NET Framework 4 Client Profile には含まれていません。System.Design.dll への参照を追加するには、プロジェクトのターゲット フレームワークを .NET Framework 4 に変更する必要があります。
デザイン時にデバッグできない
デザイン時のコードをデバッグするには、次の 2 つの方法があります。
MessageBox.Show 呼び出しをコード内の重要なポイントに配置します。
Visual Studio の別のインスタンスをアタッチして、最初のインスタンスのデザイン環境をデバッグします。
詳細については、「方法 : デザイン時サービスにアクセスする」を参照してください。
コンパイル エラー : "型または名前空間名 '型名' が見つかりませんでした。"
System.Design アセンブリを参照する必要があります。デザイナー関連の型は、System.Design アセンブリ内にあります。ここには、System.Windows.Forms.Design および System.ComponentModel.Design 名前空間内の型が含まれます。
また、Imports または using キーワードを使用して、必要な名前空間をインポートしてください。詳細については、「方法 : Windows フォームでデザイン時サポートにアクセスする」を参照してください。
デザイン時エラー : "コンポーネント 'コンポーネント名' を生成できませんでした。"
このエラーは、[ツールボックス] からデザイン サーフェイスにコンポーネントまたはコントロールを作成する際に表示されます。このエラーの考えられる 2 つの原因を次の表に示します。
原因 |
Description |
説明 |
---|---|---|
既定のコンストラクターがない |
コンポーネントまたはコントロールには、既定のコンストラクター (パラメーターのないコンストラクター) が必要です。 |
デザイン環境では、型のインスタンスを作成するためには既定のコンストラクターが必要です。 |
コンポーネントがジェネリック型 |
コンポーネントまたはコントロールをジェネリック型にすることはできません。この型は、テンプレート型またはパラメーター化された型とも呼ばれます。デザイン環境はジェネリック型をサポートしていません。 |
ジェネリック型が UserControl から派生している場合、それを Visual Studio の [ユーザー コントロール テスト コンテナー] で実行しようとすると、次のエラーが発生します。 UserControl 'name' を作成できませんでした。 エラー メッセージ: 'Type.ContainsGenericParameters が true に設定されている型を作成できません。' UserControl はリストから削除されます。 コンポーネントおよびコントロールがジェネリック型であることはできませんが、それらがジェネリック型を使用することはできます。 |
デザイン時エラー : "値を null にすることはできません。パラメーター名 : 'コンポーネント名'"
このエラーは、[ツールボックス] からデザイン サーフェイスにコンポーネントまたはコントロールを作成する際に表示されます。最も一般的な原因は、64 ビットのアセンブリに構築されたコンポーネントまたはコントロールを使用しようとしていることです。Visual Studio のデザイン環境では、64 ビットのコンポーネントはサポートされていません。
デバッグ エラー : "有効ではないスレッド間の操作 : コントロールが作成されたスレッド以外のスレッドからコントロール 'コントロール名' がアクセスされました。"
in your Windows フォーム アプリケーションでマルチスレッドを使用する場合は、スレッド セーフな方法でコントロールを呼び出すように注意する必要があります。この例外はデバッガーによって発生し、実行時には表示されませんが、この問題が発生した場合には修正することを強くお勧めします。詳細については、「方法 : Windows フォーム コントロールのスレッド セーフな呼び出しを行う」を参照してください。
デザイン時エラー : "ファイル内のクラスが視覚的にデザインできるクラスから継承されていないため、このファイル用にデザイナーを開くことはできません。"
コンポーネントまたはコントロールが含まれているファイルには、複数のクラスの定義を含めることができますが、ファイル内の先頭のクラスはデザイン可能なものである必要があります。ファイル内の先頭のクラスは、IComponent インターフェイスを実装する必要があります。または、Component クラスから派生するか、Component から派生したクラスから派生する必要があります。
コンポーネントの削除後にグリフが残る
カスタム デザイナーが Adorner オブジェクトを作成した場合は、デザイナーがスコープの外になったときに、デザイン サーフェイスからそれらを削除する必要があります。デザイナーの Dispose メソッドで BehaviorServiceAdornerCollection.Remove を呼び出して、Glyph オブジェクトと、関連する Adorner および Behavior オブジェクトを消去します。詳細については、「方法 : デザイン モードでコントロールの外観と動作を拡張する」を参照してください。
既定のデザイナーの動作がカスタムの動作によって無効になった
既定のコントロール デザイナーによって作成されるグリフは、デザイン サーフェイス上のコントロール全体を対象にします。これは本体グリフと呼ばれます。本体グリフと同じ境界を持つグリフをカスタム コントロール デザイナーが作成する場合、本体グリフに関連付けられている基になる Behavior 実装は非表示になります。これにより、スマート タグやグリフのサイズ変更などの既定の機能が表示されるのを防ぐことができます。
Behavior オブジェクト間でメッセージを渡すことはできません。そのため、マウス メッセージを処理して、それを基になる Behavior オブジェクトに転送することはできません。コントロール全体を対象にしたグリフを実装する場合は、カスタム デザインの外観および動作全体に注意する必要があります。
デザイナーのイベントが予期しない方法で発生した
カスタム デザイナーが ComponentRemoved、ActiveDesignerChanged、および SelectionChanged などのデザイナー イベントにイベント ハンドラーをアタッチする場合は、デザイナーの Dispose メソッド内のイベント ハンドラーをデタッチする必要があります。
これを実行しないと、デザイン時に予期しない動作が発生する可能性があります。発生する可能性のある症状を次の一覧に示します。
エラー メッセージ ボックス : "このコマンドの処理中にエラーが発生しました。"
エラー メッセージ ボックス : "オブジェクト参照がオブジェクト インスタンスに設定されていません。"
コンポーネントが削除されたり、デザイナーが閉じられると、イベント ハンドラーが不正に呼び出されます。
コレクションをシリアル化できない
カスタム コンポーネントまたはコントロールのコレクション プロパティをシリアル化する場合は、DesignerSerializationVisibilityAttribute を適用し、Content に設定します。詳細については、「方法 : 標準の型のコレクションを DesignerSerializationVisibilityAttribute でシリアル化する」を参照してください。
デザイナーが UndoEngine 参照を取得できない
フォームの読み込み中に UndoEngine サービスへの参照を取得しようとすると、GetService メソッドは null を返します。
UndoEngine サービスは、フォームの読み込みが完了するまでは作成および有効化されません。フォームの読み込みが完了すると、それ以降の GetService の呼び出しで UndoEngine 参照が返されます。
通常は、UndoEngine を直接参照する必要が生じることはほとんどありません。直接参照する必要があるのは、通常、ユーザーが操作を行った場合か、デザイナーの読み込み後です。
デザイン環境でコンポーネントのプロパティの変更が認識されない
直接プロパティを設定した場合、デザイン環境はコンポーネントまたはコントロールに加えられた変更を認識しません。ComponentChanged などのイベントが発生するためには、PropertyDescriptor.SetValue メソッドを使用してコンポーネントのプロパティの値を設定する必要があります。これにより、デザイン環境にプロパティの変更が通知され、デザイン サーフェイスおよび PropertyGrid コントロールを正しく更新できます。詳細については、「方法 : デザイン モードでコントロールの外観と動作を拡張する」を参照してください。
DesignerAttribute 構文
カスタム デザイナーをデザイン元のコントロールにアタッチするには、DesignerAttribute をコントロールに適用します。
DesignerAttribute パラメーターを正確に指定する必要があります。指定しない場合、デザイン環境はカスタム デザイナーを読み込みません。
コンポーネントまたはデザイナーの変更後のデザイン環境の更新
コンポーネントのデザイン時の側面に変更を加える場合は、コンポーネントのプロジェクトをビルドし直す必要があります。加えて、このコンポーネントを使用している別の Windows フォーム プロジェクトが現在開かれている場合は、多くの場合、変更内容を表示するのにプロジェクトを更新する必要があります。通常は、コンポーネントが含まれているデザイン ウィンドウをいったん閉じてから開き直す必要があります。
新しく生成された Windows フォームの FxCop 警告 : DoNotInitializeUnnecessarily
Windows フォーム デザイナーは、Windows フォーム アプリケーション プロジェクト用に C# で次のコードを生成します。
private System.ComponentModel.IContainer components = null;
有効な FxCop ルールに基づいて、FxCop は "DoNotInitializeUnnecessarily" 警告を生成します。これは、参照プロパティに関して null が共通言語ランタイム (CLR) の既定であるためです。
デザイナーが components フィールドを初期化して null にしない場合、C# コンパイラは次の警告を生成します。
"'Form1.components' は割り当てられません。常に既定値 'null' を使用します。"
SuppressMessageAttribute を使用すると、FxCop 警告が表示されないようにできます。ただし、それにより、クラス名が変更されたときにメンテナンス上の問題が発生する可能性があります。したがって、FxCop 警告を無視することをお勧めします。
部分クラスおよび Windows フォーム デザイナー
既定では、Windows フォーム デザイナーは、デザイナーのシリアル化コードをコンポーネントのメイン ファイルとは別の専用のファイルに保存します。たとえば、Windows フォーム アプリケーション プロジェクトで、Form1 クラスの定義は次の表に示すように 2 つのファイルに分割されます。
ファイル (C# のファイル名) |
Function |
---|---|
Form1.cs |
メイン クラス ファイル |
Form1.Designer.cs |
デザイナーが出力するコード |
ファイル (VB のファイル名) |
Function |
---|---|
Form1.vb |
メイン クラス ファイル |
Form1.Designer.vb |
デザイナーが出力するコード |
一般に、Windows フォーム デザイナーが生成するコードを変更する必要はありません。代わりにメイン クラスのファイルを編集します。
Windows フォーム デザイナーは、partial キーワードを使用して、Form1 の実装を 2 つのファイルに分割します。これにより、デザイナーが出力したコードがコードに混入することを防ぐことができます。partial キーワードの詳細については、「部分クラスと部分メソッド (C# プログラミング ガイド)」および「Partial (Visual Basic)」を参照してください。
Windows フォーム デザイナーでは、デザイン可能な型の定義を 2 つ以上の partial 実装に分割することはサポートされていません。この制限には、型の 3 番目の部分定義を含むクラス ファイルの新規作成や、メイン ファイルまたはデザイナー ファイルに対する型の 3 番目の部分クラスの定義の追加が含まれます。この方法で定義されたメンバーは、Windows フォーム デザイナーでは表示されません。
レガシ カスタム コントロールが原因でデザイナーで予期しない動作が発生する
デザイナーで型が無効化されると、ComponentSerializationService が一部の再読み込みを実行して、更新された型でデザイナーを更新します。Visual Studio 2005 より前のバージョンの Visual Studio では、デザイナーが完全に再読み込みされていました。Visual Studio 2005 での一部の再読み込み動作は完全な再読み込みよりも処理時間が短く、"元に戻す" スタックも保持されます。
Visual Studio 2005 より前に作成されたコンポーネントおよび対応するシリアライザーは、一部の再読み込みに対応できない場合があります。完全な再読み込みの実行中にのみ逆シリアル化するように作成されたコンポーネントとコントロールが原因で、予期しない動作が発生する可能性があります。レガシ コントロールが存在する場合に Windows フォーム デザイナーで見られる兆候には、スタック オーバーフロー、ハング、または空白領域があります。
devenv.exe.config ファイルに次の設定を追加すると、完全な再読み込み動作に戻すことができます。Visual Studio 2005 を既定の場所にインストールした場合、このファイルは C:\Program Files\Microsoft Visual Studio 8\Common7\IDE フォルダーにあります。
<appSettings>
<add key="EnableOptimizedDesignerReloading" value="false" />
</appSettings>
ホストされているデザイナーのスマート タグによって例外が発生する
Visual Studio の外部でデザイナーをホストしている場合は、スマート タグによって NullReferenceException が発生することがあります。この問題を解消するには、デザイナーに IUIService 参照を追加し、Styles プロパティを実装します。Styles によって公開される IDictionary で、次のコードに示すように新しい Font を "DialogFont" キーで指定される要素として割り当てます。
Styles["DialogFont"] = new Font(...);
コンポーネント アイコンがツールボックスに表示されない
Visual Studio で、ToolboxBitmapAttribute を使用してアイコンをカスタム コンポーネントに関連付けても、自動的に生成されたコンポーネントのビットマップがツールボックスに表示されません。ビットマップを表示するには、[ツールボックス アイテムの選択] ダイアログ ボックスを使用してコントロールを再読み込みします。詳細については、「ツールボックス アイコン」を参照してください。