4

私が取り組んでいる一連のコントロールの一部には、明らかに、それらのいくつかをまとめてコンポジットにすることが含まれます。これには考慮が必要であることを急速に学び始めています(これは私にとってまったく新しいことです!):)

私は基本的にStyledWindowコントロールを持っています。これは本質的に、Panel他のビットを実行する能力を備えたものです(境界線の追加など)。

その中で子コントロールをインスタンス化するコードを次に示します。この時点まで、平凡な静的コントロールで正しく動作しているように見えます:

    protected override void CreateChildControls()
    {
        _panel = new Panel();

        if (_editable != null)
            _editable.InstantiateIn(_panel);

        _regions = new List<IAttributeAccessor>();
        _regions.Add(_panel);
    }

今日、より複雑なコントロールを入れ子にしようとしたときに問題が発生しました。このコントロールは、ページへの参照を使用します。これは、JavaScript を挿入して、もう少し機敏で反応が良いようにするためです (RegisterClientScriptBlockこれが、ページ参照が必要な唯一の理由です)。

現在、これは「オブジェクト null」エラーを引き起こしていましたが、これを render メソッドにローカライズしました。もちろん、[null]Pageオブジェクトに対してメソッドを呼び出そうとしていました。

私を混乱させているのは、コントロールがスタンドアロンとして正常に機能することですが、それを配置するStyledWindowとすべてがひどくうまくいかないことです!

StyledWindowそのため、またはのいずれかに何かが欠けているようですChildControl。何か案は?

アップデート

Brad Wilsonが正しく指摘したように、コントロールがコレクションに追加されていませんControls。これが_panel目的であり、これは私のためにそれを処理するためにあり、基本的にオーバーライドしますControls(これはどこかのガイドから取得しました):

    Panel _panel;    // Sub-Control to store the "Content".
    public override ControlCollection Controls
    {
        get
        {
            EnsureChildControls();
            return _panel.Controls;
        }
    }

それが物事を明確にするのに役立つことを願っています。申し訳ありません。

Longhorn213 の回答に続く更新

そうですね、コントロールをいじって、1 つをコンポジット内に、もう 1 つを外側に配置しました。次に、コントロール ライフサイクルのイベント メジャー イベントで Page のステータスを取得し、ページにレンダリングしました。

スタンドアロンは正常に動作しており、ページは期待どおりに初期化されています。ただし、コンポジットにネストされているものは異なります。OnLoadイベントはまったく発生していません!したがって、コントロール階層を正しく設定していないという点でブラッドはおそらく正しいと思います。不足しているものについて誰かアドバイスをいただけますか? Panel メソッドだけでは十分ではありませんか? (まあ、明らかにそうじゃない?!) :D

助けてくれてありがとう、ありがとう:)

4

4 に答える 4

2

Controls コレクションにコントロールをどこにも追加していません。これは、ページにアクセスできない理由を説明しています (公式にページに配置されていないため)。

于 2008-09-24T15:19:25.867 に答える
1

解決しました!

そうです、今日はこれをクラックすることにしました!これが私の考えでした:

  • の使用はPanelちょっとしたハックだと思ったので、それを削除して、実際にどのように行われるかを調べる必要があります。
  • MyCtl.Controls[0].Controlsコンポジットに追加されたコントロールにアクセスするようなことをしたくありませんでした。
  • いまいましいものが機能したかった!

だから、私は検索してMSDNを押しました、この記事は本当に役に立ちました(つまり、ほとんどコピー'n'貼り付けのように、よく説明されています-MSDNが伝統的に苦手なことです)。良い!

それで、私はその使用法をPanel取り除いて、ほとんどアークルを追い、それをゴスペルとしてとらえ、私が行くにつれてメモを取りました。

これが私が今持っているものです:

  • 間違った用語を使用していることを知りました。私はそれをテンプレートコントロールと呼ぶべきでした。テンプレート化されたコントロールは技術的には複合ですが、明確な違いがあります。テンプレート化されたコントロールは、それらに追加されるアイテムのインターフェイスを定義できます。
  • テンプレート化されたコントロールは非常に強力で、頭を回すとすぐにセットアップが簡単になります。
  • デザイナーのサポートでもう少し遊んで、すべてを完全に理解していることを確認してから、ブログ投稿を取得します:)
  • 「テンプレート」コントロールは、テンプレート化されたデータのインターフェースを指定するために使用されます。

たとえば、テンプレート化されたコントロールのASPXマークアップは次のとおりです。

<cc1:TemplatedControl ID="MyCtl" runat="server">
    <Template>
        <!-- Templated Content Goes Here -->
    </Template>
</cc1:TemplatedControl>   

これが私が今持っているコードです

public class DummyWebControl : WebControl
{
    // Acts as the surrogate for the templated controls.
    // This is essentially the "interface" for the templated data.
}

TemplateControl.csで...

    ITemplate _template;
    // Surrogate to hold the controls instantiated from 
    // within the template.
    DummyWebControl _owner;

    protected override void CreateChildControls()
    {
        // Note we are calling base.Controls here
        // (you will see why in a min).
        base.Controls.Clear();
        _owner = new DummyWebControl();

        // Load the Template Content
        ITemplate template = _template;
        if (template == null)
            template = new StyledWindowDefaultTemplate();
        template.InstantiateIn(_owner);

        base.Controls.Add(_owner);
        ChildControlsCreated = true;
    }

次に、[Surrogate]オブジェクトのコントロールに簡単にアクセスできるようにするには:

(これが、base.Controlsをクリア/追加する必要がある理由です)

    public override ControlCollection Controls
    {
        get
        {
            EnsureChildControls();
            return _owner.Controls;
        }
    }

そして、それはほとんどそれです、あなたが方法を知っているとき、それは簡単です!:)

次へ:デザインタイムリージョンのサポート!

于 2008-09-25T13:41:47.590 に答える
1

私はいつも JavaScript 呼び出しを OnLoad 関数に置いてきました。以下のような。

protected override void OnLoad(EventArgs e)
{

    // Do something to get the script
    string script = GetScript();

    this.Page.ClientScript.RegisterClientScriptBlock(this.Page.GetType(), "SomeJavaScriptName", script);

    // Could also use this function to determine if the script has been register. i.e. more than 1 of the controls exists
    this.Page.ClientScript.IsClientScriptBlockRegistered("SomeJavaScriptName");

    base.OnLoad(e);
}

それでもレンダリングを実行したい場合は、応答にスクリプトを記述できます。これは RegisterScriptBlock が行うことであり、スクリプトをページにインラインで配置するだけです。

于 2008-09-24T16:46:41.677 に答える
0

そうです、プレイしてみると、コントロールのインスタンス化に何か問題があることがわかりました。Longhorn が正しかったので、スクリプト参照OnLoadを私のControls階層はControls、コンポジットのコレクションに追加することで維持されました。

したがって、ここには2つのことがありました。

  1. 必要な実際のコントロールにアクセスする必要がないControlsため、コンポジットのプロパティ アクセサーをオーバーライドしてthisPanelの Controls コレクションを返しました。これを削除しましたが、これを整理する必要があります。ctl.Controls[0].Controls[0]
  2. をコレクションに追加していませんでしたが、Panelこれを行いました。Controls

それで、今はうまくいきますが、コンポジットのプロパティを取得して、それ自体ではなくのアイテムを返すにはどうすればよいですか?ControlsPanelPanel

于 2008-09-25T09:48:54.060 に答える