2012-11-29 83 views
0

我具有延伸CompositeControl定義爲生成的定製控件,的集合:綁定列表<CompositeControl的>到一箇中繼器

[PersistChildren(true)] 
[ToolboxData("<{0}:ContractControl runat=server></{0}:ContractControl>")] 
public class ContractControl : CompositeControl 
{ 
    private int contractID = 0; 
    private ContractTileControl tileControl = null; 
    private ContractDetailControl detailControl = null; 

    private HtmlGenericControl contractMainDiv = null; 

    public int ContractID 
    { 
     get { return this.contractID; } 
     set { this.contractID = value; } 
    } 

    public ContractTileControl TileControl 
    { 
     get { return this.tileControl; } 
     set { this.tileControl = value; } 
    } 

    public ContractDetailControl DetailControl 
    { 
     get { return this.detailControl; } 
     set { this.detailControl = value; } 
    } 

    public ContractControl() 
    { 
     this.contractMainDiv = new HtmlGenericControl("div"); 
     this.contractMainDiv.ID = "contractMainDiv"; 
     this.contractMainDiv.Attributes.Add("class", "contractMain"); 
    } 

    #region protected override void OnPreRender(EventArgs e) 
    protected override void OnPreRender(EventArgs e) 
    { 
     base.OnPreRender(e); 
     //CreateChildControls(); 
    } 
    #endregion 

    #region protected override void CreateChildControls() 
    protected override void CreateChildControls() 
    { 
     base.CreateChildControls(); 
     if (tileControl != null) 
     { 
      this.contractMainDiv.Controls.Add(tileControl); 
     } 

     if (detailControl != null) 
     { 
      this.contractMainDiv.Controls.Add(detailControl); 
     } 
     this.Controls.Add(contractMainDiv); 
     //base.CreateChildControls(); 
    } 


    #endregion 

    protected override void OnLoad(EventArgs e) 
    { 
     base.OnLoad(e); 
     CreateChildControls(); 
    } 

    protected override void OnInit(EventArgs e) 
    { 
     base.OnLoad(e); 
     EnsureChildControls(); 
    } 
} 

ContractTileControlContractDetailControlCompositeControl衍生另一個定製控件。

當我將它們添加到他們提供罰款asp:PlaceHolder控制設置,但是當我定義諸如中繼器:

<asp:Repeater ID="myRepeater" runat="server" > 
    <HeaderTemplate> 
     <table border="0" cellpadding="0" cellspacing="0"> 
    </HeaderTemplate> 

    <ItemTemplate> 
     <tr><td><easit:ContractControl ID="contractControl" runat="server" /> 
     </td></tr> 
    </ItemTemplate> 
    <FooterTemplate> 
     </table> 
    </FooterTemplate> 
</asp:Repeater> 

並將其綁定到它:

private void FillContractPlaceHolder() 
    { 

     List<ContractControl> controls = new List<ContractControl>(); 
     foreach(KeyValuePair<Customer, List<TFSContract>> pair in contractList) 
     { 
      Label customerNameLbl = new Label(); 
      customerNameLbl.ID = "customerNameLbl"; 
      customerNameLbl.CssClass = "customerName"; 
      customerNameLbl.Text = pair.Key.Name; 
      contractListPlaceHolder.Controls.Add(customerNameLbl); 

      foreach (TFSContract contract in pair.Value) 
      { 
       ContractStatusBarControl status = new ContractStatusBarControl(); 
       status.WidthPercent = GetFillPercent(contract.NumberOfTasks, contract.NumberOfFinishedTasks); 

       string[] contractNameParts = Regex.Split(contract.Contract.Name, @"[A-Z]{3}-[0-9|A-Z]{2}-[0-9|A-Z]{2}", RegexOptions.IgnoreCase); 

       ContractDetailControl detail = new ContractDetailControl(); 
       detail.ContractName = contractNameParts.Last(); 
       detail.DateStarted = contract.StartDate; 
       detail.DateFinished = contract.FinishDate; 
       detail.StatusBar = status; 

       ContractTileControl tile = new ContractTileControl(); 
       Match match = Regex.Match(contract.Contract.Name, @"[A-Z]{3}-[0-9|A-Z]{2}-[0-9|A-Z]{2}", RegexOptions.IgnoreCase); 
       if (match.Value.Length != 0) 
       { 
        tile.ContractNumber = match.Value; 
       } 

       tile.ContractTasksFinished = contract.NumberOfFinishedTasks; 
       tile.ContractTasksTotal = contract.NumberOfTasks; 

       ContractControl contractControl = new ContractControl(); 
       contractControl.ContractID = contract.Contract.Id; 
       contractControl.TileControl = tile; 
       contractControl.DetailControl = detail; 
       //contractListPlaceHolder.Controls.Add(contractControl); 
       controls.Add(contractControl); 
      } 


     } 

     myRepeater.DataSource = controls; 
     myRepeater.DataBind(); 

    } 

表被創建,但是隻有ContractControl的非複合部分contractMainDiv被渲染,因爲Repeater堅持tileControldetailControl都爲空,即使它們被正確設置爲它們各自類型的實例秒。

+0

你在base.CreateChildControls做什麼();?你在哪裏創建tileControl和detailControl? –

+0

無論基礎方法在做什麼。 tileControl和detailControl是在Page_Load上與具有中繼器的同一頁面上創建的,然後通過公開它們的屬性進行設置。 只使用佔位符並將它們添加到其控件集合時它工作得非常好,但我懷疑我沒有正確地將它綁定到中繼器。 –

+1

我認爲錯誤應該在那裏,你確定你在頁面加載中爲轉發器的所有實例分配這個屬性?在佔位符的情況下,你有一個ContractControl實例,如果中繼器不止一個,你能顯示初始化代碼嗎? –

回答

2

Repeater是數據綁定,它創建用於ItemTemplate在數據源中的每個項的實例,設置其DataItem從數據源的項目和數據結合的兒童。

在這種情況下,從數據源中的項目是你ContractControl的一個實例,你ItemTemplate沒有數據綁定,所以你會與ContractControl對你已經每一項空白實例結束添加到列表中。

的快速和骯髒的解決辦法是增加一個處理程序ItemDataBound事件您Repeater的,並複製的屬性,以真正的控制:

protected void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) 
{ 
    switch (e.Item.ItemType) 
    { 
     case ListItemType.Item: 
     case ListItemType.AlternatingItem: 
     case ListItemType.SelectedItem: 
     case ListItemType.EditItem: 
     { 
     var source = (ContractControl)e.Item.DataItem; 
     var destination = (ContractControl)e.Item.FindControl("contractControl"); 
     destination.ContractID = source.ContractID; 
     destination.TileControl = source.TileControl; 
     destination.DetailControl = source.DetailControl; 
     break; 
     } 
    } 
} 

一個更好的解決辦法是綁定你Repeater到列表的TFSContract對象,並將代碼移動到ItemDataBound事件處理程序中以構建ContractControl

編輯
更新只過程實戰項目,忽略頁眉,頁腳等

+0

首先 - 謝謝你的回答,但我有點問題。在您的示例中,目標始終爲空,可能是因爲自動生成ID。 –

+0

根據你發佈的代碼,我假定'easit:ContractControl'是一個'ContractControl',具有ID =「contractControl」'set。情況並非如此嗎? –

+0

對不起,它發生是因爲我忘了過濾掉頁眉/頁腳模板。無論如何非常感謝您的回答,我已經將生成的代碼移到了「myRepeater_ItemDataBound」事件中,它的工作原理就像一個魅力。 :) –