views:

735

answers:

1

I've got several Gridviews in my application in which I use a custom PagerTemplate. I'd like to turn this custom template into a UserControl so that I don't need to replicate the same logic in multiple pages. I'm pretty sure that such a thing is possible, but I'm unsure of how exactly to wire the UserControl to the Gridview's events, and what interfaces my control may need to implement.

I'm using ASP 2.0 frameworks.

Has anyone done something like this? And if so, do you have any sample code for your usercontrol?

Thanks in advance.

+2  A: 

Dave Anderson, a co-worker of mine, wrote this server control that could help you get started. Note that we're targeting .NET 3.5.

[AspNetHostingPermission(
  SecurityAction.Demand,
  Level = AspNetHostingPermissionLevel.Minimal),
  AspNetHostingPermission(SecurityAction.InheritanceDemand,
  Level = AspNetHostingPermissionLevel.Minimal),
  DefaultProperty("Text"),
  ToolboxData("<{0}:Pager runat=\"server\"> </{0}:Pager>"),
 Designer(typeof(ServerControls.Design.PagerDesigner))
]
public class Pager : WebControl, INamingContainer
{
    #region Private Constants

    private const string Command_First = "First";
    private const string Command_Prev = "Prev";
    private const string Command_Next = "Next";
    private const string Command_Last = "Last";

    #endregion

    #region Private members

    private Control PageableNamingContainer;
    private PropertyInfo PageCountInfo;
    private PropertyInfo PageIndexInfo;
    private DropDownList ddlCurrentPage;
    private Label lblPageCount;
    private Button btnFirst;
    private Button btnPrevious;
    private Button btnNext;
    private Button btnLast;

    #endregion

    #region Private Properties

    private int PageCount
    {
        get
        {
            int Result;
            if (InsideDataPager)
                Result = (int)Math.Ceiling((decimal)(TotalRowCount / PageSize)) + 1;
            else
                Result = (int)PageCountInfo.GetValue(PageableNamingContainer, null);

            return Result;
        }
    }
    private int PageIndex
    {
        get
        {
            int Result;
            if (InsideDataPager)
                Result = (int)Math.Floor((decimal)(StartRowIndex / PageSize));
            else
                Result = (int)PageIndexInfo.GetValue(PageableNamingContainer, null);

            return Result;
        }
    }

    private int StartRowIndex
    {
        get
        {
            if (InsideDataPager)
                return MyDataPager.StartRowIndex;
            else
                throw new Exception("DataPager functionality requires DataPager.");
        }
    }
    private int TotalRowCount
    {
        get
        {
            if (InsideDataPager)
                return MyDataPager.TotalRowCount;
            else
                throw new Exception("DataPager functionality requires DataPager.");
        }
    }
    private int PageSize
    {
        get
        {
            if (InsideDataPager)
                return MyDataPager.PageSize;
            else
                throw new Exception("DataPager functionality requires DataPager.");
        }
    }

    private bool InsideDataPager
    {
        get { return ViewState["InsideDataPager"] == null ? false : (bool)ViewState["InsideDataPager"]; }
        set { ViewState["InsideDataPager"] = value; }
    }

    #region DataPager-Specific properties

    private DataPager MyDataPager
    {
        get
        {
            if (InsideDataPager)
                return (DataPager)PageableNamingContainer;
            else
                throw new Exception("DataPager functionality requires DataPager.");
        }
    }
    private int PrevPageStartIndex
    {
        get { return StartRowIndex >= PageSize ? StartRowIndex - PageSize : 0; }
    }
    private int NextPageStartIndex
    {
        get { return StartRowIndex + PageSize >= TotalRowCount ? LastPageStartIndex : StartRowIndex + PageSize; }
    }
    private int LastPageStartIndex
    {
        get { return (PageCount-1) * PageSize; }
    }

    #endregion

    #endregion

    #region Public Properties

    [
    Category("Behavior"),
    DefaultValue(""),
    Description("The stylesheet class to use for the buttons")
    ]
    public bool HideInactiveButtons { get; set; }

    [
    Category("Behavior"),
    DefaultValue("true"),
    Description("Indicates whether the controls will invoke validation routines")
    ]
    public bool CausesValidation { get; set; }

    [
    Category("Appearance"),
    DefaultValue(""),
    Description("The stylesheet class to use for the buttons")
    ]
    public string ButtonCssClass { get; set; }

    [
    Category("Appearance"),
    DefaultValue("<<"),
    Description("The text to be shown on the button that navigates to the First page")
    ]
    public string FirstText { get; set; }
    [
    Category("Appearance"),
    DefaultValue("<"),
    Description("The text to be shown on the button that navigates to the Previous page")
    ]
    public string PreviousText { get; set; }
    [
    Category("Appearance"),
    DefaultValue(">"),
    Description("The text to be shown on the button that navigates to the Next page")
    ]
    public string NextText { get; set; }
    [
    Category("Appearance"),
    DefaultValue(">>"),
    Description("The text to be shown on the button that navigates to the Last page")
    ]
    public string LastText { get; set; }

    #endregion

    #region Overridden properties

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

    #endregion

