// // System.Web.UI.WebControls.DataGrid.cs // // Authors: // Gaurav Vaish (gvaish@iitk.ac.in) // Andreas Nahr (ClassDevelopment@A-SoftTech.com) // // (C) Gaurav Vaish (2002) // (C) 2003 Andreas Nahr // using System; using System.Collections; using System.Globalization; using System.Web; using System.Web.UI; using System.Web.Util; using System.ComponentModel; using System.ComponentModel.Design; using System.Reflection; namespace System.Web.UI.WebControls { [Designer ("System.Web.UI.Design.WebControls.DataGridDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))] [Editor ("System.Web.UI.Design.WebControls.DataGridComponentEditor, " + Consts.AssemblySystem_Design, typeof (ComponentEditor))] public class DataGrid : BaseDataList, INamingContainer { public const string CancelCommandName = "Cancel"; public const string DeleteCommandName = "Delete"; public const string EditCommandName = "Edit"; public const string NextPageCommandArgument = "Next"; public const string PageCommandName = "Page"; public const string PrevPageCommandArgument = "Prev"; public const string SelectCommandName = "Select"; public const string SortCommandName = "Sort"; public const string UpdateCommandName = "Update"; private TableItemStyle alternatingItemStyle; private TableItemStyle editItemStyle; private TableItemStyle headerStyle; private TableItemStyle footerStyle; private TableItemStyle itemStyle; private TableItemStyle selectedItemStyle; private DataGridPagerStyle pagerStyle; private DataGridColumnCollection columns; private ArrayList columnsArrayList; private DataGridItemCollection items; private ArrayList itemsArrayList; private PagedDataSource pagedDataSource; private ArrayList autoGenColsArrayList; private IEnumerator storedData; private object storedDataFirst; private bool storedDataValid; private static readonly object CancelCommandEvent = new object(); private static readonly object DeleteCommandEvent = new object(); private static readonly object EditCommandEvent = new object(); private static readonly object ItemCommandEvent = new object(); private static readonly object ItemCreatedEvent = new object(); private static readonly object ItemDataBoundEvent = new object(); private static readonly object PageIndexChangedEvent = new object(); private static readonly object SortCommandEvent = new object(); private static readonly object UpdateCommandEvent = new object(); public DataGrid(): base() { } [DefaultValue (false), WebCategory ("Paging")] [WebSysDescription ("Allows custom paging.")] public virtual bool AllowCustomPaging { get { object o = ViewState["AllowCustomPaging"]; if(o != null) return (bool)o; return false; } set { ViewState["AllowCustomPaging"] = value; } } [DefaultValue (false), WebCategory ("Paging")] [WebSysDescription ("Allow using multiple pages.")] public virtual bool AllowPaging { get { object o = ViewState["AllowPaging"]; if(o != null) return (bool)o; return false; } set { ViewState["AllowPaging"] = value; } } [DefaultValue (false), WebCategory ("Behavior")] [WebSysDescription ("Allows the user to sort the table by clicking on column headers.")] public virtual bool AllowSorting { get { object o = ViewState["AllowSorting"]; if(o != null) return (bool)o; return false; } set { ViewState["AllowSorting"] = value; } } [NotifyParentProperty (true), WebCategory ("Style")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [PersistenceMode (PersistenceMode.InnerProperty)] [WebSysDescription ("The style applied to alternating items.")] public virtual TableItemStyle AlternatingItemStyle { get { if(alternatingItemStyle == null) { alternatingItemStyle = new TableItemStyle(); } if(IsTrackingViewState) { alternatingItemStyle.TrackViewState(); } return alternatingItemStyle; } } [DefaultValue (true), WebCategory ("Behavior")] [WebSysDescription ("Automatically generate columns at runtime for each field found in the datasource.")] public virtual bool AutoGenerateColumns { get { object o = ViewState["AutoGenerateColumns"]; if(o != null) return (bool)o; return true; } set { ViewState["AutoGenerateColumns"] = value; } } [DefaultValue (""), Bindable (true), WebCategory ("Appearance")] [Editor ("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))] [WebSysDescription ("The URL to the image file used as background.")] public virtual string BackImageUrl { get { if (!ControlStyleCreated) return string.Empty; return ((TableStyle) base.ControlStyle).BackImageUrl; } set { ((TableStyle) base.ControlStyle).BackImageUrl = value; } } [DefaultValue (true), WebCategory ("Behavior")] [PersistenceMode (PersistenceMode.InnerProperty)] [MergableProperty (false)] [Editor ("System.Web.UI.Design.WebControls.DataGridColumnCollectionEditor, " + Consts.AssemblySystem_Design, typeof (ComponentEditor))] [WebSysDescription ("Automatically generate columns at runtime for each field found in the datasource.")] public virtual DataGridColumnCollection Columns { get { if(columns == null) { columnsArrayList = new ArrayList(); columns = new DataGridColumnCollection(this, columnsArrayList); if(IsTrackingViewState) { ((IStateManager)columns).TrackViewState(); } } return columns; } } [Browsable (false), Bindable (true)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [WebSysDescription ("The index number for the currently selected page.")] public int CurrentPageIndex { get { object o = ViewState["CurrentPageIndex"]; if(o != null) return (int)o; return 0; } set { if(value < 0) throw new ArgumentOutOfRangeException ("value", "CurrentPageIndex value has to be 0 for 'not set' or > 0."); ViewState["CurrentPageIndex"] = value; } } [DefaultValue (-1), WebCategory ("Misc")] [WebSysDescription ("The index number for the currently edited item.")] public virtual int EditItemIndex { get { object o = ViewState["EditItemIndex"]; if(o != null) return (int)o; return -1; } set { if(value < -1) throw new ArgumentOutOfRangeException ("value", "EditItemIndex value has to be -1 for 'not set' or > -1."); ViewState["EditItemIndex"] = value; } } [NotifyParentProperty (true), WebCategory ("Style")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [PersistenceMode (PersistenceMode.InnerProperty)] [WebSysDescription ("The style applied to items that are currently being edited.")] public virtual TableItemStyle EditItemStyle { get { if(editItemStyle == null) { editItemStyle = new TableItemStyle(); if(IsTrackingViewState) { editItemStyle.TrackViewState(); } } return editItemStyle; } } [DefaultValue (null), NotifyParentProperty (true), WebCategory ("Style")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [PersistenceMode (PersistenceMode.InnerProperty)] [WebSysDescription ("The style applied to the footer.")] public virtual TableItemStyle FooterStyle { get { if(footerStyle == null) { footerStyle = new TableItemStyle(); if(IsTrackingViewState) { footerStyle.TrackViewState(); } } return footerStyle; } } [DefaultValue (null), NotifyParentProperty (true), WebCategory ("Style")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [PersistenceMode (PersistenceMode.InnerProperty)] [WebSysDescription ("The style applied to the header.")] public virtual TableItemStyle HeaderStyle { get { if(headerStyle == null) { headerStyle = new TableItemStyle(); if(IsTrackingViewState) { headerStyle.TrackViewState(); } } return headerStyle; } } [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [WebSysDescription ("A collection containing all items.")] public virtual DataGridItemCollection Items { get { if(items == null) { if(itemsArrayList == null) EnsureChildControls(); if(itemsArrayList == null) { itemsArrayList = new ArrayList(); } items = new DataGridItemCollection(itemsArrayList); } return items; } } [NotifyParentProperty (true), WebCategory ("Style")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [PersistenceMode (PersistenceMode.InnerProperty)] [WebSysDescription ("The style applied to items.")] public virtual TableItemStyle ItemStyle { get { if(itemStyle == null) { itemStyle = new TableItemStyle(); if(IsTrackingViewState) { itemStyle.TrackViewState(); } } return itemStyle; } } [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [WebSysDescription ("The number of pages.")] public int PageCount { get { if(pagedDataSource != null) { return pagedDataSource.PageCount; } object o = ViewState["PageCount"]; if(o != null) return (int)o; return 0; } } [NotifyParentProperty (true), WebCategory ("Style")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [PersistenceMode (PersistenceMode.InnerProperty)] [WebSysDescription ("The style applied to the pager.")] public virtual DataGridPagerStyle PagerStyle { get { if(pagerStyle == null) { pagerStyle = new DataGridPagerStyle(this); if(IsTrackingViewState) { pagerStyle.TrackViewState(); } } return pagerStyle; } } [DefaultValue (10), WebCategory ("Paging")] [WebSysDescription ("The maximum number of entries that are created per page.")] public virtual int PageSize { get { object o = ViewState["PageSize"]; if(o != null) return (int)o; return 10; } set { if(value < 1) throw new ArgumentOutOfRangeException(); ViewState["PageSize"] = value; } } [DefaultValue (-1), Bindable (true)] [WebSysDescription ("The index number for the currently selected item.")] public virtual int SelectedIndex { get { object o = ViewState["SelectedIndex"]; if(o != null) return (int)o; return -1; } set { if(value < -1) throw new ArgumentOutOfRangeException(); int prevVal = SelectedIndex; ViewState["SelectedIndex"] = value; if (itemsArrayList != null) { if (prevVal !=-1 && prevVal < itemsArrayList.Count) { DataGridItem prev = (DataGridItem)itemsArrayList[prevVal]; if(prev.ItemType != ListItemType.EditItem) { ListItemType newType = ListItemType.Item; if( (prevVal % 2) != 0) { newType = ListItemType.AlternatingItem; } prev.SetItemType(newType); } } if (value != -1 && itemsArrayList.Count > value) { DataGridItem itemToSelect = (DataGridItem) itemsArrayList [value]; if (itemToSelect.ItemType != ListItemType.EditItem) { itemToSelect.SetItemType (ListItemType.SelectedItem); } } } } } [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [WebSysDescription ("The currently selected item.")] public virtual DataGridItem SelectedItem { get { if(SelectedIndex == -1) return null; return Items[SelectedIndex]; } } [NotifyParentProperty (true), WebCategory ("Style")] [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [PersistenceMode (PersistenceMode.InnerProperty)] [WebSysDescription ("The style applied to the currently selected item.")] public virtual TableItemStyle SelectedItemStyle { get { if(selectedItemStyle == null) { selectedItemStyle = new TableItemStyle(); if(IsTrackingViewState) { selectedItemStyle.TrackViewState(); } } return selectedItemStyle; } } [DefaultValue (false), Bindable (true), WebCategory ("Appearance")] [WebSysDescription ("Determines if the footer should be shown.")] public virtual bool ShowFooter { get { object o = ViewState["ShowFooter"]; if(o != null) return (bool)o; return false; } set { ViewState["ShowFooter"] = value; } } [DefaultValue (false), Bindable (true), WebCategory ("Appearance")] [WebSysDescription ("Determines if the header should be shown.")] public virtual bool ShowHeader { get { object o = ViewState["ShowHeader"]; if(o != null) return (bool)o; return true; } set { ViewState["ShowHeader"] = value; } } [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [WebSysDescription ("The number of items that are visible.")] public virtual int VirtualItemCount { get { object o = ViewState["VirtualItemCount"]; if(o != null) return (int)o; return 0; } set { if(value < 0) throw new ArgumentOutOfRangeException ("value", "VirtualItemCount value has to be >= 0."); ViewState["VirtualItemCount"] = value; } } [WebCategory ("Action")] [WebSysDescription ("Raised when a cancel command is generated.")] public event DataGridCommandEventHandler CancelCommand { add { Events.AddHandler(CancelCommandEvent, value); } remove { Events.RemoveHandler(CancelCommandEvent, value); } } [WebCategory ("Action")] [WebSysDescription ("Raised when a delete command is generated.")] public event DataGridCommandEventHandler DeleteCommand { add { Events.AddHandler(DeleteCommandEvent, value); } remove { Events.RemoveHandler(DeleteCommandEvent, value); } } [WebCategory ("Action")] [WebSysDescription ("Raised when an edit command is generated.")] public event DataGridCommandEventHandler EditCommand { add { Events.AddHandler(EditCommandEvent, value); } remove { Events.RemoveHandler(EditCommandEvent, value); } } [WebCategory ("Action")] [WebSysDescription ("Raised when an item command is generated.")] public event DataGridCommandEventHandler ItemCommand { add { Events.AddHandler(ItemCommandEvent, value); } remove { Events.RemoveHandler(ItemCommandEvent, value); } } [WebCategory ("Behavior")] [WebSysDescription ("Raised when a new item is created.")] public event DataGridItemEventHandler ItemCreated { add { Events.AddHandler(ItemCreatedEvent, value); } remove { Events.RemoveHandler(ItemCreatedEvent, value); } } [WebCategory ("Behavior")] [WebSysDescription ("Raised when a item gets data-bound.")] public event DataGridItemEventHandler ItemDataBound { add { Events.AddHandler(ItemDataBoundEvent, value); } remove { Events.RemoveHandler(ItemDataBoundEvent, value); } } [WebCategory ("Action")] [WebSysDescription ("Raised when the currently selected page changes.")] public event DataGridPageChangedEventHandler PageIndexChanged { add { Events.AddHandler(PageIndexChangedEvent, value); } remove { Events.RemoveHandler(PageIndexChangedEvent, value); } } [WebCategory ("Action")] [WebSysDescription ("Raised when a sort command is generated.")] public event DataGridSortCommandEventHandler SortCommand { add { Events.AddHandler(SortCommandEvent, value); } remove { Events.RemoveHandler(SortCommandEvent, value); } } [WebCategory ("Action")] [WebSysDescription ("Raised when an update command is generated.")] public event DataGridCommandEventHandler UpdateCommand { add { Events.AddHandler(UpdateCommandEvent, value); } remove { Events.RemoveHandler(UpdateCommandEvent, value); } } protected override Style CreateControlStyle() { TableStyle style = new TableStyle(ViewState); style.GridLines = GridLines.Both; style.CellSpacing = 0; return style; } protected override void LoadViewState(object savedState) { if (savedState == null) return; object [] states = (object []) savedState; base.LoadViewState (states[0]); if(columns != null) ((IStateManager)columns).LoadViewState(states[1]); if(pagerStyle != null) pagerStyle.LoadViewState(states[2]); if(headerStyle != null) headerStyle.LoadViewState(states[3]); if(footerStyle != null) footerStyle.LoadViewState(states[4]); if(itemStyle != null) itemStyle.LoadViewState(states[5]); if(alternatingItemStyle != null) alternatingItemStyle.LoadViewState(states[6]); if(selectedItemStyle != null) selectedItemStyle.LoadViewState(states[7]); if(editItemStyle != null) editItemStyle.LoadViewState(states[8]); if (states [9] != null) { object[] array = ((object[]) states [9]); if (array.Length != 0) this.autoGenColsArrayList = new ArrayList (); else this.autoGenColsArrayList = null; for (int i = 0; i < array.Length; i++) { BoundColumn column1 = new BoundColumn (); ((IStateManager)column1).TrackViewState (); ((IStateManager)column1).LoadViewState (array [i]); column1.SetOwner (this); this.autoGenColsArrayList.Add (column1); } } } protected override object SaveViewState() { object[] states = new object [10]; states[0] = base.SaveViewState(); states[1] = (columns == null ? null : ((IStateManager)columns).SaveViewState()); states[2] = (pagerStyle == null ? null : pagerStyle.SaveViewState()); states[3] = (headerStyle == null ? null : headerStyle.SaveViewState()); states[4] = (footerStyle == null ? null : footerStyle.SaveViewState()); states[5] = (itemStyle == null ? null : itemStyle.SaveViewState()); states[6] = (alternatingItemStyle == null ? null : alternatingItemStyle.SaveViewState()); states[7] = (selectedItemStyle == null ? null : selectedItemStyle.SaveViewState()); states[8] = (editItemStyle == null ? null : editItemStyle.SaveViewState()); object [] array = null; if ((this.autoGenColsArrayList != null) && (this.autoGenColsArrayList.Count != 0)) { array = new object [((uint) this.autoGenColsArrayList.Count)]; for (int i = 0; i < array.Length; i++) array [i] = ((IStateManager) this.autoGenColsArrayList [i]).SaveViewState (); } states [9] = array; for (int i = states.Length - 1; i >= 0; i--) { if (states [i] != null) return states; } return null; } protected override void TrackViewState() { base.TrackViewState(); if(alternatingItemStyle != null) { alternatingItemStyle.TrackViewState(); } if(editItemStyle != null) { editItemStyle.TrackViewState(); } if(headerStyle != null) { headerStyle.TrackViewState(); } if(footerStyle != null) { footerStyle.TrackViewState(); } if(itemStyle != null) { itemStyle.TrackViewState(); } if(selectedItemStyle != null) { selectedItemStyle.TrackViewState(); } if(pagerStyle != null) { pagerStyle.TrackViewState(); } if(columns != null) { ((IStateManager)columns).TrackViewState(); } } protected override bool OnBubbleEvent(object source, EventArgs e) { bool retVal = false; if(e is DataGridCommandEventArgs) { DataGridCommandEventArgs ea = (DataGridCommandEventArgs)e; retVal = true; OnItemCommand(ea); string cmd = ea.CommandName; if(String.Compare(cmd, "select", true) == 0) { SelectedIndex = ea.Item.ItemIndex; OnSelectedIndexChanged(EventArgs.Empty); } else if(String.Compare(cmd,"page", true) == 0) { int cIndex = CurrentPageIndex; string cea = (string) ea.CommandArgument; if(String.Compare(cea, "prev", true) == 0) { cIndex--; } else if(String.Compare(cea, "next", true) == 0) { cIndex++; } else { cIndex = Convert.ToInt32 (cea) - 1; } OnPageIndexChanged(new DataGridPageChangedEventArgs(source, cIndex)); } else if(String.Compare(cmd, "sort", true) == 0) { OnSortCommand(new DataGridSortCommandEventArgs(source, ea)); } else if(String.Compare(cmd, "edit", true) == 0) { OnEditCommand(ea); } else if(String.Compare(cmd, "update", true) == 0) { OnUpdateCommand(ea); } else if(String.Compare(cmd, "cancel", true) == 0) { OnCancelCommand(ea); } else if(String.Compare(cmd, "delete", true) == 0) { OnDeleteCommand(ea); } } return retVal; } protected virtual void OnCancelCommand(DataGridCommandEventArgs e) { if(Events != null) { DataGridCommandEventHandler dceh = (DataGridCommandEventHandler)(Events[CancelCommandEvent]); if(dceh != null) dceh(this, e); } } protected virtual void OnDeleteCommand(DataGridCommandEventArgs e) { if(Events != null) { DataGridCommandEventHandler dceh = (DataGridCommandEventHandler)(Events[DeleteCommandEvent]); if(dceh != null) dceh(this, e); } } protected virtual void OnEditCommand(DataGridCommandEventArgs e) { if(Events != null) { DataGridCommandEventHandler dceh = (DataGridCommandEventHandler)(Events[EditCommandEvent]); if(dceh != null) dceh(this, e); } } protected virtual void OnItemCommand(DataGridCommandEventArgs e) { if(Events != null) { DataGridCommandEventHandler dceh = (DataGridCommandEventHandler)(Events[ItemCommandEvent]); if(dceh != null) dceh(this, e); } } protected virtual void OnItemCreated(DataGridItemEventArgs e) { if(Events != null) { DataGridItemEventHandler dceh = (DataGridItemEventHandler)(Events[ItemCreatedEvent]); if(dceh != null) dceh(this, e); } } protected virtual void OnItemDataBound(DataGridItemEventArgs e) { if(Events != null) { DataGridItemEventHandler dceh = (DataGridItemEventHandler)(Events[ItemDataBoundEvent]); if(dceh != null) dceh(this, e); } } protected virtual void OnPageIndexChanged(DataGridPageChangedEventArgs e) { if(Events != null) { DataGridPageChangedEventHandler dceh = (DataGridPageChangedEventHandler)(Events[PageIndexChangedEvent]); if(dceh != null) dceh(this, e); } } protected virtual void OnSortCommand(DataGridSortCommandEventArgs e) { if(Events != null) { DataGridSortCommandEventHandler dceh = (DataGridSortCommandEventHandler)(Events[SortCommandEvent]); if(dceh != null) dceh(this, e); } } protected virtual void OnUpdateCommand(DataGridCommandEventArgs e) { if(Events != null) { DataGridCommandEventHandler dceh = (DataGridCommandEventHandler)(Events[UpdateCommandEvent]); if(dceh != null) dceh(this, e); } } protected override void PrepareControlHierarchy() { if (Controls.Count == 0) return; Table display = (Table) Controls [0]; display.CopyBaseAttributes (this); if (ControlStyleCreated) { display.ApplyStyle (ControlStyle); } else { display.GridLines = GridLines.Both; display.CellSpacing = 0; } TableRowCollection rows = display.Rows; if (rows.Count == 0) return; int nCols = Columns.Count; DataGridColumn [] cols = new DataGridColumn [nCols]; Style deployStyle = null; if (nCols > 0) Columns.CopyTo (cols, 0); if (alternatingItemStyle != null) { deployStyle = new TableItemStyle (); deployStyle.CopyFrom (itemStyle); deployStyle.CopyFrom (alternatingItemStyle); } else { deployStyle = itemStyle; } int nrows = rows.Count; for (int counter = 0; counter < nrows; counter++) PrepareControlHierarchyForItem (cols, (DataGridItem) rows [counter], counter, deployStyle); } private void PrepareControlHierarchyForItem (DataGridColumn [] cols, DataGridItem item, int index, Style deployStyle) { switch (item.ItemType) { case ListItemType.Header: if (!ShowHeader) { item.Visible = false; break; } if (headerStyle != null) item.MergeStyle (headerStyle); goto case ListItemType.Separator; case ListItemType.Footer: if (!ShowFooter) { item.Visible = false; break; } if (footerStyle != null) item.MergeStyle (footerStyle); goto case ListItemType.Separator; case ListItemType.Item : item.MergeStyle (itemStyle); goto case ListItemType.Separator; case ListItemType.AlternatingItem: item.MergeStyle (deployStyle); goto case ListItemType.Separator; case ListItemType.SelectedItem: Style selStyle = new TableItemStyle (); if ((item.ItemIndex % 2) == 0) { selStyle.CopyFrom (itemStyle); } else { selStyle.CopyFrom (deployStyle); } selStyle.CopyFrom (selectedItemStyle); item.MergeStyle (selStyle); goto case ListItemType.Separator; case ListItemType.EditItem: Style edStyle = new TableItemStyle (); if ((item.ItemIndex % 2) == 0) { edStyle.CopyFrom (itemStyle); } else { edStyle.CopyFrom (deployStyle); } edStyle.CopyFrom (editItemStyle); item.MergeStyle (edStyle); goto case ListItemType.Separator; case ListItemType.Pager: if (pagerStyle == null) break; if (!pagerStyle.Visible) item.Visible = false; if (index == 0) { if (!pagerStyle.IsPagerOnTop) { item.Visible = false; break; } } else if (!pagerStyle.IsPagerOnBottom) { item.Visible = false; break; } item.MergeStyle (pagerStyle); goto case ListItemType.Separator; case ListItemType.Separator: TableCellCollection cells = item.Cells; int cellCount = cells.Count; if (cellCount > cols.Length) cellCount = cols.Length; if (cellCount > 0 && item.ItemType != ListItemType.Pager) { for (int i = 0; i < cellCount; i++) { Style colStyle = null; if (cols [i].Visible) { switch (item.ItemType) { case ListItemType.Header: colStyle = cols [i].HeaderStyleInternal; break; case ListItemType.Footer: colStyle = cols [i].FooterStyleInternal; break; default: colStyle = cols [i].ItemStyleInternal; break; } cells[i].MergeStyle (colStyle); } else { cells [i].Visible = false; } } } break; default: goto case ListItemType.Separator; } } protected override void CreateControlHierarchy(bool useDataSource) { IEnumerator pageSourceEnumerator; int itemCount; ArrayList dataKeys; ArrayList columns; IEnumerable resolvedDS; ICollection collResolvedDS; int pageDSCount; int colCount; DataGridColumn[] cols; Table deployTable; TableRowCollection deployRows; ListItemType deployType; int indexCounter; string dkField; bool dsUse; bool pgEnabled; int editIndex; int selIndex; pagedDataSource = CreatePagedDataSource(); pageSourceEnumerator = null; itemCount = -1; dataKeys = DataKeysArray; columns = null; if(itemsArrayList != null) { itemsArrayList.Clear(); } else { itemsArrayList = new ArrayList(); } if(!useDataSource) { itemCount = (int) ViewState["_!ItemCount"]; pageDSCount = (int) ViewState["_!DataSource_ItemCount"]; if(itemCount != -1) { if(pagedDataSource.IsCustomPagingEnabled) { pagedDataSource.DataSource = new DataSourceInternal(itemCount); } else { pagedDataSource.DataSource = new DataSourceInternal(pageDSCount); } pageSourceEnumerator = pagedDataSource.GetEnumerator(); columns = CreateColumnSet(null, false); itemsArrayList.Capacity = itemCount; } } else { dataKeys.Clear(); resolvedDS = GetResolvedDataSource (); if(resolvedDS != null) { collResolvedDS = resolvedDS as ICollection; if(pagedDataSource.IsPagingEnabled && !pagedDataSource.IsCustomPagingEnabled && collResolvedDS == null) { throw new HttpException(HttpRuntime.FormatResourceString("DataGrid_Missing_VirtualItemCount", ID)); } pagedDataSource.DataSource = resolvedDS; if(pagedDataSource.IsPagingEnabled && (pagedDataSource.CurrentPageIndex < 0 || pagedDataSource.PageCount < pagedDataSource.CurrentPageIndex)) { throw new HttpException(HttpRuntime.FormatResourceString("DataGrid_Invalid_Current_PageIndex", ID)); } columns = CreateColumnSet(pagedDataSource, useDataSource); if(storedDataValid) { pageSourceEnumerator = storedData; } else { pageSourceEnumerator = pagedDataSource.GetEnumerator(); } if(collResolvedDS != null) { pageDSCount = pagedDataSource.Count; dataKeys.Capacity = pageDSCount; itemsArrayList.Capacity = pageDSCount; } } } colCount = 0; if(columns != null) colCount = columns.Count; int currentSourceIndex; if(colCount > 0) { cols = (DataGridColumn []) columns.ToArray (typeof (DataGridColumn)); foreach(DataGridColumn current in cols) { current.Initialize(); } deployTable = new DataGridTableInternal(); Controls.Add(deployTable); deployRows = deployTable.Rows; indexCounter = 0; currentSourceIndex = 0; dkField = DataKeyField; dsUse = (useDataSource) ? (dkField.Length > 0) : false; pgEnabled = pagedDataSource.IsPagingEnabled; editIndex = EditItemIndex; selIndex = SelectedIndex; if(pgEnabled) { currentSourceIndex = pagedDataSource.FirstIndexInPage; CreateItem(-1, -1, ListItemType.Pager, false, null, cols, deployRows, pagedDataSource); } itemCount = 0; CreateItem(-1, -1, ListItemType.Header, useDataSource, null, cols, deployRows, null); if(storedDataValid && storedDataFirst != null) { if(dsUse) { dataKeys.Add(DataBinder.GetPropertyValue(storedDataFirst, dkField)); } if (indexCounter == editIndex) { deployType = ListItemType.EditItem; } else if (indexCounter == selIndex) { deployType = ListItemType.SelectedItem; } else { deployType = ListItemType.Item; } itemsArrayList.Add(CreateItem(0, currentSourceIndex, deployType, useDataSource, storedDataFirst, cols, deployRows, null)); itemCount++; indexCounter++; currentSourceIndex++; storedDataValid = false; storedDataFirst = null; } while(pageSourceEnumerator.MoveNext()) { object current = pageSourceEnumerator.Current; if(dsUse) { dataKeys.Add(DataBinder.GetPropertyValue(current, dkField)); } if (indexCounter == editIndex) { deployType = ListItemType.EditItem; } else if (indexCounter == selIndex) { deployType = ListItemType.SelectedItem; } else if ((indexCounter % 2) == 1) { deployType = ListItemType.AlternatingItem; } else { deployType = ListItemType.Item; } itemsArrayList.Add(CreateItem(indexCounter, currentSourceIndex, deployType, useDataSource, current, cols, deployRows, null)); itemCount++; indexCounter++; currentSourceIndex++; } CreateItem(-1, -1, ListItemType.Footer, useDataSource, null, cols, deployRows, null); if(pgEnabled) { CreateItem(-1, -1, ListItemType.Pager, false, null, cols, deployRows, pagedDataSource); } } if(useDataSource) { if(pageSourceEnumerator != null) { ViewState["_!ItemCount"] = itemCount; if(pagedDataSource.IsPagingEnabled) { ViewState["PageCount"] = pagedDataSource.PageCount; ViewState["_!DataSource_ItemCount"] = pagedDataSource.DataSourceCount; } else { ViewState["PageCount"] = 1; ViewState["_!DataSource_ItemCount"] = itemCount; } } else { ViewState["_!ItemCount"] = -1; ViewState["_!DataSource_ItemCount"] = -1; ViewState["PageCount"] = 0; } } pagedDataSource = null; } private DataGridItem CreateItem(int itemIndex, int dsIndex, ListItemType type, bool bind, object item, DataGridColumn[] columns, TableRowCollection rows, PagedDataSource dataSrc) { DataGridItem retVal; DataGridItemEventArgs args; retVal = CreateItem(itemIndex, dsIndex, type); args = new DataGridItemEventArgs(retVal); if(type != ListItemType.Pager) { InitializeItem(retVal, columns); if(bind) { retVal.DataItem = item; } OnItemCreated(args); rows.Add(retVal); if(bind) { retVal.DataBind(); OnItemDataBound(args); retVal.DataItem = null; } } else { InitializePager(retVal, columns.Length, dataSrc); OnItemCreated(args); rows.Add(retVal); } return retVal; } protected virtual DataGridItem CreateItem(int itemIndex, int dataSourceIndex, ListItemType itemType) { return new DataGridItem(itemIndex, dataSourceIndex, itemType); } protected virtual void InitializeItem(DataGridItem item, DataGridColumn[] columns) { TableCellCollection cells = item.Cells; TableCell cCell; for(int i = 0; i < columns.Length; i++) { cCell = new TableCell(); columns[i].InitializeCell(cCell, i, item.ItemType); cells.Add(cCell); } } protected virtual void InitializePager(DataGridItem item, int columnSpan, PagedDataSource pagedDataSource) { TableCell toAdd = new TableCell(); toAdd.ColumnSpan = columnSpan; if(PagerStyle.Mode == PagerMode.NextPrev) { if(!pagedDataSource.IsFirstPage) { LinkButton link = new DataGridLinkButton(); link.Text = PagerStyle.PrevPageText; link.CommandName = "Page"; link.CommandArgument = "Prev"; link.CausesValidation = false; toAdd.Controls.Add(link); } else { Label label = new Label(); label.Text = PagerStyle.PrevPageText; toAdd.Controls.Add(label); } toAdd.Controls.Add(new LiteralControl(" ")); if (pagedDataSource.PageCount == 0) { Label label = new Label(); label.Text = PagerStyle.NextPageText; toAdd.Controls.Add(label); } else { if(!pagedDataSource.IsLastPage) { LinkButton link = new DataGridLinkButton(); link.Text = PagerStyle.NextPageText; link.CommandName = "Page"; link.CommandArgument = "Next"; link.CausesValidation = false; toAdd.Controls.Add(link); } else { Label label = new Label(); label.Text = PagerStyle.NextPageText; toAdd.Controls.Add(label); } } } else { int pageCount = pagedDataSource.PageCount; int currPage = pagedDataSource.CurrentPageIndex + 1; int btnCount = PagerStyle.PageButtonCount; int numberOfPages = btnCount; if(numberOfPages > pageCount) numberOfPages = pageCount; int firstPageNumber = 1; // 10 int lastPageNumber = numberOfPages; // 11 if(currPage > lastPageNumber) { firstPageNumber = (pagedDataSource.CurrentPageIndex / btnCount) * btnCount + 1; lastPageNumber = firstPageNumber + btnCount - 1; if(lastPageNumber > pageCount) lastPageNumber = pageCount; if((lastPageNumber - firstPageNumber + 1) < btnCount) firstPageNumber = Math.Max(1, lastPageNumber - btnCount + 1); } if(firstPageNumber != 1) { LinkButton toAddBtn = new DataGridLinkButton(); toAddBtn.Text = "..."; toAddBtn.CommandName = "Page"; toAddBtn.CommandArgument = (firstPageNumber - 1).ToString(NumberFormatInfo.InvariantInfo); toAddBtn.CausesValidation = false; toAdd.Controls.Add(toAddBtn); toAdd.Controls.Add(new LiteralControl(" ")); } if (lastPageNumber == 0) { Label cPageLabel = new Label(); cPageLabel.Text = "1"; toAdd.Controls.Add(cPageLabel); } else { for(int i = firstPageNumber; i <= lastPageNumber; i++) { string argText = i.ToString(NumberFormatInfo.InvariantInfo); if(i == currPage) { Label cPageLabel = new Label(); cPageLabel.Text = argText; toAdd.Controls.Add(cPageLabel); } else { LinkButton indexButton = new DataGridLinkButton(); indexButton.Text = argText; indexButton.CommandName = "Page"; indexButton.CommandArgument = argText; indexButton.CausesValidation = false; toAdd.Controls.Add(indexButton); } if(i < lastPageNumber) toAdd.Controls.Add(new LiteralControl(" ")); } } if(pageCount > lastPageNumber) { toAdd.Controls.Add(new LiteralControl(" ")); LinkButton contLink = new DataGridLinkButton(); contLink.Text = "..."; contLink.CommandName = "Page"; contLink.CommandArgument = (lastPageNumber + 1).ToString(NumberFormatInfo.InvariantInfo); contLink.CausesValidation = false; toAdd.Controls.Add(contLink); } } item.Cells.Add(toAdd); } private PagedDataSource CreatePagedDataSource() { PagedDataSource retVal; retVal = new PagedDataSource(); retVal.CurrentPageIndex = CurrentPageIndex; retVal.PageSize = PageSize; retVal.AllowPaging = AllowPaging; retVal.AllowCustomPaging = AllowCustomPaging; retVal.VirtualCount = VirtualItemCount; return retVal; } /// /// UnDocumented method /// protected virtual ArrayList CreateColumnSet(PagedDataSource source, bool useDataSource) { DataGridColumn[] cols = new DataGridColumn [Columns.Count]; Columns.CopyTo (cols, 0); ArrayList l_columns = new ArrayList (); foreach (DataGridColumn current in cols) l_columns.Add (current); if (AutoGenerateColumns) { ArrayList auto_columns = null; if (useDataSource) { auto_columns = AutoCreateColumns (source); autoGenColsArrayList = auto_columns; } else { auto_columns = autoGenColsArrayList; } if (auto_columns != null && auto_columns.Count > 0) l_columns.AddRange (auto_columns); } return l_columns; } /// /// Generates the columns when AutoGenerateColumns is true. /// This method is called by CreateColumnSet when dataSource /// is to be used and columns need to be generated automatically. /// private ArrayList AutoCreateColumns(PagedDataSource source) { if(source != null) { ArrayList retVal = new ArrayList(); PropertyDescriptorCollection props = source.GetItemProperties(new PropertyDescriptor[0]); Type prop_type; BoundColumn b_col; if(props == null) { object fitem = null; prop_type = null; PropertyInfo prop_item = source.DataSource.GetType().GetProperty("Item", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, null, new Type[] { typeof(int) }, null); if(prop_item != null) { prop_type = prop_item.PropertyType; } if(prop_type == null || prop_type == typeof(object)) { IEnumerator en = source.GetEnumerator(); if(en.MoveNext()) fitem = en.Current; if(fitem != null) { prop_type = fitem.GetType(); } StoreEnumerator(en, fitem); } if(fitem != null && fitem is ICustomTypeDescriptor) { props = TypeDescriptor.GetProperties(fitem); } else if(prop_type != null) { if(IsBindableType(prop_type)) { b_col = new BoundColumn(); ((IStateManager)b_col).TrackViewState(); b_col.HeaderText = "Item"; b_col.SortExpression = "Item"; b_col.DataField = BoundColumn.thisExpr; b_col.SetOwner(this); retVal.Add(b_col); } else { props = TypeDescriptor.GetProperties(prop_type); } } } if(props != null && props.Count > 0) { //IEnumerable p_en = props.GetEnumerator(); try { foreach(PropertyDescriptor current in props) { if(IsBindableType(current.PropertyType)) { b_col = new BoundColumn(); ((IStateManager)b_col).TrackViewState(); b_col.HeaderText = current.Name; b_col.SortExpression = current.Name; b_col.DataField = current.Name; b_col.ReadOnly = current.IsReadOnly; b_col.SetOwner(this); retVal.Add(b_col); } } } finally { if(props is IDisposable) ((IDisposable)props).Dispose(); } } if(retVal.Count > 0) { return retVal; } throw new HttpException(HttpRuntime.FormatResourceString("DataGrid_NoAutoGenColumns", ID)); } return null; } internal void StoreEnumerator(IEnumerator source, object firstItem) { storedData = source; storedDataFirst = firstItem; storedDataValid = true; } internal void OnColumnsChanged() { } internal void OnPagerChanged() { } } }