1

我的应用程序中有几个 Gridview,我在其中使用自定义 PagerTemplate。我想把这个自定义模板变成一个 UserControl,这样我就不需要在多个页面中复制相同的逻辑。我很确定这样的事情是可能的,但我不确定如何将 UserControl 连接到 Gridview 的事件,以及我的控件可能需要实现哪些接口。

我正在使用 ASP 2.0 框架。

有没有人做过这样的事情?如果是这样,您的用户控件是否有任何示例代码?

4

1 回答 1

2

我的同事 Dave Anderson 编写了这个可以帮助您入门的服务器控件。请注意,我们的目标是 .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

}
于 2008-09-17T21:43:28.537 回答