1 //------------------------------------------------------------------------------
2 // <copyright file="ObjectList.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
8 using System.Collections;
9 using System.ComponentModel;
11 using System.Diagnostics;
12 using System.Drawing.Design;
13 using System.Globalization;
16 using System.Web.UI.WebControls;
17 using System.Web.UI.HtmlControls;
18 using System.Security.Permissions;
20 namespace System.Web.UI.MobileControls
25 * Copyright (c) 2000 Microsoft Corporation
27 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList"]/*' />
29 ControlBuilderAttribute(typeof(ObjectListControlBuilder)),
30 DefaultEvent("ItemCommand"),
31 DefaultProperty("DataSource"),
32 Designer(typeof(System.Web.UI.Design.MobileControls.ObjectListDesigner)),
33 DesignerAdapter(typeof(System.Web.UI.Design.MobileControls.Adapters.DesignerObjectListAdapter)),
34 Editor(typeof(System.Web.UI.Design.MobileControls.ObjectListComponentEditor), typeof(ComponentEditor)),
35 ToolboxData("<{0}:ObjectList runat=\"server\" LabelStyle-StyleReference=\"title\" CommandStyle-StyleReference=\"subcommand\"></{0}:ObjectList>"),
36 ToolboxItem("System.Web.UI.Design.WebControlToolboxItem, " + AssemblyRef.SystemDesign)
38 [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
39 [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
40 [Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
41 public class ObjectList : PagedControl, INamingContainer, ITemplateable, IPostBackEventHandler
43 private static readonly Object EventItemDataBind = new Object();
44 private static readonly Object EventItemCommand = new Object();
45 private static readonly Object EventItemSelect = new Object();
46 private static readonly Object EventShowItemCommands = new Object();
48 private Object _dataSource;
49 private IEnumerable _resolvedDataSource;
50 private ObjectListFieldCollection _fields;
51 private ObjectListFieldCollection _autoGeneratedFields;
52 private ObjectListFieldCollection _allFields;
53 private ObjectListItemCollection _items;
54 private ObjectListCommandCollection _commands;
55 private ObjectListCommandCollection _globalCommands;
56 private int _labelFieldIndex = -1;
57 private int[] _tableFieldIndices = null;
58 private IEnumerator _storedEnumerator = null;
59 private Object _firstDataItem = null;
60 private bool _storedDataValid = false;
61 private ObjectListViewMode _viewMode = ObjectListViewMode.List;
62 private bool _ignoreFieldsItemsViewModeViewState = false;
63 private Style _commandStyle = null;
64 private Style _labelStyle = null;
65 private const string _itemCountViewStateKey = "_!ItemCount";
66 private int _selectedIndex = -1;
67 private bool _selectedIndexDirty = false;
68 private bool _loadingItems = false;
70 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SelectMoreCommand"]/*' />
71 public static String SelectMoreCommand
79 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DataSource"]/*' />
83 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
84 MobileCategory(SR.Category_Data),
85 MobileSysDescription(SR.ObjectList_DataSource)
87 public virtual Object DataSource
96 // _allFields and _resolvedDataSource need to be recalculated.
98 _resolvedDataSource = null;
102 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DataMember"]/*' />
106 MobileCategory(SR.Category_Data),
107 MobileSysDescription(SR.List_DataMember),
108 TypeConverter(typeof(System.Web.UI.Design.MobileControls.Converters.DataMemberConverter))
110 public virtual String DataMember
114 String s = (String)ViewState["DataMember"];
115 return s == null ? String.Empty : s;
119 ViewState["DataMember"] = value;
123 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Fields"]/*' />
127 Editor(typeof(System.Web.UI.Design.MobileControls.FieldCollectionEditor), typeof(UITypeEditor)),
128 MergableProperty(false),
129 MobileCategory(SR.Category_Data),
130 MobileSysDescription(SR.ObjectList_Fields),
131 PersistenceMode(PersistenceMode.InnerDefaultProperty)
133 public virtual ObjectListFieldCollection Fields
139 _fields = new ObjectListFieldCollection(this);
140 if (IsTrackingViewState)
142 ((IStateManager)_fields).TrackViewState();
149 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Items"]/*' />
153 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
155 public virtual ObjectListItemCollection Items
161 _items = new ObjectListItemCollection(this);
162 if (IsTrackingViewState)
164 ((IStateManager)_items).TrackViewState();
171 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Commands"]/*' />
174 Editor(typeof(System.Web.UI.Design.MobileControls.CommandCollectionEditor), typeof(UITypeEditor)),
175 MergableProperty(false),
176 MobileCategory(SR.Category_Data),
177 MobileSysDescription(SR.ObjectList_Commands),
178 PersistenceMode(PersistenceMode.InnerDefaultProperty)
180 public virtual ObjectListCommandCollection Commands
184 if (_commands == null)
186 _commands = new ObjectListCommandCollection();
187 if (IsTrackingViewState)
189 ((IStateManager)_commands).TrackViewState();
196 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LabelField"]/*' />
199 MobileCategory(SR.Category_Data),
200 MobileSysDescription(SR.ObjectList_LabelField),
201 TypeConverter(typeof(System.Web.UI.Design.MobileControls.Converters.DataFieldConverter))
203 public String LabelField
207 String s = (String)ViewState["LabelField"];
208 return (s != null) ? s : String.Empty;
212 ViewState["LabelField"] = value;
213 InvalidateDisplayFieldIndices();
217 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DefaultCommand"]/*' />
221 MobileCategory(SR.Category_Data),
222 MobileSysDescription(SR.ObjectList_DefaultCommand),
223 TypeConverter(typeof(System.Web.UI.Design.MobileControls.Converters.DefaultCommandConverter))
225 public String DefaultCommand
229 String s = (String)ViewState["DefaultCommand"];
230 return (s != null) ? s : String.Empty;
234 ViewState["DefaultCommand"] = value;
238 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.TableFields"]/*' />
242 Editor(typeof(System.Web.UI.Design.MobileControls.TableFieldsEditor),
243 typeof(UITypeEditor)),
244 MobileCategory(SR.Category_Data),
245 MobileSysDescription(SR.ObjectList_TableFields)
247 public String TableFields
251 String s = (String)ViewState["TableFields"];
252 return (s != null) ? s : String.Empty;
256 ViewState["TableFields"] = value;
257 InvalidateDisplayFieldIndices();
261 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SelectedIndex"]/*' />
265 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
267 public int SelectedIndex
271 return _selectedIndex;
275 if (value == -1 && ViewMode != ObjectListViewMode.List)
278 SR.GetString(SR.ObjectList_MustBeInListModeToClearSelectedIndex));
280 int itemCount = ItemCount > 0 ? ItemCount : Items.Count;
283 throw new ArgumentOutOfRangeException("SelectedIndex",
284 SR.GetString(SR.ObjectList_SelectedIndexTooSmall, value));
286 else if (itemCount > 0 && value >= itemCount)
288 throw new ArgumentOutOfRangeException("SelectedIndex",
289 SR.GetString(SR.ObjectList_SelectedIndexTooBig, value, itemCount));
291 // End of guard clauses.
293 _selectedIndexDirty = (value != _selectedIndex) && IsTrackingViewState;
294 DeselectItemIfLoaded(_selectedIndex);
295 SelectItemIfLoaded(value);
296 _selectedIndex = value;
300 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Selection"]/*' />
304 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
306 public ObjectListItem Selection
310 if (SelectedIndex == -1)
314 EnsureItemLoaded (SelectedIndex);
315 int selectedIndex = TranslateVirtualItemIndex(SelectedIndex);
316 if (selectedIndex >= 0 && selectedIndex < Items.Count)
318 Debug.Assert (Items[selectedIndex].Selected);
319 return Items[selectedIndex];
328 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.AutoGenerateFields"]/*' />
333 MobileCategory(SR.Category_Behavior),
334 MobileSysDescription(SR.ObjectList_AutoGenerateFields)
336 public bool AutoGenerateFields
340 Object b = ViewState["AutoGenerateFields"];
341 return (b != null) ? (bool)b : true;
345 if (value != AutoGenerateFields)
347 ViewState["AutoGenerateFields"] = value;
349 _autoGeneratedFields = null;
351 InvalidateDisplayFieldIndices();
356 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.AllFields"]/*' />
360 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
362 public IObjectListFieldCollection AllFields
366 if (_allFields == null)
368 if (_autoGeneratedFields == null)
376 _allFields = _fields;
383 _allFields = _autoGeneratedFields;
387 int count = _fields.Count + _autoGeneratedFields.Count;
389 ArrayList list = new ArrayList(count);
391 foreach (ObjectListField field in _fields)
396 foreach (ObjectListField field in _autoGeneratedFields)
401 _allFields = new ObjectListFieldCollection(this, list);
409 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LabelFieldIndex"]/*' />
413 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
415 public int LabelFieldIndex
419 if (_labelFieldIndex == -1)
421 CalculateDisplayFieldIndices();
423 return _labelFieldIndex;
427 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Details"]/*' />
431 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
437 EnsureChildControls();
438 if (ViewMode != ObjectListViewMode.Details)
440 throw new Exception(SR.GetString(SR.ObjectList_MustBeInDetailsModeToGetDetails));
446 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.TableFieldIndices"]/*' />
450 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
452 public int[] TableFieldIndices
456 if (_labelFieldIndex == -1)
458 CalculateDisplayFieldIndices();
460 Debug.Assert(_tableFieldIndices != null, "_tableFieldIndices is null.");
461 return _tableFieldIndices;
465 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.EnsureTemplatedUI"]/*' />
466 public override void EnsureTemplatedUI()
468 EnsureChildControls();
471 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.EnsureChildControls"]/*' />
472 protected override void EnsureChildControls()
474 // if EnsureChildControls is called before items are created (e.g., at
475 // LoadPrivateViewState), there will be no controls. Need to build child
476 // controls in this case, so we set ChildControlsCreated to false.
477 ChildControlsCreated = ChildControlsCreated && Controls.Count > 0;
478 base.EnsureChildControls();
481 private void CalculateDisplayFieldIndices()
483 String labelField = LabelField;
484 if (labelField.Length > 0)
486 _labelFieldIndex = GetFieldIndex(labelField);
490 _labelFieldIndex = 0;
493 String tableFields = TableFields;
494 int length = tableFields.Length;
496 // Populate the _tableFieldIndices array.
497 ArrayList tableFieldIndexList = new ArrayList();
498 for (int pos = 0; pos < length; )
500 int nextSemicolon = tableFields.IndexOf(';', pos);
501 String fieldName = (nextSemicolon == -1) ?
502 tableFields.Substring(pos) :
503 tableFields.Substring(pos, nextSemicolon - pos);
504 tableFieldIndexList.Add(GetFieldIndex(fieldName));
505 pos = nextSemicolon == -1 ? length : nextSemicolon + 1;
507 _tableFieldIndices = (int[])tableFieldIndexList.ToArray(typeof(int));
510 internal void InvalidateDisplayFieldIndices()
512 _labelFieldIndex = -1;
513 _tableFieldIndices = null;
516 private int GetFieldIndex(String field)
518 int index = AllFields.IndexOf(field);
521 throw new ArgumentException(SR.GetString(
522 SR.ObjectList_FieldNotFound, field));
527 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.AddParsedSubObject"]/*' />
528 protected override void AddParsedSubObject(Object obj)
530 if (!(obj is LiteralControl))
532 if (obj is ObjectListField)
534 Fields.Add((ObjectListField)obj);
536 else if (obj is ObjectListCommand)
538 Commands.Add((ObjectListCommand)obj);
542 base.AddParsedSubObject(obj);
547 private IEnumerable ResolvedDataSource
551 if (_resolvedDataSource == null)
553 _resolvedDataSource =
554 DataSourceHelper.GetResolvedDataSource(DataSource, DataMember);
556 return _resolvedDataSource;
560 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateChildControls"]/*' />
561 protected override void CreateChildControls()
564 if (ViewState[_itemCountViewStateKey] != null)
566 CreateChildControls(false);
570 private void CreateChildControls(bool doDataBind)
575 CreateTemplatedUI(doDataBind);
576 ChildControlsCreated = true;
580 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DataBind"]/*' />
581 public override void DataBind()
583 // Do our own databinding
584 OnDataBinding(EventArgs.Empty);
586 // Contained items will be databound after they have been created,
587 // so we don't want to walk the hierarchy here.
590 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnDataBinding"]/*' />
591 protected override void OnDataBinding(EventArgs e)
593 base.OnDataBinding(e);
595 if (ResolvedDataSource == null)
597 ClearItemsAndControls();
601 if (AutoGenerateFields)
603 CreateAutoGeneratedFields(ResolvedDataSource);
606 if ((AllFields == null || AllFields.Count == 0)
607 && MobilePage != null
608 && !MobilePage.DesignMode)
611 SR.GetString(SR.ObjectList_MustHaveOneOrMoreFields));
614 CreateItems(ResolvedDataSource);
618 // To clear the selected index, the ViewMode must be list.
619 ViewMode = ObjectListViewMode.List;
624 SelectItemIfLoaded(SelectedIndex);
627 CreateChildControls(true);
630 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateTemplatedItemsList"]/*' />
631 public void CreateTemplatedItemsList(bool doDataBind)
633 ObjectListItemCollection items = Items;
635 ITemplate headerTemplate = GetTemplate(Constants.HeaderTemplateTag);
636 ITemplate footerTemplate = GetTemplate(Constants.FooterTemplateTag);
637 ITemplate itemTemplate = GetTemplate(Constants.ItemTemplateTag);
638 ITemplate separatorTemplate = GetTemplate(Constants.SeparatorTemplateTag);
639 ITemplate alternatingItemTemplate = GetTemplate(Constants.AlternatingItemTemplateTag);
640 if (alternatingItemTemplate == null)
642 alternatingItemTemplate = itemTemplate;
645 CreateControlItem(MobileListItemType.HeaderItem, headerTemplate, doDataBind);
646 for (int i = 0; i < items.Count; i++)
650 CreateControlItem(MobileListItemType.SeparatorItem,
654 AddItemAsControl(i, items[i],
655 ((i & 1) == 1) ? alternatingItemTemplate : itemTemplate,
658 CreateControlItem(MobileListItemType.FooterItem, footerTemplate, doDataBind);
661 private void AddItemAsControl(
664 ITemplate itemTemplate,
667 if (itemTemplate != null)
669 // No need to do it again, since CreateItems already does it.
670 item.Controls.Clear();
673 CheckedInstantiateTemplate (itemTemplate, item, this);
681 private void CreateControlItem(
682 MobileListItemType itemType,
683 ITemplate itemTemplate,
686 if (itemTemplate != null)
688 MobileListItem item = new MobileListItem(itemType);
689 AddItemAsControl(-1, item, itemTemplate, doDataBind);
693 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateTemplatedItemDetails"]/*' />
694 public void CreateTemplatedItemDetails(bool doDataBind)
696 ITemplate detailsTemplate = GetTemplate(Constants.ItemDetailsTemplateTag);
697 Selection.Controls.Clear();
699 // Selection ID must be the same on each request. AUI 8007.
700 Selection.ID = "_ctl";
702 if (detailsTemplate != null)
704 if (!Controls.Contains (Selection))
706 Controls.Add (Selection);
708 CheckedInstantiateTemplate (detailsTemplate, Selection, this);
711 Selection.DataBind();
716 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateItems"]/*' />
717 protected virtual void CreateItems(IEnumerable dataSource)
719 Debug.Assert (dataSource != null, "dataSource is null");
724 IEnumerator enumerator;
726 if(_storedDataValid && _firstDataItem != null)
728 enumerator = _storedEnumerator;
729 ObjectListItem item = CreateItem(_firstDataItem);
730 item.SetIndex(count + Items.BaseIndex);
733 _storedDataValid = false;
734 _firstDataItem = null;
735 _storedEnumerator = null;
739 enumerator = dataSource.GetEnumerator();
742 while(enumerator.MoveNext())
744 Object dataItem = enumerator.Current;
745 ObjectListItem item = CreateItem(dataItem);
746 item.SetIndex(count + Items.BaseIndex);
752 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateItem"]/*' />
753 protected virtual ObjectListItem CreateItem(Object dataItem)
755 ObjectListItem item = new ObjectListItem(this, dataItem);
759 IObjectListFieldCollection allFields = AllFields;
761 foreach (ObjectListField field in AllFields)
763 field.DataBindItem(fieldIndex, item);
767 // Use delegated data binding, if specified.
769 if (dataItem != null)
771 OnItemDataBind(new ObjectListDataBindEventArgs(item, dataItem));
777 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnPreRender"]/*' />
778 protected override void OnPreRender(EventArgs e)
784 int firstVisibleItem = FirstVisibleItemIndex;
785 int pageSize = VisibleItemCount;
786 int lastVisibleItem = firstVisibleItem + pageSize - 1;
788 int separatorIndex = 0;
789 foreach(Control ctl in Controls)
791 MobileListItem item = ctl as MobileListItem;
794 if (item.ItemType == MobileListItemType.ListItem)
796 item.Visible = itemIndex >= firstVisibleItem && itemIndex <= lastVisibleItem;
799 else if (item.ItemType == MobileListItemType.SeparatorItem)
801 item.Visible = separatorIndex >= firstVisibleItem &&
802 separatorIndex < lastVisibleItem;
810 /////////////////////////////////////////////////////////////////////////
811 // FIELD AUTO-GENERATION
812 /////////////////////////////////////////////////////////////////////////
814 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateAutoGeneratedFields"]/*' />
815 protected void CreateAutoGeneratedFields(IEnumerable dataSource)
817 if (dataSource == null)
822 ArrayList list = new ArrayList();
823 PropertyDescriptorCollection propertyDescriptors = null;
825 if (dataSource is ITypedList)
827 propertyDescriptors =
828 ((ITypedList)dataSource).GetItemProperties(new PropertyDescriptor[0]);
831 if (propertyDescriptors == null)
833 IEnumerator enumerator = dataSource.GetEnumerator();
834 if (enumerator.MoveNext())
836 Object sampleItem = enumerator.Current;
837 StoreEnumerator(enumerator, sampleItem);
838 if (IsBindableType(sampleItem.GetType()))
840 list.Add(CreateAutoGeneratedField(
841 SR.GetString(SR.ObjectList_ItemTitle),
846 propertyDescriptors = TypeDescriptor.GetProperties(sampleItem);
851 if (propertyDescriptors != null && propertyDescriptors.Count > 0)
853 foreach (PropertyDescriptor pd in propertyDescriptors)
855 if (IsBindableType(pd.PropertyType))
858 ObjectListTitleAttribute attr =
859 (ObjectListTitleAttribute)pd.Attributes[typeof(ObjectListTitleAttribute)];
868 list.Add(CreateAutoGeneratedField(title, pd.Name));
873 _autoGeneratedFields = new ObjectListFieldCollection(this, list);
876 /// Caches the fact that we have already consumed the first item from the enumeration
877 /// and must use it first during our item creation.
878 internal void StoreEnumerator(IEnumerator enumerator, object firstDataItem)
880 _storedEnumerator = enumerator;
881 _firstDataItem = firstDataItem;
882 _storedDataValid = true;
885 private bool IsBindableType(Type type)
887 return(type.IsPrimitive ||
888 (type == typeof(String)) ||
889 (type == typeof(DateTime)) ||
890 (type == typeof(Decimal)));
893 private ObjectListField CreateAutoGeneratedField(String title, String dataField)
895 ObjectListField field = new ObjectListField();
896 ((IStateManager)field).TrackViewState();
898 if (dataField != null)
900 field.DataField = dataField;
904 field.SelfReference = true;
909 Object SaveAutoFieldsState()
911 int autoGeneratedCount = (_autoGeneratedFields != null) ? _autoGeneratedFields.Count : 0;
912 if (autoGeneratedCount != 0)
914 Object[] fieldStates = new Object[autoGeneratedCount];
915 for (int i = 0; i < autoGeneratedCount; i++)
917 fieldStates[i] = ((IStateManager)_autoGeneratedFields[i]).SaveViewState();
927 void LoadAutoFieldsState(Object state)
931 Object[] fieldStates = (Object[])state;
932 int count = fieldStates.Length;
933 ArrayList list = new ArrayList(count);
934 foreach (Object fieldState in fieldStates)
936 ObjectListField field = new ObjectListField();
937 ((IStateManager)field).TrackViewState();
938 ((IStateManager)field).LoadViewState (fieldState);
941 _autoGeneratedFields = new ObjectListFieldCollection(this, list);
945 internal void OnFieldChanged(bool fieldAddedOrRemoved)
947 // Called when a field is added, removed, etc.
948 if (IsTrackingViewState)
951 // avoid view state being out of sync with fields.
952 _ignoreFieldsItemsViewModeViewState = true;
953 if (fieldAddedOrRemoved)
957 InvalidateDisplayFieldIndices();
961 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.InternalItemCount"]/*' />
962 protected override int InternalItemCount
966 if (_items != null && Items.Count > 0)
978 /////////////////////////////////////////////////////////////////////////
980 /////////////////////////////////////////////////////////////////////////
982 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ItemDataBind"]/*' />
984 MobileCategory(SR.Category_Action),
985 MobileSysDescription(SR.ObjectList_OnItemDataBind)
987 public event ObjectListDataBindEventHandler ItemDataBind
991 Events.AddHandler(EventItemDataBind, value);
995 Events.RemoveHandler(EventItemDataBind, value);
999 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnItemDataBind"]/*' />
1000 protected virtual void OnItemDataBind(ObjectListDataBindEventArgs e)
1002 ObjectListDataBindEventHandler onItemDataBindHandler =
1003 (ObjectListDataBindEventHandler)Events[EventItemDataBind];
1004 if (onItemDataBindHandler != null)
1006 onItemDataBindHandler(this, e);
1010 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ItemCommand"]/*' />
1012 MobileCategory(SR.Category_Action),
1013 MobileSysDescription(SR.ObjectList_OnItemCommand)
1015 public event ObjectListCommandEventHandler ItemCommand
1019 Events.AddHandler(EventItemCommand, value);
1023 Events.RemoveHandler(EventItemCommand, value);
1027 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnItemCommand"]/*' />
1028 protected virtual void OnItemCommand(ObjectListCommandEventArgs e)
1030 ObjectListCommandEventHandler onItemCommandHandler = (ObjectListCommandEventHandler)Events[EventItemCommand];
1031 if (onItemCommandHandler != null)
1033 onItemCommandHandler(this, e);
1037 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ItemSelect"]/*' />
1039 MobileCategory(SR.Category_Action),
1040 MobileSysDescription(SR.ObjectList_OnItemSelect)
1042 public event ObjectListSelectEventHandler ItemSelect
1046 Events.AddHandler(EventItemSelect, value);
1050 Events.RemoveHandler(EventItemSelect, value);
1054 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnItemSelect"]/*' />
1055 protected virtual void OnItemSelect(ObjectListSelectEventArgs e)
1057 ObjectListSelectEventHandler onItemSelectHandler = (ObjectListSelectEventHandler)Events[EventItemSelect];
1058 if (onItemSelectHandler != null)
1060 onItemSelectHandler(this, e);
1064 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.HasItemCommandHandler"]/*' />
1068 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1070 public bool HasItemCommandHandler
1074 return Events[EventItemCommand] != null;
1078 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ShowItemCommands"]/*' />
1080 MobileCategory(SR.Category_Action),
1081 MobileSysDescription(SR.ObjectList_OnShowItemCommands)
1083 public event ObjectListShowCommandsEventHandler ShowItemCommands
1087 Events.AddHandler(EventShowItemCommands, value);
1091 Events.RemoveHandler(EventShowItemCommands, value);
1095 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnShowItemCommands"]/*' />
1096 protected virtual void OnShowItemCommands(ObjectListShowCommandsEventArgs e)
1098 ObjectListShowCommandsEventHandler onShowItemCommandsHandler
1099 = (ObjectListShowCommandsEventHandler)Events[EventShowItemCommands];
1100 if (onShowItemCommandsHandler != null)
1102 onShowItemCommandsHandler(this, e);
1106 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnBubbleEvent"]/*' />
1107 protected override bool OnBubbleEvent(Object sender, EventArgs e)
1109 bool handled = false;
1111 if (e is CommandEventArgs)
1113 if (e is ObjectListCommandEventArgs)
1115 OnItemCommand((ObjectListCommandEventArgs)e);
1124 protected void RaisePostBackEvent(String eventArgument)
1126 if (!Adapter.HandlePostBackEvent(eventArgument))
1128 OnItemCommand(new ObjectListCommandEventArgs(Selection, eventArgument));
1132 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.RaiseDefaultItemEvent"]/*' />
1133 public void RaiseDefaultItemEvent(int itemIndex)
1135 EnsureItemLoaded (itemIndex);
1136 int itemCollIndex = TranslateVirtualItemIndex(itemIndex);
1137 SelectedIndex = itemIndex;
1138 OnItemCommand(new ObjectListCommandEventArgs(Items[itemCollIndex], DefaultCommand));
1141 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SelectListItem"]/*' />
1142 public bool SelectListItem(int itemIndex, bool selectMore)
1144 EnsureItemLoaded (itemIndex);
1145 int itemCollIndex = TranslateVirtualItemIndex(itemIndex);
1147 ObjectListSelectEventArgs args = new ObjectListSelectEventArgs(
1148 Items[itemCollIndex],
1150 SelectedIndex = itemIndex;
1152 return args.UseDefaultHandling;
1155 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.PreShowItemCommands"]/*' />
1156 public void PreShowItemCommands(int itemIndex)
1158 // Called just before commands are shown for a given item. We call
1159 // an event handler that can modify (or even replace) the commands collection,
1160 // but first we mark the collection, and save it off, so that we can
1161 // save the state of the collection at this point.
1163 if (_commands != null)
1165 _globalCommands = _commands;
1166 _commands.GlobalStateSet();
1169 SelectedIndex = itemIndex;
1171 ObjectListShowCommandsEventArgs eventArgs =
1172 new ObjectListShowCommandsEventArgs(Selection, Commands);
1173 OnShowItemCommands(eventArgs);
1174 if (eventArgs.Commands != _commands)
1176 _commands = eventArgs.Commands;
1180 private void EnsureItemLoaded(int virtualIndex)
1182 Debug.Assert (virtualIndex >= 0, "virtualIndex < 0");
1183 if (ItemCount > 0 &&
1185 virtualIndex < Items.BaseIndex ||
1186 Items.Count <= virtualIndex - Items.BaseIndex))
1188 OnLoadItems(new LoadItemsEventArgs(virtualIndex, 1));
1192 private int TranslateVirtualItemIndex(int virtualIndex)
1194 Debug.Assert(ItemCount > 0 || Items.BaseIndex == 0);
1196 // Translate virtual index to true index within collection.
1197 // If custom pagination is off, virtual index is the true index.
1198 return virtualIndex - Items.BaseIndex;
1201 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnLoadItems"]/*' />
1202 protected override void OnLoadItems(LoadItemsEventArgs e)
1204 // We should only load items if the base index has changed, or if
1205 // the desired items do not exist in the list. Otherwise, we are making
1206 // the app reload the same items over and over.
1208 if (e.ItemIndex != Items.BaseIndex || e.ItemCount != Items.Count)
1210 _loadingItems = true;
1211 Items.BaseIndex = e.ItemIndex;
1213 base.OnLoadItems(e);
1214 _loadingItems = false;
1218 /////////////////////////////////////////////////////////////////////////
1220 /////////////////////////////////////////////////////////////////////////
1222 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.TrackViewState"]/*' />
1223 protected override void TrackViewState()
1225 base.TrackViewState();
1226 if (_fields != null)
1228 ((IStateManager)_fields).TrackViewState();
1230 if (_commands != null)
1232 ((IStateManager)_commands).TrackViewState();
1236 ((IStateManager)_items).TrackViewState();
1240 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SavePrivateViewState"]/*' />
1241 protected override Object SavePrivateViewState()
1243 Object baseState = base.SavePrivateViewState();
1244 if (ViewMode != ObjectListViewMode.List || _selectedIndexDirty)
1246 return new Triplet(baseState, (int) ViewMode, SelectedIndex);
1248 else if (baseState != null)
1255 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LoadPrivateViewState"]/*' />
1256 protected override void LoadPrivateViewState(Object state)
1260 Triplet stateTriplet = state as Triplet;
1261 if (stateTriplet != null)
1263 base.LoadPrivateViewState (stateTriplet.First);
1264 ObjectListViewMode originalViewMode = _viewMode;
1266 // use private field because property get calls CreateChildControls.
1267 _viewMode = (ObjectListViewMode) stateTriplet.Second;
1269 // use property to insure we load items if necessary and set selected index dirty.
1270 SelectedIndex = (int)stateTriplet.Third;
1272 bool viewModeChanged = (originalViewMode != _viewMode);
1273 if (ChildControlsCreated && viewModeChanged)
1275 // This is before items loaded in LVS, so we only do this if
1276 // child controls already created in init (e.g., no VS.)
1277 CreateChildControls (true);
1282 base.LoadPrivateViewState(state);
1287 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SaveViewState"]/*' />
1288 protected override Object SaveViewState()
1290 Object baseState, fieldsState, autoFieldsState, commandsState, itemsState;
1292 Debug.Assert (Items != null, "get_Items should initialize Items collection.");
1293 int count = Items.Count;
1294 // HasControls implies DataBound on this or a prev req (but not converse).
1295 if (count > 0 || HasControls())
1297 ViewState[_itemCountViewStateKey] = count;
1299 baseState = base.SaveViewState();
1300 fieldsState = (_fields != null) ? ((IStateManager)_fields).SaveViewState() : null;
1301 autoFieldsState = SaveAutoFieldsState();
1302 commandsState = (_commands != null) ? ((IStateManager)_commands).SaveViewState() : null;
1303 itemsState = (_items != null) ? ((IStateManager)_items).SaveViewState() : null;
1305 if (itemsState != null ||
1306 fieldsState != null ||
1307 autoFieldsState != null ||
1308 commandsState != null )
1310 return new Object[5]
1319 else if (baseState != null)
1321 return new Object[1] { baseState };
1326 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LoadViewState"]/*' />
1327 protected override void LoadViewState(Object savedState)
1329 // copy locally (can change during Fields.LVS).
1330 bool ignoreFieldsItemsViewModeViewState = _ignoreFieldsItemsViewModeViewState;
1331 if (savedState != null)
1333 Object[] state = (Object[])savedState;
1334 base.LoadViewState(state[0]);
1336 if (state.Length > 1)
1338 // Always load items after loading fields, because field changes can wipe out
1340 if(!ignoreFieldsItemsViewModeViewState)
1342 ((IStateManager)Fields).LoadViewState(state[1]);
1343 LoadAutoFieldsState(state[2]);
1345 ((IStateManager)Commands).LoadViewState(state[3]);
1346 if(!ignoreFieldsItemsViewModeViewState)
1348 ((IStateManager)Items).LoadViewState(state[4]);
1349 SelectItemIfLoaded(SelectedIndex);
1355 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ViewMode"]/*' />
1359 DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1361 public ObjectListViewMode ViewMode
1369 if (SelectedIndex == -1 && value != ObjectListViewMode.List)
1371 throw new Exception(SR.GetString(
1372 SR.ObjectList_CannotSetViewModeWithNoSelectedItem));
1374 if (value == ObjectListViewMode.List)
1376 // Set pagination state changed to refresh pagination.
1377 Form.PaginationStateChanged = true;
1380 CreateChildControls(true);
1384 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DetailsCommandText"]/*' />
1389 MobileCategory(SR.Category_Appearance),
1390 MobileSysDescription(SR.ObjectList_DetailsCommandText),
1392 public String DetailsCommandText
1396 String detailsCommandText = (String)ViewState["DetailsCommandText"];
1397 return detailsCommandText != null ? detailsCommandText : String.Empty;
1401 ViewState["DetailsCommandText"] = value;
1405 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.BackCommandText"]/*' />
1410 MobileCategory(SR.Category_Appearance),
1411 MobileSysDescription(SR.ObjectList_BackCommandText),
1413 public String BackCommandText
1417 String backCommandText = (String) ViewState["BackCommandText"];
1418 return backCommandText != null ? backCommandText : String.Empty;
1422 ViewState["BackCommandText"] = value;
1426 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.MoreText"]/*' />
1431 MobileCategory(SR.Category_Appearance),
1432 MobileSysDescription(SR.ObjectList_MoreText)
1434 public String MoreText
1438 String moreText = (String)ViewState["MoreText"];
1439 return moreText != null ? moreText : String.Empty;
1443 ViewState["MoreText"] = value;
1447 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CommandStyle"]/*' />
1449 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
1450 MobileCategory(SR.Category_Style),
1451 MobileSysDescription(SR.ObjectList_CommandStyle),
1452 NotifyParentProperty(true)
1454 public Style CommandStyle
1458 if (_commandStyle == null)
1460 _commandStyle = new Style();
1461 _commandStyle.SetControl(this);
1462 _commandStyle.StyleReference = "subcommand";
1464 return _commandStyle;
1468 _commandStyle = value;
1472 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LabelStyle"]/*' />
1475 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
1476 MobileCategory(SR.Category_Style),
1477 MobileSysDescription(SR.ObjectList_LabelStyle),
1478 NotifyParentProperty(true)
1480 public Style LabelStyle
1484 if (_labelStyle == null)
1486 _labelStyle = new Style();
1487 _labelStyle.SetControl(this);
1488 _labelStyle.StyleReference = "title";
1494 _labelStyle = value;
1498 internal override void InvalidateParentStyles()
1500 if (_commandStyle != null)
1502 _commandStyle.InvalidateParentStyle();
1504 if (_labelStyle != null)
1506 _labelStyle.InvalidateParentStyle();
1508 base.InvalidateParentStyles();
1511 internal override void InternalItemCountChangedHandler(int newItemCount)
1513 if (newItemCount == 0)
1515 ClearItemsAndControls();
1519 private void ClearItemsAndControls()
1521 ViewMode = ObjectListViewMode.List;
1527 // Wrapper to increase intelligibility at point of call.
1528 private void SelectItemIfLoaded(int virtualIndex)
1530 SetItemSelectedPropertyIfItemLoaded(virtualIndex, true);
1533 // Wrapper to increase intelligibility at point of call.
1534 private void DeselectItemIfLoaded(int virtualIndex)
1536 SetItemSelectedPropertyIfItemLoaded(virtualIndex, false);
1539 private void SetItemSelectedPropertyIfItemLoaded(int virtualIndex, bool newValue)
1541 if (virtualIndex < 0)
1545 int physicalIndex = TranslateVirtualItemIndex(virtualIndex);
1546 if (physicalIndex >= 0 && physicalIndex < Items.Count)
1548 Items[physicalIndex].Selected = newValue;
1552 #region IPostBackEventHandler implementation
1553 void IPostBackEventHandler.RaisePostBackEvent(String eventArgument) {
1554 RaisePostBackEvent(eventArgument);
1561 * Control builder for object lists.
1563 * Copyright (c) 2000 Microsoft Corporation
1566 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectListControlBuilder"]/*' />
1567 [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
1568 [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
1569 [Obsolete("The System.Web.Mobile.dll assembly has been deprecated and should no longer be used. For information about how to develop ASP.NET mobile applications, see http://go.microsoft.com/fwlink/?LinkId=157231.")]
1570 public class ObjectListControlBuilder : MobileControlBuilder
1572 /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectListControlBuilder.GetChildControlType"]/*' />
1573 public override Type GetChildControlType(String tagName, IDictionary attributes)
1575 if (String.Compare(tagName, "Field", StringComparison.OrdinalIgnoreCase) == 0)
1577 return typeof(ObjectListField);
1579 else if (String.Compare(tagName, "Command", StringComparison.OrdinalIgnoreCase) == 0)
1581 return typeof(ObjectListCommand);
1585 return base.GetChildControlType(tagName, attributes);