Jim's Blog Ramblings about novels, comics, programming, and other geek topics

12Aug/073

Templated User Control – Paging DataRepeater

Google AdSense

This is something that I’ve wanted to do for a while and I finally wrote the code for it on Friday. I use the ASP.NET DataRepeater control nearly exclusively for rendering rows from the Microsoft SQL Server database. However, the biggest missing feature from the DataRepeater is support for paging. So, like most developers, I just wrote additional code to handle it myself.

Making a DataRepeater to page results was the easy part. You just bind it to a System.Data.PagedDataSource, set the CurrentPageIndex property to the current page (zero-based), and set the PageSize property to however many records you want per page. Of course, you’ll need to include links for “Next” and “Previous” pages or a list of page numbers to jump to. I track the current page index by using a URL parameter on the Page_Load event. There’s also the PageCount property of the CurrentPageIndex (not zero-based) that returns the total number of pages based on the PageSize value.

Okay, so I wanted to bundle all of that code into an ASP.NET User Control. This lead me to MSDN and the blogosphere, but I stumbled for a few minutes due to the overwhelming number of search results. After a few minutes, I finally found the correct search phrase of “Templated User Control DataRepeater.”

Here's a snippet of code that I'm using now.


Below is how the User Control looks on the Web Form page. There's a few properties (such as PageSize) that are implemented, but not used below. Due to the size of the code blocks, I removed commenting and some segments.

ASP.NET Web Page (Design)
    <asp:SqlDataSource ID="sqlMyQuery" runat="server"
        ConnectionString="<%$ ConnectionStrings:My_Database%>"
        SelectCommand="select Title, Id from MyTable">
    </asp:SqlDataSource>

    <MyControls:PagedRepeater id="repActiveOrdersPaged" runat="server"
        PageSize="25"
        DataSourceId="sqlMyQuery"
        EnableViewState="false">
        <ItemTemplate>
              <%# Eval("Title") %> <%# Eval("taskorder_id") %>
             <hr/>
        </ItemTemplate>
    </MyControls:PagedRepeater>

Here's a view of the User Control's design

WebControls/PagedRepeater.ascx (Design)
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="PagedRepeater.ascx.cs"
    Inherits="WebControls_PagedRepeater" %>
<asp:Repeater ID="dataRepeater" runat="server" OnItemDataBound="dataRepeater_ItemDataBound">
    <HeaderTemplate>
            Showing Page
            <asp:Literal ID="litCurrentPage" runat="server"></asp:Literal>
            of
            <asp:Literal ID="litTotalPages" runat="server"></asp:Literal>
            <asp:HyperLink ID="hypPrevPage" runat="server">
                <asp:Literal ID="litPrevPageText" runat="server">Prev Page</asp:Literal></asp:HyperLink>
            <asp:HyperLink ID="hypNextPage" runat="server">
                <asp:Literal ID="litNextPageText" runat="server">Next Page</asp:Literal></asp:HyperLink>
    </HeaderTemplate>
    <ItemTemplate>
        <asp:PlaceHolder runat="server" ID="placeHolderItemTemplate" />
    </ItemTemplate>
    <FooterTemplate>
            Showing Page
            <asp:Literal ID="litCurrentPage" runat="server"></asp:Literal>
            of
            <asp:Literal ID="litTotalPages" runat="server"></asp:Literal>
            <asp:HyperLink ID="hypPrevPage" runat="server">
                <asp:Literal ID="litPrevPageText" runat="server">Prev Page</asp:Literal></asp:HyperLink>
            <asp:HyperLink ID="hypNextPage" runat="server">
                <asp:Literal ID="litNextPageText" runat="server">Next Page</asp:Literal></asp:HyperLink>
    </FooterTemplate>
</asp:Repeater>

Here's the User Control's code behind

WebControls/PagedRepeater.ascx.cs (Code Behind)
public partial class WebControls_PagedRepeater : UserControl
{

    private int _currentPageIndex;
    private string _dataSourceId = string.Empty;
    private PagedDataSource _pagedDataSource;
    public void DataSourceCallback(IEnumerable data)
    {
        if (data != null)
        {
            _pagedDataSource.DataSource = data;
            dataRepeater.DataSource = _pagedDataSource;
            dataRepeater.DataBind();
        }
    }

    public WebControls_PagedRepeater()
    {
        _pagedDataSource = new PagedDataSource();
        _currentPageIndex = 0;
        this.AllowPaging = true;

        this.PageSize = 25;
    }

