2 // System.Web.UI.WebControls.DataGrid.cs
5 // Jackson Harper (jackson@ximian.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 // (C) 2005 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Web.Util;
31 using System.Collections;
32 using System.Globalization;
33 using System.ComponentModel;
34 using System.Reflection;
35 using System.Security.Permissions;
37 namespace System.Web.UI.WebControls {
40 [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
41 [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
43 [Editor("System.Web.UI.Design.WebControls.DataGridComponentEditor, " + Consts.AssemblySystem_Design, typeof(System.ComponentModel.ComponentEditor))]
44 [Designer("System.Web.UI.Design.WebControls.DataGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45 public class DataGrid : BaseDataList, INamingContainer {
47 public const string CancelCommandName = "Cancel";
48 public const string DeleteCommandName = "Delete";
49 public const string EditCommandName = "Edit";
50 public const string SelectCommandName = "Select";
51 public const string SortCommandName = "Sort";
52 public const string UpdateCommandName = "Update";
54 public const string PageCommandName = "Page";
55 public const string NextPageCommandArgument = "Next";
56 public const string PrevPageCommandArgument = "Prev";
58 private static readonly object CancelCommandEvent = new object ();
59 private static readonly object DeleteCommandEvent = new object ();
60 private static readonly object EditCommandEvent = new object ();
61 private static readonly object ItemCommandEvent = new object ();
62 private static readonly object ItemCreatedEvent = new object ();
63 private static readonly object ItemDataBoundEvent = new object ();
64 private static readonly object PageIndexChangedEvent = new object ();
65 private static readonly object SortCommandEvent = new object ();
66 private static readonly object UpdateCommandEvent = new object ();
68 private TableItemStyle alt_item_style;
69 private TableItemStyle edit_item_style;
70 private TableItemStyle footer_style;
71 private TableItemStyle header_style;
72 private TableItemStyle item_style;
73 private TableItemStyle selected_style;
74 private DataGridPagerStyle pager_style;
76 private ArrayList items_list;
77 private DataGridItemCollection items;
79 private ArrayList columns_list;
80 private DataGridColumnCollection columns;
82 private ArrayList data_source_columns_list;
83 private DataGridColumnCollection data_source_columns;
85 private Table render_table;
86 private DataGridColumn [] render_columns;
87 private PagedDataSource paged_data_source;
88 private IEnumerator data_enumerator;
91 [WebSysDescription ("")]
92 [WebCategory ("Paging")]
93 public virtual bool AllowCustomPaging {
94 get { return ViewState.GetBool ("AllowCustomPaging", false); }
95 set { ViewState ["AllowCustomPaging"] = value; }
99 [WebSysDescription ("")]
100 [WebCategory ("Paging")]
101 public virtual bool AllowPaging {
102 get { return ViewState.GetBool ("AllowPaging", false); }
103 set { ViewState ["AllowPaging"] = value; }
106 [DefaultValue(false)]
107 [WebSysDescription ("")]
108 [WebCategory ("Behavior")]
109 public virtual bool AllowSorting {
110 get { return ViewState.GetBool ("AllowSorting", false); }
111 set { ViewState ["AllowSorting"] = value; }
115 [WebSysDescription ("")]
116 [WebCategory ("Behavior")]
117 public virtual bool AutoGenerateColumns {
118 get { return ViewState.GetBool ("AutoGenerateColumns", true); }
119 set { ViewState ["AutoGenerateColumns"] = value; }
128 [Editor("System.Web.UI.Design.ImageUrlEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
129 [WebSysDescription ("")]
130 [WebCategory ("Appearance")]
131 public virtual string BackImageUrl {
132 get { return TableStyle.BackImageUrl; }
133 set { TableStyle.BackImageUrl = value; }
140 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
141 [WebSysDescription ("")]
142 [WebCategory ("Behavior")]
143 public int CurrentPageIndex {
144 get { return ViewState.GetInt ("CurrentPageIndex", 0); }
147 throw new ArgumentOutOfRangeException ("value");
148 ViewState ["CurrentPageIndex"] = value;
153 [WebSysDescription ("")]
154 [WebCategory ("Misc")]
155 public virtual int EditItemIndex {
156 get { return ViewState.GetInt ("EditItemIndex", -1); }
159 throw new ArgumentOutOfRangeException ("value");
160 ViewState ["EditItemIndex"] = value;
165 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
166 [WebSysDescription ("")]
167 [WebCategory ("Style")]
168 public int PageCount {
170 if (paged_data_source != null)
171 return paged_data_source.PageCount;
173 return ViewState.GetInt ("PageCount", 0);
178 [WebSysDescription ("")]
179 [WebCategory ("Paging")]
180 public virtual int PageSize {
181 get { return ViewState.GetInt ("PageSize", 10); }
184 throw new ArgumentOutOfRangeException ("value");
185 ViewState ["PageSize"] = value;
189 void AdjustItemTypes (int prev_select, int new_select)
191 if (items_list == null)
192 return; // nothing to select
194 int count = items_list.Count;
196 return; // nothing to select
199 // Restore item type for the previously selected one.
200 if (prev_select >= 0 && prev_select < count) {
201 item = (DataGridItem) items_list [prev_select];
203 if (item.ItemType == ListItemType.EditItem) {
204 // nothing to do. This has priority.
205 } else if ((item.ItemIndex % 2) != 0) {
206 item.SetItemType (ListItemType.AlternatingItem);
208 item.SetItemType (ListItemType.Item);
212 if (new_select == -1 || new_select >= count)
213 return; // nothing to select
215 item = (DataGridItem) items_list [new_select];
216 if (item.ItemType != ListItemType.EditItem) // EditItem takes precedence
217 item.SetItemType (ListItemType.SelectedItem);
222 [WebSysDescription ("")]
223 [WebCategory ("Paging")]
224 public virtual int SelectedIndex {
225 get { return ViewState.GetInt ("SelectedIndex", -1); }
228 throw new ArgumentOutOfRangeException ("value");
230 int selected_index = ViewState.GetInt ("SelectedIndex", -1);
231 AdjustItemTypes (selected_index, value);
232 ViewState ["SelectedIndex"] = value;
236 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
237 [NotifyParentProperty(true)]
238 [PersistenceMode(PersistenceMode.InnerProperty)]
239 [WebSysDescription ("")]
240 [WebCategory ("Style")]
241 public virtual TableItemStyle AlternatingItemStyle {
243 if (alt_item_style == null) {
244 alt_item_style = new TableItemStyle ();
245 if (IsTrackingViewState)
246 alt_item_style.TrackViewState ();
248 return alt_item_style;
252 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
253 [NotifyParentProperty(true)]
254 [PersistenceMode(PersistenceMode.InnerProperty)]
255 [WebSysDescription ("")]
256 [WebCategory ("Style")]
257 public virtual TableItemStyle EditItemStyle {
259 if (edit_item_style == null) {
260 edit_item_style = new TableItemStyle ();
261 if (IsTrackingViewState)
262 edit_item_style.TrackViewState ();
264 return edit_item_style;
269 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
270 [NotifyParentProperty(true)]
271 [PersistenceMode(PersistenceMode.InnerProperty)]
272 [WebSysDescription ("")]
273 [WebCategory ("Style")]
274 public virtual TableItemStyle FooterStyle {
276 if (footer_style == null) {
277 footer_style = new TableItemStyle ();
278 if (IsTrackingViewState)
279 footer_style.TrackViewState ();
286 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
287 [NotifyParentProperty(true)]
288 [PersistenceMode(PersistenceMode.InnerProperty)]
289 [WebSysDescription ("")]
290 [WebCategory ("Style")]
291 public virtual TableItemStyle HeaderStyle {
293 if (header_style == null) {
294 header_style = new TableItemStyle ();
295 if (IsTrackingViewState)
296 header_style.TrackViewState ();
302 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
303 [NotifyParentProperty(true)]
304 [PersistenceMode(PersistenceMode.InnerProperty)]
305 [WebSysDescription ("")]
306 [WebCategory ("Style")]
307 public virtual TableItemStyle ItemStyle {
309 if (item_style == null) {
310 item_style = new TableItemStyle ();
311 if (IsTrackingViewState)
312 item_style.TrackViewState ();
318 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
319 [NotifyParentProperty(true)]
320 [PersistenceMode(PersistenceMode.InnerProperty)]
321 [WebSysDescription ("")]
322 [WebCategory ("Style")]
323 public virtual TableItemStyle SelectedItemStyle {
325 if (selected_style == null) {
326 selected_style = new TableItemStyle ();
327 if (IsTrackingViewState)
328 selected_style.TrackViewState ();
330 return selected_style;
334 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
335 [NotifyParentProperty(true)]
336 [PersistenceMode(PersistenceMode.InnerProperty)]
337 [WebSysDescription ("")]
338 [WebCategory ("Style")]
339 public virtual DataGridPagerStyle PagerStyle {
341 if (pager_style == null) {
342 pager_style = new DataGridPagerStyle ();
343 if (IsTrackingViewState)
344 pager_style.TrackViewState ();
351 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
352 [WebSysDescription ("")]
353 [WebCategory ("Style")]
354 public virtual DataGridItemCollection Items {
356 EnsureChildControls ();
358 if (items_list == null)
359 items_list = new ArrayList ();
360 items = new DataGridItemCollection (items_list);
366 [DefaultValue (null)]
367 [Editor ("System.Web.UI.Design.WebControls.DataGridColumnCollectionEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
368 [MergableProperty (false)]
369 [PersistenceMode (PersistenceMode.InnerProperty)]
370 [WebSysDescription ("")]
371 [WebCategory ("Behavior")]
372 public virtual DataGridColumnCollection Columns {
374 if (columns == null) {
375 columns_list = new ArrayList ();
376 columns = new DataGridColumnCollection (this, columns_list);
377 if (IsTrackingViewState) {
378 IStateManager manager = (IStateManager) columns;
379 manager.TrackViewState ();
386 private DataGridColumnCollection DataSourceColumns {
388 if (data_source_columns == null) {
389 data_source_columns_list = new ArrayList ();
390 data_source_columns = new DataGridColumnCollection (this,
391 data_source_columns_list);
392 if (IsTrackingViewState) {
393 IStateManager manager = (IStateManager) data_source_columns;
394 manager.TrackViewState ();
397 return data_source_columns;
401 class TableID : Table
405 public TableID (Control parent)
407 this.parent = parent;
410 protected override void AddAttributesToRender (HtmlTextWriter writer)
412 base.AddAttributesToRender (writer);
414 writer.AddAttribute ("id", parent.ClientID);
418 private Table RenderTable {
420 if (render_table == null) {
422 render_table = new TableID (this);
424 render_table = new ChildTable ();
426 render_table.AutoID = false;
433 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
434 [WebSysDescription ("")]
435 [WebCategory ("Paging")]
436 public virtual DataGridItem SelectedItem {
438 if (SelectedIndex == -1)
440 return Items [SelectedIndex];
447 [DefaultValue(false)]
448 [WebSysDescription ("")]
449 [WebCategory ("Appearance")]
450 public virtual bool ShowFooter {
451 get { return ViewState.GetBool ("ShowFooter", false); }
452 set { ViewState ["ShowFooter"] = value; }
459 [WebSysDescription ("")]
460 [WebCategory ("Appearance")]
461 public virtual bool ShowHeader {
462 get { return ViewState.GetBool ("ShowHeader", true); }
463 set { ViewState ["ShowHeader"] = value; }
467 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
468 [WebSysDescription ("")]
469 [WebCategory ("Appearance")]
470 public virtual int VirtualItemCount {
471 get { return ViewState.GetInt ("VirtualItemCount", 0); }
474 throw new ArgumentOutOfRangeException ("value");
475 ViewState ["VirtualItemCount"] = value;
480 protected override HtmlTextWriterTag TagKey {
481 get { return HtmlTextWriterTag.Table; }
485 private TableStyle TableStyle {
486 get { return (TableStyle) ControlStyle; }
489 static Type [] item_args = new Type [] {typeof (int) };
490 void AddColumnsFromSource (PagedDataSource data_source)
492 PropertyDescriptorCollection props = null;
494 bool no_items = false;
496 // Use plain reflection for the Item property.
497 // If we use TypeDescriptor, props will hold
498 // all of the Type properties, which will be listed as columns
499 Type ds_type = data_source.GetType ();
500 PropertyInfo pinfo = ds_type.GetProperty ("Item", item_args);
502 IEnumerator items = (data_source.DataSource != null) ? data_source.GetEnumerator () : null;
503 if (items != null && items.MoveNext ()) {
504 object data = items.Current;
505 if ((data is ICustomTypeDescriptor) || (!IsBindableType(data.GetType())))
506 props = TypeDescriptor.GetProperties (data);
507 else if (data != null)
508 ptype = data.GetType ();
509 data_enumerator = items;
514 ptype = pinfo.PropertyType;
518 // Found the "Item" property
519 AddPropertyToColumns ();
520 } else if (props != null) {
521 foreach (PropertyDescriptor pd in props)
522 AddPropertyToColumns (pd, false);
523 } else if (!no_items) {
524 // This is not thrown for an empty ArrayList.
525 string msg = String.Format ("DataGrid '{0}' cannot autogenerate " +
526 "columns from the given datasource. {1}", ID, ptype);
527 throw new HttpException (msg);
531 protected virtual ArrayList CreateColumnSet (PagedDataSource dataSource, bool useDataSource)
533 ArrayList res = new ArrayList ();
534 if (columns_list != null)
535 res.AddRange (columns_list);
537 if (AutoGenerateColumns) {
539 data_enumerator = null;
540 PropertyDescriptorCollection props = dataSource.GetItemProperties (null);
541 DataSourceColumns.Clear ();
543 foreach (PropertyDescriptor d in props)
544 AddPropertyToColumns (d, false);
546 AddColumnsFromSource (dataSource);
550 if (data_source_columns != null && data_source_columns.Count > 0)
551 res.AddRange (data_source_columns);
557 private void AddPropertyToColumns ()
559 BoundColumn b = new BoundColumn ();
560 if (IsTrackingViewState) {
561 IStateManager m = (IStateManager) b;
565 b.HeaderText = "Item";
566 b.SortExpression = "Item";
567 b.DataField = BoundColumn.thisExpr;
568 DataSourceColumns.Add (b);
571 private void AddPropertyToColumns (PropertyDescriptor prop, bool tothis)
573 BoundColumn b = new BoundColumn ();
575 if (IsTrackingViewState) {
576 IStateManager m = (IStateManager) b;
579 b.HeaderText = prop.Name;
580 b.DataField = (tothis ? BoundColumn.thisExpr : prop.Name);
581 b.SortExpression = prop.Name;
583 if (string.Compare (DataKeyField, b.DataField, StringComparison.InvariantCultureIgnoreCase) == 0) {
587 DataSourceColumns.Add (b);
590 protected override void TrackViewState ()
592 base.TrackViewState ();
594 if (pager_style != null)
595 pager_style.TrackViewState ();
596 if (header_style != null)
597 header_style.TrackViewState ();
598 if (footer_style != null)
599 footer_style.TrackViewState ();
600 if (item_style != null)
601 item_style.TrackViewState ();
602 if (alt_item_style != null)
603 alt_item_style.TrackViewState ();
604 if (selected_style != null)
605 selected_style.TrackViewState ();
606 if (edit_item_style != null)
607 edit_item_style.TrackViewState ();
609 if (ControlStyleCreated)
610 ControlStyle.TrackViewState ();
612 IStateManager manager = (IStateManager) columns;
614 manager.TrackViewState ();
617 protected override object SaveViewState ()
620 object [] res = new object [11];
622 object [] res = new object [10];
625 res [0] = base.SaveViewState ();
626 if (columns != null) {
627 IStateManager cm = (IStateManager) columns;
628 res [1] = cm.SaveViewState ();
630 if (pager_style != null)
631 res [2] = pager_style.SaveViewState ();
632 if (header_style != null)
633 res [3] = header_style.SaveViewState ();
634 if (footer_style != null)
635 res [4] = footer_style.SaveViewState ();
636 if (item_style != null)
637 res [5] = item_style.SaveViewState ();
638 if (alt_item_style != null)
639 res [6] = alt_item_style.SaveViewState ();
640 if (selected_style != null)
641 res [7] = selected_style.SaveViewState ();
642 if (edit_item_style != null)
643 res [8] = edit_item_style.SaveViewState ();
645 if (ControlStyleCreated)
646 res [9] = ControlStyle.SaveViewState ();
648 if (data_source_columns != null) {
649 IStateManager m = (IStateManager) data_source_columns;
650 res [10] = m.SaveViewState ();
653 if (data_source_columns != null) {
654 IStateManager m = (IStateManager) data_source_columns;
655 res [9] = m.SaveViewState ();
662 protected override void LoadViewState (object savedState)
664 object [] pieces = savedState as object [];
669 base.LoadViewState (pieces [0]);
670 if (columns != null) {
671 IStateManager cm = (IStateManager) columns;
672 cm.LoadViewState (pieces [1]);
674 if (pieces [2] != null)
675 PagerStyle.LoadViewState (pieces [2]);
676 if (pieces [3] != null)
677 HeaderStyle.LoadViewState (pieces [3]);
678 if (pieces [4] != null)
679 FooterStyle.LoadViewState (pieces [4]);
680 if (pieces [5] != null)
681 ItemStyle.LoadViewState (pieces [5]);
682 if (pieces [6] != null)
683 AlternatingItemStyle.LoadViewState (pieces [6]);
684 if (pieces [7] != null)
685 SelectedItemStyle.LoadViewState (pieces [7]);
686 if (pieces [8] != null)
687 EditItemStyle.LoadViewState (pieces [8]);
690 if (pieces [9] != null)
691 ControlStyle.LoadViewState (pieces [8]);
693 if (pieces [10] != null) {
694 // IStateManager manager = (IStateManager) DataSourceColumns;
695 // manager.LoadViewState (pieces [10]);
696 object [] cols = (object []) pieces [10];
697 foreach (object o in cols) {
698 BoundColumn c = new BoundColumn ();
699 ((IStateManager) c).TrackViewState ();
701 ((IStateManager) c).LoadViewState (o);
702 DataSourceColumns.Add (c);
706 if (pieces [9] != null) {
707 // IStateManager manager = (IStateManager) DataSourceColumns;
708 // manager.LoadViewState (pieces [9]);
709 object [] cols = (object []) pieces [9];
710 foreach (object o in cols) {
711 BoundColumn c = new BoundColumn ();
713 ((IStateManager) c).LoadViewState (o);
714 DataSourceColumns.Add (c);
720 protected override Style CreateControlStyle ()
723 TableStyle res = new TableStyle ();
725 TableStyle res = new TableStyle (ViewState);
727 res.GridLines = GridLines.Both;
732 protected virtual void InitializeItem (DataGridItem item, DataGridColumn [] columns)
734 bool th = UseAccessibleHeader && item.ItemType == ListItemType.Header;
735 for (int i = 0; i < columns.Length; i++) {
736 TableCell cell = null;
738 cell = new TableHeaderCell ();
739 cell.Attributes["scope"] = "col";
742 cell = new TableCell ();
743 columns [i].InitializeCell (cell, i, item.ItemType);
744 item.Cells.Add (cell);
748 protected virtual void InitializePager (DataGridItem item, int columnSpan, PagedDataSource pagedDataSource)
750 TableCell pager_cell;
751 if (PagerStyle.Mode == PagerMode.NextPrev)
752 pager_cell = InitializeNextPrevPager (item, columnSpan, pagedDataSource);
754 pager_cell = InitializeNumericPager (item, columnSpan, pagedDataSource);
756 item.Controls.Add (pager_cell);
759 private TableCell InitializeNumericPager (DataGridItem item, int columnSpan,
760 PagedDataSource paged)
762 TableCell res = new TableCell ();
763 res.ColumnSpan = columnSpan;
765 int button_count = PagerStyle.PageButtonCount;
766 int current = paged.CurrentPageIndex;
767 int start = current - (current % button_count);
768 int end = start + button_count;
770 if (end > paged.PageCount)
771 end = paged.PageCount;
774 LinkButton link = new LinkButton ();
776 link.CommandName = PageCommandName;
777 link.CommandArgument = start.ToString (CultureInfo.InvariantCulture);
778 link.CausesValidation = false;
779 res.Controls.Add (link);
780 res.Controls.Add (new LiteralControl (" "));
783 for (int i = start; i < end; i++) {
784 Control number = null;
785 string page = (i + 1).ToString (CultureInfo.InvariantCulture);
786 if (i != paged.CurrentPageIndex) {
787 LinkButton link = new LinkButton ();
789 link.CommandName = PageCommandName;
790 link.CommandArgument = page;
791 link.CausesValidation = false;
794 Label pageLabel = new Label();
795 pageLabel.Text = page;
799 res.Controls.Add (number);
801 res.Controls.Add (new LiteralControl (" "));
804 if (end < paged.PageCount) {
805 res.Controls.Add (new LiteralControl (" "));
806 LinkButton link = new LinkButton ();
808 link.CommandName = PageCommandName;
809 link.CommandArgument = (end + 1).ToString (CultureInfo.InvariantCulture);
810 link.CausesValidation = false;
811 res.Controls.Add (link);
817 private TableCell InitializeNextPrevPager (DataGridItem item, int columnSpan, PagedDataSource paged)
819 TableCell res = new TableCell ();
820 res.ColumnSpan = columnSpan;
825 if (paged.IsFirstPage) {
826 Label l = new Label ();
827 l.Text = PagerStyle.PrevPageText;
831 LinkButton l = new DataControlLinkButton ();
833 LinkButton l = new LinkButton ();
835 l.Text = PagerStyle.PrevPageText;
836 l.CommandName = PageCommandName;
837 l.CommandArgument = PrevPageCommandArgument;
838 l.CausesValidation = false;
842 if (paged.Count > 0 && !paged.IsLastPage) {
844 LinkButton l = new DataControlLinkButton ();
846 LinkButton l = new LinkButton ();
848 l.Text = PagerStyle.NextPageText;
849 l.CommandName = PageCommandName;
850 l.CommandArgument = NextPageCommandArgument;
851 l.CausesValidation = false;
854 Label l = new Label ();
855 l.Text = PagerStyle.NextPageText;
859 res.Controls.Add (prev);
860 res.Controls.Add (new LiteralControl (" "));
861 res.Controls.Add (next);
866 protected virtual DataGridItem CreateItem (int itemIndex, int dataSourceIndex,
867 ListItemType itemType)
869 DataGridItem res = new DataGridItem (itemIndex, dataSourceIndex, itemType);
873 private DataGridItem CreateItem (int item_index, int data_source_index,
874 ListItemType type, bool data_bind, object data_item,
875 PagedDataSource paged)
877 DataGridItem res = CreateItem (item_index, data_source_index, type);
878 DataGridItemEventArgs args = new DataGridItemEventArgs (res);
879 bool no_pager = (type != ListItemType.Pager);
882 InitializeItem (res, render_columns);
884 res.DataItem = data_item;
885 OnItemCreated (args);
887 InitializePager (res, render_columns.Length, paged);
888 if (pager_style != null)
889 res.ApplyStyle (pager_style);
890 OnItemCreated (args);
893 // Add before the column is bound, so that the
894 // value is saved in the viewstate
895 RenderTable.Controls.Add (res);
897 if (no_pager && data_bind) {
899 OnItemDataBound (args);
905 class NCollection : ICollection {
908 public NCollection (int n)
913 public IEnumerator GetEnumerator ()
915 for (int i = 0; i < n; i++)
923 public bool IsSynchronized {
924 get { return false; }
927 public object SyncRoot {
931 public void CopyTo (Array array, int index)
933 throw new NotImplementedException ("This should never be called");
937 protected override void CreateControlHierarchy (bool useDataSource)
940 RenderTable.Controls.Clear ();
941 Controls.Add (RenderTable);
943 IEnumerable data_source;
944 ArrayList keys = null;
947 if (IsBoundUsingDataSourceID)
948 data_source = GetData ();
951 data_source = DataSourceResolver.ResolveDataSource (DataSource, DataMember);
952 if (data_source == null) {
957 keys = DataKeysArray;
960 int nitems = ViewState.GetInt ("Items", 0);
961 data_source = new NCollection (nitems);
964 paged_data_source = new PagedDataSource ();
965 PagedDataSource pds = paged_data_source;
966 pds.AllowPaging = AllowPaging;
967 pds.AllowCustomPaging = AllowCustomPaging;
968 pds.DataSource = data_source;
969 pds.CurrentPageIndex = CurrentPageIndex;
970 pds.PageSize = PageSize;
971 pds.VirtualCount = VirtualItemCount;
973 if ((pds.IsPagingEnabled) && (pds.PageCount < pds.CurrentPageIndex)) {
975 throw new HttpException ("Invalid DataGrid PageIndex");
978 ArrayList cList = CreateColumnSet (paged_data_source, useDataSource);
979 if (cList.Count == 0) {
984 Page page = this.Page;
986 page.RequiresPostBackScript ();
988 render_columns = new DataGridColumn [cList.Count];
989 for (int c = 0; c < cList.Count; c++) {
990 DataGridColumn col = (DataGridColumn) cList [c];
991 col.Set_Owner (this);
993 render_columns [c] = col;
996 if (pds.IsPagingEnabled)
997 CreateItem (-1, -1, ListItemType.Pager, false, null, pds);
999 CreateItem (-1, -1, ListItemType.Header, useDataSource, null, pds);
1001 // No indexer on PagedDataSource so we have to do
1002 // this silly foreach and index++
1003 if (items_list == null)
1004 items_list = new ArrayList ();
1008 bool skip_first = false;
1009 IEnumerator enumerator = null;
1010 if (data_enumerator != null) {
1011 // replaced when creating bound columns
1012 enumerator = data_enumerator;
1014 } else if (pds.DataSource != null) {
1015 enumerator = pds.GetEnumerator ();
1023 int dataset_index = pds.FirstIndexInPage;
1024 int selected_index = SelectedIndex;
1025 int edit_item_index = EditItemIndex;
1026 while (enumerator != null && (skip_first || enumerator.MoveNext ())) {
1027 // MS does not render <table blah></table> on empty datasource.
1033 object data = enumerator.Current;
1034 // This will throw if the DataKeyField is not there. As on MS, this
1035 // will not be hit on an empty datasource.
1036 // The values stored here can be used in events so that you can
1037 // get, for example, the row that was clicked
1038 // (data.Rows.Find (ItemsGrid.DataKeys [e.Item.ItemIndex]))
1039 // BaseDataList will keep the array across postbacks.
1040 if (useDataSource && key != "")
1041 keys.Add (DataBinder.GetPropertyValue (data, key));
1043 ListItemType type = ListItemType.Item;
1044 if (index == edit_item_index)
1045 type = ListItemType.EditItem;
1046 else if (index == selected_index)
1047 type = ListItemType.SelectedItem;
1048 else if (index % 2 != 0)
1049 type = ListItemType.AlternatingItem;
1051 items_list.Add (CreateItem (index, dataset_index, type, useDataSource, data, pds));
1056 CreateItem (-1, -1, ListItemType.Footer, useDataSource, null, paged_data_source);
1057 if (pds.IsPagingEnabled) {
1058 CreateItem (-1, -1, ListItemType.Pager, false, null, paged_data_source);
1060 ViewState ["Items"] = pds.IsCustomPagingEnabled ? index : pds.DataSourceCount;
1061 } else if (useDataSource) {
1062 ViewState ["Items"] = index;
1066 void ApplyColumnStyle (TableCellCollection cells, ListItemType type)
1068 int ncells = Math.Min (cells.Count, render_columns.Length);
1072 for (int i = 0; i < ncells; i++) {
1074 TableCell cell = cells [i];
1075 DataGridColumn column = render_columns [i];
1076 if (!column.Visible) {
1077 cell.Visible = false;
1081 style = column.GetStyle (type);
1083 cell.MergeStyle (style);
1087 protected override void PrepareControlHierarchy ()
1089 if (!HasControls () || Controls.Count == 0)
1090 return; // No one called CreateControlHierarchy() with DataSource != null
1092 Table rt = render_table;
1093 rt.CopyBaseAttributes (this);
1094 rt.ApplyStyle (ControlStyle);
1096 rt.Caption = Caption;
1097 rt.CaptionAlign = CaptionAlign;
1098 rt.Enabled = Enabled;
1100 bool top_pager = true;
1101 foreach (DataGridItem item in rt.Rows) {
1103 switch (item.ItemType) {
1104 case ListItemType.Item:
1105 ApplyItemStyle (item);
1107 case ListItemType.AlternatingItem:
1108 ApplyItemStyle (item);
1110 case ListItemType.EditItem:
1111 item.MergeStyle (edit_item_style);
1112 ApplyItemStyle (item);
1113 ApplyColumnStyle (item.Cells, ListItemType.EditItem);
1115 case ListItemType.Footer:
1117 item.Visible = false;
1120 if (footer_style != null)
1121 item.MergeStyle (footer_style);
1122 ApplyColumnStyle (item.Cells, ListItemType.Footer);
1124 case ListItemType.Header:
1126 item.Visible = false;
1129 if (header_style != null)
1130 item.MergeStyle (header_style);
1131 ApplyColumnStyle (item.Cells, ListItemType.Header);
1133 case ListItemType.SelectedItem:
1134 item.MergeStyle (selected_style);
1135 ApplyItemStyle (item);
1136 ApplyColumnStyle (item.Cells, ListItemType.SelectedItem);
1138 case ListItemType.Separator:
1139 ApplyColumnStyle (item.Cells, ListItemType.Separator);
1141 case ListItemType.Pager:
1142 DataGridPagerStyle ps = PagerStyle;
1143 if (ps.Visible == false || !paged_data_source.IsPagingEnabled) {
1144 item.Visible = false;
1147 item.Visible = (ps.Position != PagerPosition.Bottom);
1149 item.Visible = (ps.Position != PagerPosition.Top);
1154 item.MergeStyle (pager_style);
1160 void ApplyItemStyle (DataGridItem item)
1162 if (item.ItemIndex % 2 != 0)
1163 item.MergeStyle (alt_item_style);
1165 item.MergeStyle (item_style);
1166 ApplyColumnStyle (item.Cells, ListItemType.Item);
1169 protected override bool OnBubbleEvent (object source, EventArgs e)
1171 DataGridCommandEventArgs de = e as DataGridCommandEventArgs;
1176 string cn = de.CommandName;
1177 CultureInfo inv = CultureInfo.InvariantCulture;
1180 if (String.Compare (cn, CancelCommandName, true, inv) == 0) {
1181 OnCancelCommand (de);
1182 } else if (String.Compare (cn, DeleteCommandName, true, inv) == 0) {
1183 OnDeleteCommand (de);
1184 } else if (String.Compare (cn, EditCommandName, true, inv) == 0) {
1186 } else if (String.Compare (cn, SelectCommandName, true, inv) == 0) {
1187 SelectedIndex = de.Item.ItemIndex;
1188 OnSelectedIndexChanged (de);
1189 } else if (String.Compare (cn, SortCommandName, true, inv) == 0) {
1190 DataGridSortCommandEventArgs se = new DataGridSortCommandEventArgs (de.CommandSource, de);
1192 } else if (String.Compare (cn, UpdateCommandName, true, inv) == 0) {
1193 OnUpdateCommand (de);
1194 } else if (String.Compare (cn, PageCommandName, true, inv) == 0) {
1196 if (String.Compare ((string) de.CommandArgument,
1197 NextPageCommandArgument, true, inv) == 0) {
1198 new_index = CurrentPageIndex + 1;
1199 } else if (String.Compare ((string) de.CommandArgument,
1200 PrevPageCommandArgument, true, inv) == 0) {
1201 new_index = CurrentPageIndex - 1;
1203 // It seems to just assume it's an int and parses, no
1204 // checks to make sure its valid or anything.
1205 // also it's always one less then specified, not sure
1207 new_index = Int32.Parse ((string) de.CommandArgument, inv) - 1;
1209 DataGridPageChangedEventArgs pc = new DataGridPageChangedEventArgs (
1210 de.CommandSource, new_index);
1211 OnPageIndexChanged (pc);
1217 protected virtual void OnCancelCommand (DataGridCommandEventArgs e)
1219 DataGridCommandEventHandler handler = (DataGridCommandEventHandler) Events [CancelCommandEvent];
1220 if (handler != null)
1224 protected virtual void OnDeleteCommand (DataGridCommandEventArgs e)
1226 DataGridCommandEventHandler handler = (DataGridCommandEventHandler) Events [DeleteCommandEvent];
1227 if (handler != null)
1231 protected virtual void OnEditCommand (DataGridCommandEventArgs e)
1233 DataGridCommandEventHandler handler = (DataGridCommandEventHandler) Events [EditCommandEvent];
1234 if (handler != null)
1238 protected virtual void OnItemCommand (DataGridCommandEventArgs e)
1240 DataGridCommandEventHandler handler = (DataGridCommandEventHandler) Events [ItemCommandEvent];
1241 if (handler != null)
1245 protected virtual void OnItemCreated (DataGridItemEventArgs e)
1247 DataGridItemEventHandler handler = (DataGridItemEventHandler) Events [ItemCreatedEvent];
1248 if (handler != null)
1252 protected virtual void OnItemDataBound (DataGridItemEventArgs e)
1254 DataGridItemEventHandler handler = (DataGridItemEventHandler) Events [ItemDataBoundEvent];
1255 if (handler != null)
1259 protected virtual void OnPageIndexChanged (DataGridPageChangedEventArgs e)
1261 DataGridPageChangedEventHandler handler = (DataGridPageChangedEventHandler) Events [PageIndexChangedEvent];
1262 if (handler != null)
1266 protected virtual void OnSortCommand (DataGridSortCommandEventArgs e)
1268 DataGridSortCommandEventHandler handler = (DataGridSortCommandEventHandler) Events [SortCommandEvent];
1269 if (handler != null)
1273 protected virtual void OnUpdateCommand (DataGridCommandEventArgs e)
1275 DataGridCommandEventHandler handler = (DataGridCommandEventHandler) Events [UpdateCommandEvent];
1276 if (handler != null)
1280 [WebSysDescription ("")]
1281 [WebCategory ("Action")]
1282 public event DataGridCommandEventHandler CancelCommand {
1283 add { Events.AddHandler (CancelCommandEvent, value); }
1284 remove { Events.RemoveHandler (CancelCommandEvent, value); }
1287 [WebSysDescription ("")]
1288 [WebCategory ("Action")]
1289 public event DataGridCommandEventHandler DeleteCommand {
1290 add { Events.AddHandler (DeleteCommandEvent, value); }
1291 remove { Events.RemoveHandler (DeleteCommandEvent, value); }
1294 [WebSysDescription ("")]
1295 [WebCategory ("Action")]
1296 public event DataGridCommandEventHandler EditCommand {
1297 add { Events.AddHandler (EditCommandEvent, value); }
1298 remove { Events.RemoveHandler (EditCommandEvent, value); }
1301 [WebSysDescription ("")]
1302 [WebCategory ("Action")]
1303 public event DataGridCommandEventHandler ItemCommand {
1304 add { Events.AddHandler (ItemCommandEvent, value); }
1305 remove { Events.RemoveHandler (ItemCommandEvent, value); }
1309 [WebSysDescription ("")]
1310 [WebCategory ("Action")]
1311 public event DataGridItemEventHandler ItemCreated {
1312 add { Events.AddHandler (ItemCreatedEvent, value); }
1313 remove { Events.RemoveHandler (ItemCreatedEvent, value); }
1316 [WebSysDescription ("")]
1317 [WebCategory ("Action")]
1318 public event DataGridItemEventHandler ItemDataBound {
1319 add { Events.AddHandler (ItemDataBoundEvent, value); }
1320 remove { Events.RemoveHandler (ItemDataBoundEvent, value); }
1323 [WebSysDescription ("")]
1324 [WebCategory ("Action")]
1325 public event DataGridPageChangedEventHandler PageIndexChanged {
1326 add { Events.AddHandler (PageIndexChangedEvent, value); }
1327 remove { Events.RemoveHandler (PageIndexChangedEvent, value); }
1330 [WebSysDescription ("")]
1331 [WebCategory ("Action")]
1332 public event DataGridSortCommandEventHandler SortCommand {
1333 add { Events.AddHandler (SortCommandEvent, value); }
1334 remove { Events.RemoveHandler (SortCommandEvent, value); }
1337 [WebSysDescription ("")]
1338 [WebCategory ("Action")]
1339 public event DataGridCommandEventHandler UpdateCommand {
1340 add { Events.AddHandler (UpdateCommandEvent, value); }
1341 remove { Events.AddHandler (UpdateCommandEvent, value); }