2011-10-05 6 views
5

ネストされた階層を表すクラス(MyClass)があるため、クラスにはMyClassのコレクションであるプロパティがあります。 MyClassにもタイトルプロパティがありますユーザーコントロールをリピータに動的に追加する

Webページに表示するには、リピーターを持つユーザーコントロールを作成したいと考えていました。アイテムテンプレートでは、タイトルプロパティを表示するリテラルがあり、リピーターのItemCreatedイベントには、私はusercontrolの新しいインスタンスを作成し、それをリピーターの現在のアイテムに追加します。

私の問題は、UserControlのPage_Loadイベントが発生したときに、コントロールが動的に追加された場合、EnsureChildControlsを呼び出してもrepMyClassリピータporopertyがnullになります。私はここに何かを逃していますか私がリピータを作成し、私のuserctonrolをアイテムテンプレートにドロップするとうまく動作します。私はこれを動的に動かすことができないのですか?

ユーザーコントロール:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.ascx.cs" Inherits="MyControl" %> 
Items:<br/> 
<asp:Repeater ID="repMyClass" runat="server" EnableViewState="false" 
    OnItemCreated="repMenuItems_ItemCreated"> 
    <HeaderTemplate><ul><HeaderTemplate> 
    <ItemTemplate> 
     <li><%# Eval("Title") %> 
      <div><asp:PlaceHolder ID="SubItemPlaceholder" runat="server" /></div> 
     </li></ItemTemplate> 
    <FooterTemplate></ul></FooterTemplate> 
</asp:Repeater> 

ユーザーコントロールコード:あなたがしたいとロードイベントでそれを使用するプロパティを取るコントロール内の別のコンストラクタを行い、その後、渡すことができ

public partial class MyControl: System.Web.UI.UserControl 
{ 
    public IEnumerable<MyClass> ChildItems { get; set; } 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     this.repMyClass.DataSource = ChildItems; 
     this.repMyClass.DataBind(); 
    } 

    protected void repMenuItems_ItemCreated(object Sender, RepeaterItemEventArgs e) 
    { 
     if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item) 
     { 
      //Get the MyClass instance for this repeater item 
      MyClass mcCurrent = (MyClass)e.Item.DataItem; 

      //If the MyClass instance has child instances 
      if (mcCurrent.Children != null && mcCurrent.Children.Length > 0) 
      { 
       //Add a new user control and set it's property so it can bind 
       PlaceHolder ph = (PlaceHolder)e.Item.FindControl("SubItemPlaceholder"); 

       MyControl ctl = (MyControl)Page.LoadControl(typeof(MyControl),new object[] {}); 

       ctl.ChildItems = mcCurrent.Children; 
       ph.Controls.Add(ctl); 
      } 
     } 
    } 
} 
+0

これを説明するために編集できますか、これをクリーンアップすることはできますか?私は、この文章の半分の編集が完了していないかもしれないと思いますか? "私の問題は、動的に追加されたコントロールのPage_Loadイベントが最初に発生したときに、repNyClassリピータのporopertyがヌルです" – chrismay

答えて

0

それはLoadControl()呼び出しで現在空のオブジェクト配列にあります。

もう1つの方法は、本質的に実際の負荷であり、コントロールごとに要求ごとに1回発生するので、コントロールのLoadイベントではなくプロパティのセッターでロジックを発生させることです。

もう1つの方法は、すべてを動的にロードすることではありません。

あなたの項目テンプレートの内側にあなたのような何かを持つことができます。

<uc:MyControl runat="server 
    ChildItems='<%# ((MyClass) Container.DataItem).Children %>' 
    Visible='<%# ((MyClass) Container.DataItem).Children.Length > 0 %>' 
    /> 

を更新

リピータやページのライフサイクル内のユーザーコントロールに私の子コントロールでエラーを与えたことはないもう一つのアプローチは、あります作成されたItemの代わりにItem Data Boundイベントを使用します。

実際、私は今考えてみると、e.Item.DataItem hasn; tがまだバインドされていないため、あなたのコードではいけません。

イベントをItemDataBoundに変更し、これが機能するかどうかを確認してください。

私はまだ項目のマークアップにコントロールを組み込み、イベントのコントロールの可視性を制御することをお勧めします(今はItemDataBoundになります)。コントロールをe.Item.FindControl("ControlId") as MyControlのように参照できます(現在の項目に見つからない場合はnullが返されます)。

は私がアコーディオンを使用して、ネストされたレポートを作成するために長い時間前にこれを行っていた

+0

問題は、ユーザーコントロールに自分の子コントロール(この場合はリピータ)があります。ユーザーコントロールのpage_loadイベントでは、リピータ変数は実際にはnullです。私は自分自身を設定することはできません、asp.netフレームワークが必要です。 – Jeremy

+0

理論では、負荷を使用する必要はなく、代わりにセッターを使用する必要があります。もう1つの選択肢は、問題を修正する可能性があるという回答の更新です。私は問題が使用されたイベントだと思う、これは問題になる可能性が非常に高い。 – Meligy

3

...両方を組み合わせてみるか、少なくともバインドの代わりに、作成したデータにイベントを変更して、見てみましょう。あなたが動的にユーザーコントロールのインスタンスを追加するインデックスでは、

// Declare Placeholder  
PlaceHolder ph = (PlaceHolder)e.Item.FindControl("SubItemPlaceholder") 

// Adding some literal controls to header 
ph.Controls.Add(new LiteralControl("This is the accordion header!!")); 

// Declare new control variable 
crt = new Control(); 

// Load up your User Control 
crt = LoadControl("~/MyControl.ascx"); 

// Check if it has loaded properly 
if (crt != null) 
{ 
    // GET/SET any custom properties of the User Control 
    ((myClass)crt).title = "Welcome"; 

    // Add the new User Control to the placeholder's controls collection 
    ph.Controls.Add(crt); 
} 

注:ユーザーコントロールで 、あなたは宣言タグ

「クラス名」を追加する必要があります
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="MyControl.ascx.cs" Inherits="myTest" ClassName="myClass" %> 

また、インスタンスを動的に作成するときに公開するプロパティは、次のように宣言します。

"repMyClass"の作成時に値を強制したい場合は、それをプロパティとして設定し、任意の値をプログラマティカルに割り当てることができます。

+0

問題は、私のユーザーコントロールにそれ自身の子コントロール(この場合はリピーター)があることです。ユーザーコントロールのpage_loadイベントでは、リピータ変数は実際にはnullです。私は自分自身を設定することはできません、asp.netフレームワークが必要です。 – Jeremy

+0

@Jeremy:できます。リピータータイプのプロパティを作成するだけです。あなたはそれにアクセスし、それをインスタンス化し、あなたが望むものを何でもします。明確にしてください - 私によると、UserControlのパブリックプロパティは、UserControlのページロードで、パブリックプロパティを使用してリピータにデータをバインドする必要があります。あれは正しいですか? –

関連する問題