3

UserControl次のような階層があります。

public class BaseClass : UserControl
{
    protected Label[] Labels;
    public BaseClass(int num)
    {
        Labels = new Label[num];
        for(int i=0; i<num; i++)
        {
            Labels[i] = new Label();
        }
    }
}

そして別のファイルで:

public class DerivedClass : BaseClass
{
    public DerivedClass() : base(2)
    {
        // Do stuff to the location, size, font, text of Labels
    }
}

この構造は、BaseClass がコア ロジックを処理し、DerivedClass が表示ロジックを処理するように設計されています。ラベルの数は可変である必要があります (DerivedClasses が異なれば num 値も異なります)。

私の問題は、表示調整のに表示されるように、デザイナー ビューに UserControl を表示することです。いくつかの問題があります。まず、BaseClass に既定のコンストラクターがない場合、DerivedClass のデザイナー ビューが単に失敗します。デフォルトのコンストラクターを追加しても、デザイナー ビューには、さまざまな表示変更なしで DerivedClass のレイアウトが表示されます。

デザイナー ビューを使用してコントロールを変更することに興味はありません。反対ではありませんが、ラベルが配列にあるという事実は、デザイナー ビューがラベルにアクセスできないように思われます。DerivedClass でディスプレイ レイアウト コードの効果を確認できることに単純に興味があります。

4

2 に答える 2

3

Windowsフォームデザイナには、現在設計されているクラス自体のコンストラクターを実行できないという制限があるようです。親クラスのコンストラクターのみが起動されます。

私があなたの例を取るならば:

public partial class BaseControl : UserControl
{
    public BaseControl()
    {
        InitializeComponent();
    }


    protected Label[] Labels;

    public BaseControl(int num) : base()
    { 
        Labels = new Label[num]; 
        for(int i=0; i<num; i++) 
        { 
            Labels[i] = new Label(); 
        } 
    }

}

public class DerivedControl : BaseControl
{

    public DerivedControl() : base(5)
    {
        Controls.Add(Labels[0]);

        Labels[0].Text = "Hello";
        Labels[0].Location = new System.Drawing.Point(10, 10);

    }

}

次に、Derived Controlのデザイナーを見ると、何も表示されません。ただし、DerivedControlから派生した次のコントロールを追加すると、次のようになります。

public class GrandchildControl : DerivedControl
{

    public GrandchildControl() : base() { }

}

そして、私のプロジェクトを構築した後、デザイナー(Visual Studio 2010)でそれを見てください。

GrandchildControlは、期待どおりにDerivedControlコンストラクターを呼び出します

それはデザイナーの特徴のようです。MSDNブログ(かなり古い)のこのブログ投稿によると

  1. Form1は、視覚的に継承する別のフォーム、たとえばForm2を追加する前にビルドする必要があります。これは、Form2のデザイナがSystem.Windows.Forms.FormではなくForm1をインスタンス化する必要があるためです。これは、デザイナーでForm2を開き、デバッガーをVisual Studioに接続し、Form1のInitializeComponentにブレークポイントを設定すると、ブレークポイントがヒットする理由も説明しています。

  2. InitializeComponentの上に、手動で変更しないように警告するコメントがあります。これは、設計者がこのコードを解析する必要があり、解析できる内容に関していくつかの制限があるためです。通常、そこでシリアル化されたものはすべて解析することが保証されていますが、追加する可能性のある任意のコードは解析できません。

  3. コンストラクターまたはLoadイベントハンドラーでフォームにコントロールを手動で(コードを介して)追加している場合、コントロールはデザイナーに表示されません。これは、デザイナがそれを解析しないためです。InitializeComponentのみを解析します。

これを確実に機能させる唯一の方法は、すべてのコードをInitializeComponentによって呼び出されるメソッドに移動することです(デザイナーによって「上書き」されたときに、コードを元に戻すことを忘れないでください)。または、上記で行ったように実行し、GrandchildUserControlを作成して、関心のある実際のコントロールのコンストラクター呼び出しを偽造します。

FWIWこれは1)と3)の結果であり、ほぼ確実に設計による回避策であると思います。

ポイント1)は、これらの状況に対する優れた調査手法も提供します。実際にVisual Studioの別のインスタンスを起動し、Visual Studioの最初のインスタンスに接続して、そこで実行されているメソッド呼び出しをデバッグできます。これは、過去にいくつかのデザイナーの問題をトラブルシューティングするのに役立ちました。

于 2012-05-08T16:07:01.357 に答える