2014-02-17 113 views
1

我想通過預定義模板將asp.net DataPager控件擴展爲自定義控件。這是所需的輸出自定義DataPager的問題

enter image description here

問題

  1. 當我加載包含自定義DataPager的首次頁面,我ObjectDataSourceSelectMethod被稱爲3倍。
  2. 當我嘗試使用DataPager加載另一頁數據時,SelectMethod被調用兩次。
  3. 當我嘗試加載另一頁數據時,無論是使用Next/Previous按鈕還是DropDownList,頁面都不會更改。我運行了一些調試,發現它沒有將正確的值傳遞給SelectMethod的StartRowIndexParameter(它每次調用方法時都會傳遞0)。

下面是我的自定義控件的代碼。

public class DataPagerDDL : DataPager 
{ 
    protected override void RenderContents(HtmlTextWriter writer) 
    { 
     //add custom template 
     TemplatePagerField templateField = new TemplatePagerField(); 
     templateField.PagerTemplate = new CustomTemplate(); 
     Fields.Add(templateField); 

     //add previous/next page template 
     NextPreviousPagerField nextPreviousField = new NextPreviousPagerField();    
     nextPreviousField.ShowFirstPageButton = false; 
     nextPreviousField.ShowLastPageButton = false; 
     nextPreviousField.PreviousPageText = "<<"; 
     nextPreviousField.NextPageText = ">>"; 
     Fields.Add(nextPreviousField); 

     base.RenderContents(writer); 
    } 

    public void cmbPage_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     DropDownList cmbPage = (DropDownList)sender; 
     this.SetPageProperties(cmbPage.SelectedIndex * MaximumRows, MaximumRows, true); 
    } 
} 

public class CustomTemplate : ITemplate 
{ 
    /// <summary> 
    /// Insert an instance of text and controls into the specified container. 
    /// </summary> 
    public void InstantiateIn(Control container) 
    { 
     DataPagerFieldItem caller = (DataPagerFieldItem)container; 
     DataPagerDDL pager = (DataPagerDDL)caller.Parent; 
     int totalPages = pager.TotalRowCount/pager.MaximumRows; 
     if (pager.TotalRowCount % pager.MaximumRows > 0) totalPages += 1; 
     int currentPage = (pager.StartRowIndex/pager.MaximumRows) + 1; 

     DropDownList cmbPage = new DropDownList(); 
     cmbPage.ID = "cmbPage"; 
     cmbPage.AutoPostBack = true; 
     cmbPage.SelectedIndexChanged += new EventHandler(pager.cmbPage_SelectedIndexChanged); 
     for (int i = 1; i <= totalPages; i++) 
     { 
      ListItem item = new ListItem(i.ToString(), i.ToString()); 
      if (i == currentPage) item.Selected = true; 
      cmbPage.Items.Add(item); 
     } 

     pager.Controls.Add(new LiteralControl("Page ")); 
     pager.Controls.Add(cmbPage); 
     pager.Controls.Add(new LiteralControl(" of " + totalPages.ToString() + " pages | ")); 
    } 
} 

這是我的頁面的樣子:

<asp:ListView ID="ListView1" DataSourceID="ods1" ... > 
... 
</asp:ListView> 

<custom:DataPagerDDL ID="CustomDataPager" runat="server" PagedControlID="ListView1" 
     PageSize="25"> 
</custom:DataPagerDDL>  

<asp:ObjectDataSource ID="ods1" ... > 
</asp:ObjectDataSource> 

我應該怎麼做,使我的自定義DataPager的工作如預期?提前致謝! :)

回答

2

我懷疑你是在頁面生命週期中太晚創建尋呼機字段。嘗試從DataPagerDDL類的Init事件創建它們。

此外,您的CustomTemplate應該將控件添加到container而不是pager

public class DataPagerDDL : DataPager 
{ 
    protected override void OnInit(EventArgs e) 
    { 
     CreateDefaultPagerFields(); 
     base.OnInit(e); 
    } 

    protected virtual void CreateDefaultPagerFields() 
    { 
     //add custom template 
     TemplatePagerField templateField = new TemplatePagerField(); 
     templateField.PagerTemplate = new CustomTemplate(); 
     Fields.Add(templateField); 

     //add previous/next page template 
     NextPreviousPagerField nextPreviousField = new NextPreviousPagerField();    
     nextPreviousField.ShowFirstPageButton = false; 
     nextPreviousField.ShowLastPageButton = false; 
     nextPreviousField.PreviousPageText = "<<"; 
     nextPreviousField.NextPageText = ">>"; 
     Fields.Add(nextPreviousField); 
    } 

    public void cmbPage_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     DropDownList cmbPage = (DropDownList)sender; 
     SetPageProperties(cmbPage.SelectedIndex * MaximumRows, MaximumRows, true); 
    } 
} 

public class CustomTemplate : ITemplate 
{ 
    public void InstantiateIn(Control container) 
    { 
     DataPagerFieldItem caller = (DataPagerFieldItem)container; 
     DataPagerDDL pager = (DataPagerDDL)caller.Parent; 
     int totalPages = pager.TotalRowCount/pager.MaximumRows; 
     if (pager.TotalRowCount % pager.MaximumRows > 0) totalPages += 1; 
     int currentPage = (pager.StartRowIndex/pager.MaximumRows) + 1; 

     DropDownList cmbPage = new DropDownList(); 
     cmbPage.ID = "cmbPage"; 
     cmbPage.AutoPostBack = true; 
     cmbPage.SelectedIndexChanged += pager.cmbPage_SelectedIndexChanged; 

     for (int i = 1; i <= totalPages; i++) 
     { 
      ListItem item = new ListItem(i.ToString(), i.ToString()); 
      if (i == currentPage) item.Selected = true; 
      cmbPage.Items.Add(item); 
     } 

     container.Controls.Add(new LiteralControl("Page ")); 
     container.Controls.Add(cmbPage); 
     container.Controls.Add(new LiteralControl(" of " + totalPages + " pages | ")); 
    } 
} 
+0

現貨上,謝謝!一般建議在Init上設置控件的屬性?如果控件具有其他自定義屬性,例如'Label'上的'UserName'屬性?我有另一個自定義控件,我嘗試在Init上設置屬性,但它不起作用。我認爲這是因爲自定義屬性的值(它是在HTML標記中設置的)直到Load事件之後才被檢索。我對嗎? –

+0

在控件的'Init'事件中設置屬性在很大程度上等同於在頁面標記中設置它們。屬性值不會存儲在'ViewState'中,因此您必須在每個請求上設置它們;不要將代碼包裝在'if(!IsPostBack)'塊中。當您動態修改控件樹時,Init'事件通常是您想要進行更改的最新點,以確保動態控件可以參與回發事件處理。 –

+0

採取'OnInit'方法爲我解決了一個無關的問題。我正在使用'CreateChildControls()'來實例化模板。除了沒有數據的情況以外,這個工作正常。出於某種原因,這個調用會自身級聯並導致堆棧溢出。重構代碼以這個帖子的方式實例化解決了這個問題。 – GunnerGuyven