    #region Overridden methods/events

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (!GetPageInfo(NamingContainer))
            throw new Exception("Unable to locate the Pageable Container.");
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        if (PageableNamingContainer != null)
        {
            EnsureChildControls();

            ddlCurrentPage.Items.Clear();
            for (int i = 0; i < PageCount; i++)
                ddlCurrentPage.Items.Add(new ListItem((i + 1).ToString(), (i + 1).ToString()));

            lblPageCount.Text = PageCount.ToString();
            if (HideInactiveButtons)
            {
                btnFirst.Visible = btnPrevious.Visible = (PageIndex > 0);
                btnLast.Visible = btnNext.Visible = (PageIndex < (PageCount - 1));
            }
            else
            {
                btnFirst.Enabled = btnPrevious.Enabled = (PageIndex > 0);
                btnLast.Enabled = btnNext.Enabled = (PageIndex < (PageCount - 1));
            }
            ddlCurrentPage.SelectedIndex = PageIndex;
        }
        else
            ddlCurrentPage.SelectedIndex = 0;
    }

    protected override bool OnBubbleEvent(object source, EventArgs args)
    {
        // We handle all our events inside this class when
        // we are inside a DataPager
        return InsideDataPager;
    }

    #endregion

    #region Event delegate

    protected void PagerEvent(object sender, EventArgs e)
    {
        if (InsideDataPager)
        {
            int NewStartingIndex;

            if (sender.GetType() == typeof(Button))
            {
                string arg = ((Button)sender).CommandArgument.ToString();
                switch (arg)
                {
                    case Command_Prev:
                        NewStartingIndex = PrevPageStartIndex;
                        break;
                    case Command_Next:
                        NewStartingIndex = NextPageStartIndex;
                        break;
                    case Command_Last:
                        NewStartingIndex = LastPageStartIndex;
                        break;
                    case Command_First:
                    default:
                        NewStartingIndex = 0;
                        break;
                }
            }
            else
            {
                NewStartingIndex = Math.Min(((DropDownList)sender).SelectedIndex * PageSize, LastPageStartIndex);
            }

            MyDataPager.SetPageProperties(NewStartingIndex, MyDataPager.MaximumRows, true);
        }
        else
        {
            CommandEventArgs ea = new CommandEventArgs("Page", ((DropDownList)sender).SelectedValue);
            RaiseBubbleEvent(this, ea);
        }
    }

    #endregion

    #region GetPageableContainer

    private bool GetPageInfo(Control namingContainer)
    {
        if (namingContainer == null || namingContainer.GetType() == typeof(Page))
            throw new Exception(this.GetType().ToString() + " must be used in a pageable container like a GridView.");

        /* 
         * NOTE: If we are inside a DataPager, this will be 
         *       our first-level NamingContainer, so there
         *       will never be any reflection in that case.
         */
        if (namingContainer.GetType() == typeof(DataPagerFieldItem))
        {
            InsideDataPager = true;
            PageableNamingContainer = ((DataPagerFieldItem)namingContainer).Pager;
            return true;
        }

        PageCountInfo = namingContainer.GetType().GetProperty("PageCount");
        PageIndexInfo = namingContainer.GetType().GetProperty("PageIndex");
        if (PageCountInfo == null || PageIndexInfo == null)
            return GetPageInfo(namingContainer.NamingContainer);
        else
        {
            PageableNamingContainer = namingContainer;
            return true;
        }
    }

    #endregion

    #region Control generation

    protected override void CreateChildControls()
    {
        Controls.Clear();
        Controls.Add(BuildControlTable());
    }

    private Table BuildControlTable()
    {
        Table ControlTable = new Table();
        ControlTable.CssClass = CssClass;
        TableRow tr = new TableRow();
        TableCell td = new TableCell();

        td.Text = "Page";
        tr.Cells.Add(td);

        td = new TableCell();
        ddlCurrentPage = new DropDownList();
        ddlCurrentPage.ID = "ddlCurrentPage";
        ddlCurrentPage.AutoPostBack = true;
        ddlCurrentPage.SelectedIndexChanged += PagerEvent;
        ddlCurrentPage.CausesValidation = CausesValidation;
        td.Controls.Add(ddlCurrentPage);
        tr.Cells.Add(td);

        td = new TableCell();
        td.Text = "of";
        tr.Cells.Add(td);

        td = new TableCell();
        lblPageCount = new Label();
        td.Controls.Add(lblPageCount);
        tr.Cells.Add(td);

        AddButton(tr, ref btnFirst, string.IsNullOrEmpty(FirstText) ? "<<" : FirstText, Command_First);
        AddButton(tr, ref btnPrevious, string.IsNullOrEmpty(PreviousText) ? "<" : PreviousText, Command_Prev);
        AddButton(tr, ref btnNext, string.IsNullOrEmpty(NextText) ? ">" : NextText, Command_Next);
        AddButton(tr, ref btnLast, string.IsNullOrEmpty(LastText) ? ">>" : LastText, Command_Last);
        ControlTable.Rows.Add(tr);

        return ControlTable;
    }

    private void AddButton(TableRow row, ref Button button, string text, string argument)
    {
        button = new Button();
        button.Text = text;
        button.CssClass = ButtonCssClass;
        button.CommandName = "Page";
        button.CommandArgument = argument;
        button.CausesValidation = CausesValidation;
        if (InsideDataPager)
            button.Click += PagerEvent;
        TableCell td = new TableCell();
        td.Controls.Add(button);
        row.Cells.Add(td);
    }

    #endregion

}
marc
what is the Designer attribute referencing?Designer(typeof(ServerControls.Design.PagerDesigner))
flesh