    protected void dataRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Header || e.Item.ItemType == ListItemType.Footer)
        {
            int prevPageIndex = _currentPageIndex - 1;
            int nextPageIndex = _currentPageIndex + 1;

            string pageUrl = HttpContext.Current.Request.Url.AbsolutePath;

            HyperLink hypHeaderPrev = (HyperLink)e.Item.FindControl("hypPrevPage");
            HyperLink hypHeaderNext = (HyperLink)e.Item.FindControl("hypNextPage");
            Literal litCurrentPage = (Literal)e.Item.FindControl("litCurrentPage");
            Literal litTotalPages = (Literal)e.Item.FindControl("litTotalPages");

            litCurrentPage.Text = (_currentPageIndex + 1).ToString();
            litTotalPages.Text = this.PageCount.ToString();

            if (_currentPageIndex > 0)
            {
                hypHeaderPrev.NavigateUrl = string.Format("{0}?page={1}", pageUrl, prevPageIndex);
                hypHeaderPrev.Visible = true;
            }
            else
                hypHeaderPrev.Visible = false;


            if (_currentPageIndex < this.PageCount - 1)
            {
                hypHeaderNext.NavigateUrl = string.Format("{0}?page={1}", pageUrl, nextPageIndex);
                hypHeaderNext.Visible = true;
            }
            else
                hypHeaderNext.Visible = false;

        }

        if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
        {
            if (_itemTemplate != null)
            {
                ItemContainer container = new ItemContainer(0, e.Item.DataItem);
                _itemTemplate.InstantiateIn(container);
                PlaceHolder ph = (PlaceHolder)e.Item.FindControl("PlaceHolderItemTemplate");
                ph.Controls.Add(container);
            }
            e.Item.DataBind();
        }
    }


    protected override void OnDataBinding(EventArgs e)
    {
        EnsureChildControls();
        base.OnDataBinding(e);
        _pagedDataSource.CurrentPageIndex = this.CurrentPageIndex;

        if (this.DataSourceId.Length.Equals(0))
        {   //use datasource
            dataRepeater.DataSource = _pagedDataSource;
            dataRepeater.DataBind();
        }
        else
        {   //use datasourceId

            Control cntrl = this.Parent.FindControl(this.DataSourceId);

            if (cntrl == null)
                cntrl = this.Parent.NamingContainer.FindControl(this.DataSourceId);

            if (cntrl == null)
                throw new ApplicationException(string.Format("Cannot find the DataSourceId of '{0}'.", this.DataSourceId));

            DataSourceControl dbControl = (DataSourceControl)cntrl;

            if (dbControl != null)
            {
                dbControl.DataBind();
                ICollection viewNames = ((IDataSource)dbControl).GetViewNames();
                string viewName = null;
                foreach (string name in viewNames)
                {
                    viewName = name;
                    break;//get 1st name
                }

                DataSourceViewSelectCallback delCallback = new DataSourceViewSelectCallback(DataSourceCallback);
                ((IDataSource)dbControl).GetView(viewName).Select(DataSourceSelectArguments.Empty, delCallback);
            }
        }


    }


    protected void Page_Init(object sender, EventArgs e)
    {
        if (Request.Params["page"] != null)
            if (!int.TryParse(Request.Params["page"], out _currentPageIndex))
                _currentPageIndex = 0;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        this.DataBind();
    }





... lots more code for properties


    public IEnumerable DataSource
    {
        get { return _pagedDataSource.DataSource; }
        set { _pagedDataSource.DataSource = value; }
    }

    public string DataSourceId
    {
        get { return _dataSourceId; }
        set { _dataSourceId = value; }
    }



    private ITemplate _itemTemplate = null;
    [TemplateContainer(typeof(ItemContainer))]
    public ITemplate ItemTemplate
    {
        get { return _itemTemplate; }
        set { _itemTemplate = value;}
    }
    public class ItemContainer : Control, INamingContainer
    {
        private int _index;
        private object _dataItem;
        internal ItemContainer(int index, object dataItem) { _index = index; _dataItem = dataItem; }
        public int Index { get { return _index; } }
        public object DataItem { get { return _dataItem; } }
    }

}
Helpful Links:
My Related Posts: ,

James Welch

James Welch is a software engineer in Vermont working for a large information technology company and specializing in .NET. Additionally, he holds a Master’s Degree in Software Engineering and a Bachelor of Science Degree in Computer Science. Jim also enjoys local craft beer, comic books, and science-fiction and fantasy novels, games, and movies.

Twitter Google+ 

Comments (3) Trackbacks (0)
  1. hai
    i want full source code with sample files for templated paging..plese send immediately

  2. I ended up rewriting all of this and not using this initial code base. I made my own “data repeater” custom web control and forgot trying to fix the ASP.NET data repeater. There’s a few examples on MSDN and CodeProject.

    Here’s a few links:
    http://www.codeproject.com/useritems/Templated_Pager_Control.asp
    http://msdn.microsoft.com/msdnmag/issues/05/06/CuttingEdge/
    http://weblogs.asp.net/scottgu/archive/2006/06/04/Supporting-Templates-with-ASP.NET-User-Controls.aspx
    http://msdn2.microsoft.com/en-us/library/36574bf6(vs.71).aspx

  3. Very nice article. I really enjoyed it reading. And it also cleared lot of my doubts about DataRepeater Control in Asp.Net. Check this link too its having wonderful explanation on DataRepeater Control in C#.Net, check that post url…

    http://www.mindstick.com/Articles/de1a3efe-25f4-4fb6-a48b-2c35d052475d/?DataRepeater%20Control%20in%20C#.Net

    Thanks everyone!!


Leave a Reply

No trackbacks yet.