using
System;
using
System.IO;
using
System.Drawing;
using
System.Data;
using
System.Data.SqlClient;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.ComponentModel;
using
Base.Data;
namespace
Base.Web
...
{ PagingMode enum#region PagingMode enum public enum PagingMode ...{ Cached, NonCached } #endregion PagerStyle enum#region PagerStyle enum public enum PagerStyle ...{ NextPrev, NumericPages, NumericList } #endregion VirtualRecordCount class#region VirtualRecordCount class public class VirtualRecordCount ...{ public int RecordCount; public int PageCount; public int RecordsInLastPage; } #endregion PageChangedEventArgs class#region PageChangedEventArgs class public class PageChangedEventArgs : EventArgs ...{ public int OldPageIndex; public int NewPageIndex; } #endregion ListChangedEventArgs class#region ListChangedEventArgs class public class ListChangedEventArgs : EventArgs ...{ public int OldListIndex; public int NewListIndex; } #endregion Page Control#region Page Control [DefaultProperty("SelectCommand")] [DefaultEvent("PageIndexChanged")] public class PageControl : WebControl, INamingContainer ...{ PRIVATE DATA MEMBERS#region PRIVATE DATA MEMBERS // *********************************************************************** // PRIVATE members private PagedDataSource _dataSource; private Control _controlToPaginate; private string CacheKeyName ...{ get ...{return Page.Request.FilePath + "_" + UniqueID + "_Data";} } private string CurrentPageText = "【当前{0}页】【总共{1}页】"; private string RecordCountText = "【总共{0}条记录】"; private string NoPageSelectedText = "无选中页"; private string QueryPageCommandText = "SELECT * FROM " + "(SELECT TOP {0} * FROM " + "(SELECT TOP {1} * FROM ({2}) AS t0 ORDER BY {3} {4}) AS t1 " + "ORDER BY {3} {5}) AS t2 " + "ORDER BY {3}"; private string QueryCountCommandText = "SELECT COUNT(*) FROM ({0}) AS t0"; // *********************************************************************** #endregion CTOR(s)#region CTOR(s) // *********************************************************************** // Ctor public PageControl() : base() ...{ _dataSource = null; _controlToPaginate = null; Font.Name = "verdana"; Font.Size = FontUnit.Point(8); BackColor = Color.Transparent; ForeColor = Color.Black; BorderStyle = BorderStyle.None; BorderWidth = Unit.Parse("1px"); Width=Unit.Parse("100%"); PagingMode = PagingMode.NonCached; PagerStyle = PagerStyle.NextPrev; CurrentPageIndex = 0; SelectCommand = ""; ItemsPerPage = 20; TotalPages = -1; CacheDuration = 60; } // *********************************************************************** #endregion PUBLIC PROGRAMMING INTERFACE#region PUBLIC PROGRAMMING INTERFACE // *********************************************************************** // METHOD ClearCache // Removes any data cached for paging public void ClearCache() ...{ if (PagingMode == PagingMode.Cached) Page.Cache.Remove(CacheKeyName); } // *********************************************************************** // *********************************************************************** // EVENT PageIndexChanged // Fires when the pager is about to switch to a new page public delegate void PageChangedEventHandler(object sender, PageChangedEventArgs e); public event PageChangedEventHandler PageIndexChanged; protected virtual void OnPageIndexChanged(PageChangedEventArgs e) ...{ if (PageIndexChanged != null) PageIndexChanged(this, e); } // *********************************************************************** public delegate void ListChangedEventHandler(object sender, ListChangedEventArgs e); public event ListChangedEventHandler ListIndexChanged; protected virtual void OnListIndexChanged(ListChangedEventArgs e) ...{ if (ListIndexChanged != null) ListIndexChanged(this, e); } // *********************************************************************** // PROPERTY CacheDuration [Description("Gets and sets for how many seconds the data should stay in the cache")] public int CacheDuration ...{ get ...{return Convert.ToInt32(ViewState["CacheDuration"]);} set ...{ViewState["CacheDuration"] = value;} } // *********************************************************************** // *********************************************************************** // PROPERTY PagingMode [Description("Indicates whether the data are retrieved page by page or can be cached")] public PagingMode PagingMode ...{ get ...{return (PagingMode) ViewState["PagingMode"];} set ...{ViewState["PagingMode"] = value;} } // *********************************************************************** // *********************************************************************** // PROPERTY PagerStyle [Description("Indicates the style of the pager's navigation bar")] public PagerStyle PagerStyle ...{ get ...{return (PagerStyle) ViewState["PagerStyle"];} set ...{ViewState["PagerStyle"] = value;} } // *********************************************************************** // *********************************************************************** // PROPERTY ControlToPaginate [Description("Gets and sets the name of the control to paginate")] public string ControlToPaginate ...{ get ...{return Convert.ToString(ViewState["ControlToPaginate"]);} set ...{ViewState["ControlToPaginate"] = value;} } // *********************************************************************** // *********************************************************************** // PROPERTY ItemsPerPage [Description("Gets and sets the number of items to display per page")] public int ItemsPerPage ...{ get ...{return Convert.ToInt32(ViewState["ItemsPerPage"]);} set ...{ViewState["ItemsPerPage"] = value;} } // *********************************************************************** // *********************************************************************** // PROPERTY CurrentPageIndex [Description("Gets and sets the index of the currently displayed page")] public int CurrentPageIndex ...{ get ...{return Convert.ToInt32(ViewState["CurrentPageIndex"]);} set ...{ViewState["CurrentPageIndex"] = value;} } // *********************************************************************** public int RecordCount ...{ get ...{return Convert.ToInt32(ViewState["RecordCount"]);} set ...{ViewState["RecordCount"] = value;} } public int CurrentListIndex ...{ get ...{return Convert.ToInt32(ViewState["CurrentListIndex"]);} set ...{ViewState["CurrentListIndex"] = value;} } public int ListCount ...{ get ...{return Convert.ToInt32(ViewState["ListCount"]);} set ...{ViewState["ListCount"] = value;} } // *********************************************************************** // PROPERTY SelectCommand [Description("Gets and sets the SQL query to get data")] public string SelectCommand ...{ get ...{return Convert.ToString(ViewState["SelectCommand"]);} set ...{ViewState["SelectCommand"] = value;} } // *********************************************************************** // *********************************************************************** // PROPERTY SortField [Description("Gets and sets the sort-by field. It is mandatory in NonCached mode.)")] public string SortField ...{ get ...{return Convert.ToString(ViewState["SortKeyField"]);} set ...{ViewState["SortKeyField"] = value;} } // *********************************************************************** // *********************************************************************** // PROPERTY PageCount // Gets the number of displayable pages [Browsable(false)] public int PageCount ...{ get ...{return TotalPages;} } // *********************************************************************** // *********************************************************************** // PROPERTY TotalPages // Gets and sets the number of pages to display protected int TotalPages ...{ get ...{return Convert.ToInt32(ViewState["TotalPages"]);} set ...{ViewState["TotalPages"] = value;} } // *********************************************************************** // *********************************************************************** // OVERRIDE DataBind // Fetches and stores the data public override void DataBind() ...{ // Fires the data binding event base.DataBind(); // Controls must be recreated after data binding ChildControlsCreated = false; // Ensures the control exists and is a list control if (ControlToPaginate == "") return; _controlToPaginate = Page.FindControl(ControlToPaginate); if (_controlToPaginate == null) return; if (!(_controlToPaginate is BaseDataList || _controlToPaginate is ListControl||_controlToPaginate is Repeater)) return; // Ensures enough info to connect and query is specified if (SelectCommand == "") return; // Fetch data if (PagingMode == PagingMode.Cached) ...{ FetchAllData(); } else ...{ //if (SortField == "") // return; FetchPageData(); } // Bind data to the buddy control BaseDataList baseDataListControl = null; ListControl listControl = null; if (_controlToPaginate is BaseDataList) ...{ baseDataListControl = (BaseDataList) _controlToPaginate; baseDataListControl.DataSource = _dataSource; baseDataListControl.DataBind(); return; } if (_controlToPaginate is ListControl) ...{ listControl = (ListControl) _controlToPaginate; listControl.Items.Clear(); listControl.DataSource = _dataSource; listControl.DataBind(); return; } if (_controlToPaginate is Repeater) ...{ ( _controlToPaginate as Repeater).DataSource=_dataSource; ( _controlToPaginate as Repeater).DataBind(); return; } } // *********************************************************************** // *********************************************************************** // OVERRIDE Render // Writes the content to be rendered on the client protected override void Render(HtmlTextWriter output) ...{ // If in design-mode ensure that child controls have been created. // Child controls are not created at this time in design-mode because // there's no pre-render stage. Do so for composite controls like this if (Site != null && Site.DesignMode) CreateChildControls(); base.Render(output); } // *********************************************************************** // *********************************************************************** // OVERRIDE CreateChildControls // Outputs the HTML markup for the control protected override void CreateChildControls() ...{ Controls.Clear(); ClearChildViewState(); BuildControlHierarchy(); } // *********************************************************************** #endregion PRIVATE HELPER METHODS#region PRIVATE HELPER METHODS // *********************************************************************** // PRIVATE BuildControlHierarchy // Control the building of the control's hierarchy private void BuildControlHierarchy() ...{ // Build the surrounding table (one row, two cells) Table t = new Table(); t.Font.Name = Font.Name; t.Font.Size = Font.Size; t.BorderStyle = BorderStyle; t.BorderWidth = BorderWidth; t.BorderColor = BorderColor; t.Width = Width; t.Height = Height; t.BackColor = BackColor; t.ForeColor = ForeColor; // Build the table row TableRow row = new TableRow(); t.Rows.Add(row); // Build the cell with the page index TableCell cellPageDesc = new TableCell(); cellPageDesc.HorizontalAlign = HorizontalAlign.Left; BuildCurrentPage(cellPageDesc); row.Cells.Add(cellPageDesc); // Build the cell with navigation bar TableCell cellNavBar = new TableCell(); switch(PagerStyle) ...{ case PagerStyle.NextPrev: BuildNextPrevUI(cellNavBar); break; case PagerStyle.NumericPages: BuildNumericPagesUI(cellNavBar); break; case PagerStyle.NumericList: BuildNumericListUI(cellNavBar); break; } cellNavBar.HorizontalAlign=HorizontalAlign.Justify; row.Cells.Add(cellNavBar); TableCell cellRecordCountDesc = new TableCell(); cellRecordCountDesc.HorizontalAlign = HorizontalAlign.Right; BuildRecordCount(cellRecordCountDesc); row.Cells.Add(cellRecordCountDesc); // Add the table to the control tree Controls.Add(t); } // *********************************************************************** // *********************************************************************** // PRIVATE BuildNextPrevUI // Generates the HTML markup for the Next/Prev navigation bar private void BuildNextPrevUI(TableCell cell) ...{ bool isValidPage = (CurrentPageIndex >=0 && CurrentPageIndex <= TotalPages-1); bool canMoveBack = (CurrentPageIndex>0); bool canMoveForward = (CurrentPageIndex<TotalPages-1); // Render the << button LinkButton first = new LinkButton(); first.ID = "First"; first.Click += new EventHandler(first_Click); first.Font.Name = "webdings"; first.Font.Size = FontUnit.Medium; first.ForeColor = ForeColor; first.ToolTip = "First page"; first.Text = "7"; first.Enabled = isValidPage && canMoveBack; cell.Controls.Add(first); // Add a separator cell.Controls.Add(new LiteralControl(" ")); // Render the < button LinkButton prev = new LinkButton(); prev.ID = "Prev"; prev.Click += new EventHandler(prev_Click); prev.Font.Name = "webdings"; prev.Font.Size = FontUnit.Medium; prev.ForeColor = ForeColor; prev.ToolTip = "Previous page"; prev.Text = "3"; prev.Enabled = isValidPage && canMoveBack; cell.Controls.Add(prev); // Add a separator cell.Controls.Add(new LiteralControl(" ")); // Render the > button LinkButton next = new LinkButton(); next.ID = "Next"; next.Click += new EventHandler(next_Click); next.Font.Name = "webdings"; next.Font.Size = FontUnit.Medium; next.ForeColor = ForeColor; next.ToolTip = "Next page"; next.Text = "4"; next.Enabled = isValidPage && canMoveForward; cell.Controls.Add(next); // Add a separator cell.Controls.Add(new LiteralControl(" ")); // Render the >> button LinkButton last = new LinkButton(); last.ID = "Last"; last.Click += new EventHandler(last_Click); last.Font.Name = "webdings"; last.Font.Size = FontUnit.Medium; last.ForeColor = ForeColor; last.ToolTip = "Last page"; last.Text = "8"; last.Enabled = isValidPage && canMoveForward; cell.Controls.Add(last); } // *********************************************************************** private void BuildNumericListUI(TableCell cell) ...{ bool isValidList = (CurrentListIndex >=0 && CurrentListIndex <= ListCount-1); bool canMoveBack = (CurrentListIndex>0); bool canMoveForward = (CurrentListIndex<ListCount-1); // Render the << button LinkButton first = new LinkButton(); first.ID = "First"; first.Click += new EventHandler(firstList_Click); first.Font.Name = "webdings"; first.Font.Size = FontUnit.Medium; first.ForeColor = ForeColor; first.ToolTip = "First page"; first.Text = "7"; first.Enabled = isValidList && canMoveBack; cell.Controls.Add(first); // Add a separator cell.Controls.Add(new LiteralControl(" ")); // Render the < button LinkButton prev = new LinkButton(); prev.ID = "Prev"; prev.Click += new EventHandler(prevList_Click); prev.Font.Name = "webdings"; prev.Font.Size = FontUnit.Medium; prev.ForeColor = ForeColor; prev.ToolTip = "Previous page"; prev.Text = "3"; prev.Enabled = isValidList && canMoveBack; cell.Controls.Add(prev); cell.Controls.Add(new LiteralControl(" ")); for(int i=CurrentListIndex*10;i<(CurrentListIndex+1)*10&&i<PageCount;i++) ...{ LinkButton lbtn = new LinkButton(); lbtn.ID = "lbtn_"+i.ToString(); lbtn.Click += new EventHandler(lbtn_Click); if(i==CurrentPageIndex) ...{ lbtn.ForeColor = Color.Red; } else ...{ lbtn.ForeColor = ForeColor; } lbtn.ToolTip = "第"+i.ToString()+"页"; lbtn.Text = (i+1).ToString(); cell.Controls.Add(lbtn); cell.Controls.Add(new LiteralControl(" | ")); } // Render the > button LinkButton next = new LinkButton(); next.ID = "Next"; next.Click += new EventHandler(nextList_Click); next.Font.Name = "webdings"; next.Font.Size = FontUnit.Medium; next.ForeColor = ForeColor; next.ToolTip = "Next page"; next.Text = "4"; next.Enabled = isValidList && canMoveForward; cell.Controls.Add(next); // Add a separator cell.Controls.Add(new LiteralControl(" ")); // Render the >> button LinkButton last = new LinkButton(); last.ID = "Last"; last.Click += new EventHandler(lastList_Click); last.Font.Name = "webdings"; last.Font.Size = FontUnit.Medium; last.ForeColor = ForeColor; last.ToolTip = "Last page"; last.Text = "8"; last.Enabled = isValidList && canMoveForward; cell.Controls.Add(last); } // *********************************************************************** // PRIVATE BuildNumericPagesUI // Generates the HTML markup for the Numeric Pages button bar private void BuildNumericPagesUI(TableCell cell) ...{ // Render a drop-down list DropDownList pageList = new DropDownList(); pageList.ID = "PageList"; pageList.AutoPostBack = true; pageList.SelectedIndexChanged += new EventHandler(PageList_Click); pageList.Font.Name = Font.Name; pageList.Font.Size = Font.Size; pageList.ForeColor = ForeColor; // Embellish the list when there are no pages to list if (TotalPages <=0 || CurrentPageIndex == -1) ...{ pageList.Items.Add("No pages"); pageList.Enabled = false; pageList.SelectedIndex = 0; } else // Populate the list ...{ for(int i=1; i<=TotalPages; i++) ...{ ListItem item = new ListItem(i.ToString(), (i-1).ToString()); pageList.Items.Add(item); } pageList.SelectedIndex = CurrentPageIndex; } cell.Controls.Add(pageList); } // *********************************************************************** // *********************************************************************** // PRIVATE BuildCurrentPage // Generates the HTML markup to describe the current page (0-based) private void BuildCurrentPage(TableCell cell) ...{ // Use a standard template: Page X of Y if (CurrentPageIndex <0 || CurrentPageIndex >= TotalPages) cell.Text = NoPageSelectedText; else cell.Text = String.Format(CurrentPageText, (CurrentPageIndex+1), TotalPages); } // *********************************************************************** private void BuildRecordCount(TableCell cell) ...{ cell.Text = String.Format(RecordCountText,RecordCount.ToString()); } // *********************************************************************** // PRIVATE ValidatePageIndex // Ensures the CurrentPageIndex is either valid [0,TotalPages) or -1 private void ValidatePageIndex() ...{ if (!(CurrentPageIndex >=0 && CurrentPageIndex < TotalPages)) CurrentPageIndex = -1; return; } private void ValidateListIndex() ...{ if (!(CurrentListIndex >=0 && CurrentListIndex < ListCount)) CurrentListIndex = -1; return; } // *********************************************************************** // *********************************************************************** // PRIVATE FetchAllData // Runs the query for all data to be paged and caches the resulting data private void FetchAllData() ...{ // Looks for data in the ASP.NET Cache DataTable data; data = (DataTable) Page.Cache[CacheKeyName]; if (data == null) ...{ // Fix SelectCommand with order-by info AdjustSelectCommand(true); data = DBHelper.ExecuteDataTable(this.SelectCommand,false); Page.Cache.Insert(CacheKeyName, data, null, DateTime.Now.AddSeconds(CacheDuration), System.Web.Caching.Cache.NoSlidingExpiration); } // Configures the paged data source component if (_dataSource == null) _dataSource = new PagedDataSource(); _dataSource.DataSource = data.DefaultView; // must be IEnumerable! _dataSource.AllowPaging = true; _dataSource.PageSize = ItemsPerPage; TotalPages = _dataSource.PageCount; RecordCount = data.Rows.Count; ListCount=(PageCount%10==0)?PageCount/10:PageCount/10+1; // Ensures the page index is valid ValidatePageIndex(); if (CurrentPageIndex == -1) ...{ _dataSource = null; return; } ValidateListIndex(); if (CurrentListIndex == -1) return; // Selects the page to view _dataSource.CurrentPageIndex = CurrentPageIndex; } // *********************************************************************** // *********************************************************************** // PRIVATE FetchPageData // Runs the query to get only the data that fit into the current page private void FetchPageData() ...{ // Need a validated page index to fetch data. // Also need the virtual page count to validate the page index AdjustSelectCommand(false); VirtualRecordCount countInfo = CalculateVirtualRecordCount(); TotalPages = countInfo.PageCount; RecordCount = countInfo.RecordCount; ListCount=(PageCount%10==0)?PageCount/10:PageCount/10+1; // Validate the page number (ensures CurrentPageIndex is valid or -1) ValidatePageIndex(); if (CurrentPageIndex == -1) return; ValidateListIndex(); if (CurrentListIndex == -1) return; DataTable data =DBHelper.ExecuteDataTable(PrepareCommand(countInfo),false); // Configures the paged data source component if (_dataSource == null) _dataSource = new PagedDataSource(); _dataSource.AllowCustomPaging = true; _dataSource.AllowPaging = true; _dataSource.CurrentPageIndex = 0; _dataSource.PageSize = ItemsPerPage; _dataSource.VirtualCount = countInfo.RecordCount; _dataSource.DataSource = data.DefaultView; } // *********************************************************************** // *********************************************************************** // PRIVATE AdjustSelectCommand // Strips ORDER-BY clauses from SelectCommand and adds a new one based // on SortKeyField private void AdjustSelectCommand(bool addCustomSortInfo) ...{ // Truncate where ORDER BY is found string temp = SelectCommand.ToLower(); int pos = temp.IndexOf("order by"); if (pos > -1) SelectCommand = SelectCommand.Substring(0, pos); // Add new ORDER BY info if SortKeyField is specified if (SortField != "" && addCustomSortInfo) SelectCommand += " ORDER BY " + SortField; } // *********************************************************************** // *********************************************************************** // PRIVATE CalculateVirtualRecordCount // Calculates record and page count for the specified query private VirtualRecordCount CalculateVirtualRecordCount() ...{ VirtualRecordCount count = new VirtualRecordCount(); // Calculate the virtual number of records from the query count.RecordCount = GetQueryVirtualCount(); count.RecordsInLastPage = ItemsPerPage; // Calculate the correspondent number of pages int lastPage = count.RecordCount/ItemsPerPage; int remainder = count.RecordCount % ItemsPerPage; if (remainder >0) lastPage++; count.PageCount = lastPage; // Calculate the number of items in the last page if (remainder >0) count.RecordsInLastPage = remainder; return count; } // *********************************************************************** // *********************************************************************** // PRIVATE PrepareCommand // Prepares and returns the command object for the reader-based query private string PrepareCommand(VirtualRecordCount countInfo) ...{ if (SortField == "") ...{ // Get metadata for all columns and choose either the primary key // or the string text = "SET FMTONLY ON;" + SelectCommand + ";SET FMTONLY OFF;"; DataTable t = DBHelper.ExecuteDataTable(text,false); DataColumn col = null; if (t.PrimaryKey.Length >0) col = t.PrimaryKey[0]; else col = t.Columns[0]; SortField = col.ColumnName; } // Determines how many records are to be retrieved. // The last page could require less than other pages int recsToRetrieve = ItemsPerPage; if (CurrentPageIndex == countInfo.PageCount-1) recsToRetrieve = countInfo.RecordsInLastPage; string cmdText = String.Format(QueryPageCommandText, recsToRetrieve, // {0} --> page size ItemsPerPage*(CurrentPageIndex+1), // {1} --> size * index SelectCommand, // {2} --> base query SortField, // {3} --> key field in the query "ASC", // Default to ascending order "DESC"); return cmdText; } // *********************************************************************** // *********************************************************************** // PRIVATE GetQueryVirtualCount // Run a query to get the record count private int GetQueryVirtualCount() ...{ string cmdText = String.Format(QueryCountCommandText, SelectCommand); return Function.getInt(DBHelper.ExecuteDataTable(cmdText,false).Rows[0][0]); } // *********************************************************************** // *********************************************************************** // PRIVATE GoToPage // Sets the current page index private void GoToPage(int pageIndex) ...{ // Prepares event data PageChangedEventArgs e = new PageChangedEventArgs(); e.OldPageIndex = CurrentPageIndex; e.NewPageIndex = pageIndex; // Updates the current index CurrentPageIndex = pageIndex; // Fires the page changed event OnPageIndexChanged(e); // Binds new data DataBind(); } // *********************************************************************** private void GoToList(int listIndex) ...{ // Prepares event data ListChangedEventArgs e = new ListChangedEventArgs(); e.OldListIndex = CurrentListIndex; e.NewListIndex = listIndex; if(e.NewListIndex>e.OldListIndex) ...{ CurrentPageIndex=(e.NewListIndex)*10; } else ...{ CurrentPageIndex=(e.NewListIndex+1)*10-1; } // Updates the current index CurrentListIndex = listIndex; // Fires the page changed event OnListIndexChanged(e); // Binds new data DataBind(); } // *********************************************************************** // PRIVATE first_Click // Event handler for the << button private void first_Click(object sender, EventArgs e) ...{ GoToPage(0); } // *********************************************************************** private void lbtn_Click(object sender, EventArgs e) ...{ CurrentPageIndex=int.Parse((sender as LinkButton).Text)-1; GoToPage(CurrentPageIndex); } // *********************************************************************** // PRIVATE prev_Click // Event handler for the < button private void prev_Click(object sender, EventArgs e) ...{ GoToPage(CurrentPageIndex-1); } // *********************************************************************** private void prevList_Click(object sender, EventArgs e) ...{ GoToList(CurrentListIndex-1); } private void nextList_Click(object sender, EventArgs e) ...{ GoToList(CurrentListIndex+1); } private void firstList_Click(object sender, EventArgs e) ...{ GoToList(0); } private void lastList_Click(object sender, EventArgs e) ...{ GoToList(ListCount-1); } // *********************************************************************** // PRIVATE next_Click // Event handler for the > button private void next_Click(object sender, EventArgs e) ...{ GoToPage(CurrentPageIndex+1); } // *********************************************************************** // *********************************************************************** // PRIVATE last_Click // Event handler for the >> button private void last_Click(object sender, EventArgs e) ...{ GoToPage(TotalPages-1); } // *********************************************************************** // *********************************************************************** // PRIVATE PageList_Click // Event handler for any page selected from the drop-down page list private void PageList_Click(object sender, EventArgs e) ...{ DropDownList pageList = (DropDownList) sender; int pageIndex = Convert.ToInt32(pageList.SelectedItem.Value); GoToPage(pageIndex); } // *********************************************************************** #endregion } #endregion
转载请注明原文地址: https://ibbs.8miu.com/read-20018.html