Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Web.Mobile / UI / MobileControls / ObjectList.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="ObjectList.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 using System;
8 using System.Collections;
9 using System.ComponentModel;
10 using System.Data;
11 using System.Diagnostics;
12 using System.Drawing.Design;
13 using System.Globalization;
14 using System.Web;
15 using System.Web.UI;
16 using System.Web.UI.WebControls;
17 using System.Web.UI.HtmlControls;
18 using System.Security.Permissions;
19
20 namespace System.Web.UI.MobileControls
21 {
22     /*
23      * Object List class.
24      *
25      * Copyright (c) 2000 Microsoft Corporation
26      */
27     /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList"]/*' />
28     [
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)
37     ]
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
42     {
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();
47
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;
69
70         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SelectMoreCommand"]/*' />
71         public static String SelectMoreCommand
72         {
73             get
74             {
75                 return "More";
76             }
77         }
78
79         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DataSource"]/*' />
80         [
81             Bindable(true),
82             DefaultValue(null),
83             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
84             MobileCategory(SR.Category_Data),
85             MobileSysDescription(SR.ObjectList_DataSource)
86         ]
87         public virtual Object DataSource 
88         {
89             get 
90             {
91                 return _dataSource;
92             }
93             set 
94             {
95                 _dataSource = value;
96                 // _allFields and _resolvedDataSource need to be recalculated.  
97                 _allFields = null;
98                 _resolvedDataSource = null;
99             }
100         }
101
102         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DataMember"]/*' />
103         [
104             Bindable(false),
105             DefaultValue(""),
106             MobileCategory(SR.Category_Data),
107             MobileSysDescription(SR.List_DataMember),
108             TypeConverter(typeof(System.Web.UI.Design.MobileControls.Converters.DataMemberConverter))
109         ]
110         public virtual String DataMember
111         {
112             get 
113             {
114                 String s = (String)ViewState["DataMember"];
115                 return s == null ? String.Empty : s;
116             }
117             set 
118             {
119                 ViewState["DataMember"] = value;
120             }
121         }
122
123         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Fields"]/*' />
124         [
125             Bindable(false),
126             DefaultValue(null),
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)
132         ]
133         public virtual ObjectListFieldCollection Fields
134         {
135             get
136             {
137                 if (_fields == null)
138                 {
139                     _fields = new ObjectListFieldCollection(this);
140                     if (IsTrackingViewState)
141                     {
142                         ((IStateManager)_fields).TrackViewState();
143                     }
144                 }
145                 return _fields;
146             }
147         }
148
149         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Items"]/*' />
150         [
151             Bindable(true),
152             Browsable(false),
153             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
154         ]
155         public virtual ObjectListItemCollection Items
156         {
157             get
158             {
159                 if (_items == null)
160                 {
161                     _items = new ObjectListItemCollection(this);
162                     if (IsTrackingViewState)
163                     {
164                         ((IStateManager)_items).TrackViewState();
165                     }
166                 }
167                 return _items;
168             }
169         }
170
171         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Commands"]/*' />
172         [
173             Bindable(false),
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)
179         ]
180         public virtual ObjectListCommandCollection Commands
181         {
182             get
183             {
184                 if (_commands == null)
185                 {
186                     _commands = new ObjectListCommandCollection();
187                     if (IsTrackingViewState)
188                     {
189                         ((IStateManager)_commands).TrackViewState();
190                     }
191                 }
192                 return _commands;
193             }
194         }
195
196         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LabelField"]/*' />
197         [
198             DefaultValue(""),
199             MobileCategory(SR.Category_Data),
200             MobileSysDescription(SR.ObjectList_LabelField),
201             TypeConverter(typeof(System.Web.UI.Design.MobileControls.Converters.DataFieldConverter))
202         ]
203         public String LabelField 
204         {
205             get 
206             {
207                 String s = (String)ViewState["LabelField"];
208                 return (s != null) ? s : String.Empty;
209             }
210             set 
211             {
212                 ViewState["LabelField"] = value;
213                 InvalidateDisplayFieldIndices();
214             }
215         }
216
217         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DefaultCommand"]/*' />
218         [
219             Bindable(true),
220             DefaultValue(""),
221             MobileCategory(SR.Category_Data),
222             MobileSysDescription(SR.ObjectList_DefaultCommand),
223             TypeConverter(typeof(System.Web.UI.Design.MobileControls.Converters.DefaultCommandConverter))
224         ]
225         public String DefaultCommand
226         {
227             get 
228             {
229                 String s = (String)ViewState["DefaultCommand"];
230                 return (s != null) ? s : String.Empty;
231             }
232             set 
233             {
234                 ViewState["DefaultCommand"] = value;
235             }
236         }
237
238         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.TableFields"]/*' />
239         [
240             Bindable(true),
241             DefaultValue(""),
242             Editor(typeof(System.Web.UI.Design.MobileControls.TableFieldsEditor),
243                 typeof(UITypeEditor)),
244             MobileCategory(SR.Category_Data),
245             MobileSysDescription(SR.ObjectList_TableFields)
246         ]
247         public String TableFields 
248         {
249             get 
250             {
251                 String s = (String)ViewState["TableFields"];
252                 return (s != null) ? s : String.Empty;
253             }
254             set 
255             {
256                 ViewState["TableFields"] = value;
257                 InvalidateDisplayFieldIndices();
258             }
259         }
260
261         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SelectedIndex"]/*' />
262         [
263             Bindable(false),
264             Browsable(false),
265             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
266         ]
267         public int SelectedIndex
268         {
269             get 
270             {
271                 return _selectedIndex;
272             }
273             set 
274             {
275                 if (value == -1 && ViewMode != ObjectListViewMode.List)
276                 {
277                     throw new Exception(
278                         SR.GetString(SR.ObjectList_MustBeInListModeToClearSelectedIndex));
279                 }                
280                 int itemCount = ItemCount > 0 ? ItemCount : Items.Count;
281                 if (value < -1)
282                 {
283                     throw new ArgumentOutOfRangeException("SelectedIndex",
284                         SR.GetString(SR.ObjectList_SelectedIndexTooSmall, value));
285                 }
286                 else if (itemCount > 0 && value >= itemCount)
287                 {
288                     throw new ArgumentOutOfRangeException("SelectedIndex",
289                         SR.GetString(SR.ObjectList_SelectedIndexTooBig, value, itemCount));
290                 }
291                 // End of guard clauses.
292
293                 _selectedIndexDirty = (value != _selectedIndex) && IsTrackingViewState;
294                 DeselectItemIfLoaded(_selectedIndex);
295                 SelectItemIfLoaded(value);
296                 _selectedIndex = value;
297             }
298         }
299
300         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Selection"]/*' />
301         [
302             Bindable(false),
303             Browsable(false),
304             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
305         ]
306         public ObjectListItem Selection
307         {
308             get 
309             {
310                 if (SelectedIndex == -1)
311                 {
312                     return null;
313                 }
314                 EnsureItemLoaded (SelectedIndex);
315                 int selectedIndex = TranslateVirtualItemIndex(SelectedIndex);
316                 if (selectedIndex >= 0 && selectedIndex < Items.Count)
317                 {
318                     Debug.Assert (Items[selectedIndex].Selected);
319                     return Items[selectedIndex];
320                 }
321                 else
322                 {
323                     return null;
324                 }
325             }
326         }
327
328         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.AutoGenerateFields"]/*' />
329         [
330             Bindable(false),
331             Browsable(true),
332             DefaultValue(true),
333             MobileCategory(SR.Category_Behavior),
334             MobileSysDescription(SR.ObjectList_AutoGenerateFields)
335         ]
336         public bool AutoGenerateFields
337         {
338             get
339             {
340                 Object b = ViewState["AutoGenerateFields"];
341                 return (b != null) ? (bool)b : true;
342             }
343             set
344             {
345                 if (value != AutoGenerateFields)
346                 {
347                     ViewState["AutoGenerateFields"] = value;
348                     _allFields = null;
349                     _autoGeneratedFields = null;
350                     _items = null;
351                     InvalidateDisplayFieldIndices();
352                 }
353             }
354         }
355
356         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.AllFields"]/*' />
357         [
358             Bindable(false),
359             Browsable(false),
360             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
361         ]
362         public IObjectListFieldCollection AllFields
363         {
364             get
365             {
366                 if (_allFields == null)
367                 {
368                     if (_autoGeneratedFields == null)
369                     {
370                         if (_fields == null)
371                         {
372                             return null;
373                         }
374                         else
375                         {
376                             _allFields = _fields;
377                         }
378                     }
379                     else 
380                     {
381                         if (_fields == null)
382                         {
383                             _allFields = _autoGeneratedFields;
384                         }
385                         else 
386                         {
387                             int count = _fields.Count + _autoGeneratedFields.Count;
388
389                             ArrayList list = new ArrayList(count);
390
391                             foreach (ObjectListField field in _fields)
392                             {
393                                 list.Add(field);
394                             }
395
396                             foreach (ObjectListField field in _autoGeneratedFields)
397                             {
398                                 list.Add(field);
399                             }
400
401                             _allFields = new ObjectListFieldCollection(this, list);
402                         }
403                     }
404                 }
405                 return _allFields;
406             }
407         }
408
409         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LabelFieldIndex"]/*' />
410         [
411             Bindable(false),
412             Browsable(false),
413             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
414         ]
415         public int LabelFieldIndex
416         {
417             get
418             {
419                 if (_labelFieldIndex == -1)
420                 {
421                     CalculateDisplayFieldIndices();
422                 }
423                 return _labelFieldIndex;
424             }
425         }
426
427         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.Details"]/*' />
428         [
429             Bindable(false),
430             Browsable(false),
431             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
432         ]
433         public Panel Details
434         {
435             get
436             {
437                 EnsureChildControls();
438                 if (ViewMode != ObjectListViewMode.Details)
439                 {
440                     throw new Exception(SR.GetString(SR.ObjectList_MustBeInDetailsModeToGetDetails));
441                 }
442                 return Selection;
443             }
444         }
445
446         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.TableFieldIndices"]/*' />
447         [
448             Bindable(false),
449             Browsable(false),
450             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
451         ]
452         public int[] TableFieldIndices
453         {
454             get
455             {
456                 if (_labelFieldIndex == -1)
457                 {
458                     CalculateDisplayFieldIndices();
459                 }
460                 Debug.Assert(_tableFieldIndices != null, "_tableFieldIndices is null.");
461                 return _tableFieldIndices;
462             }
463         }
464
465         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.EnsureTemplatedUI"]/*' />
466         public override void EnsureTemplatedUI()
467         {
468             EnsureChildControls();
469         }
470
471         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.EnsureChildControls"]/*' />
472         protected override void EnsureChildControls()
473         {
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();
479         }
480
481         private void CalculateDisplayFieldIndices()
482         {
483             String labelField = LabelField;
484             if (labelField.Length > 0)
485             {
486                 _labelFieldIndex = GetFieldIndex(labelField);
487             }
488             else
489             {
490                 _labelFieldIndex = 0;
491             }
492
493             String tableFields = TableFields;
494             int length = tableFields.Length;
495
496             // Populate the _tableFieldIndices array.
497             ArrayList tableFieldIndexList = new ArrayList();
498             for (int pos = 0; pos < length; )
499             {
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;
506             }
507             _tableFieldIndices = (int[])tableFieldIndexList.ToArray(typeof(int));
508         }
509
510         internal void InvalidateDisplayFieldIndices()
511         {
512             _labelFieldIndex = -1;
513             _tableFieldIndices = null;
514         }
515
516         private int GetFieldIndex(String field)
517         {
518             int index = AllFields.IndexOf(field);
519             if (index == -1)
520             {
521                 throw new ArgumentException(SR.GetString(
522                                         SR.ObjectList_FieldNotFound, field));
523             }
524             return index;
525         }
526
527         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.AddParsedSubObject"]/*' />
528         protected override void AddParsedSubObject(Object obj)
529         {
530             if (!(obj is LiteralControl))
531             {
532                 if (obj is ObjectListField)
533                 {
534                     Fields.Add((ObjectListField)obj);
535                 } 
536                 else if (obj is ObjectListCommand)
537                 {
538                     Commands.Add((ObjectListCommand)obj);
539                 }
540                 else
541                 {
542                     base.AddParsedSubObject(obj);
543                 }
544             }
545         }
546
547         private IEnumerable ResolvedDataSource
548         {
549             get
550             {
551                 if (_resolvedDataSource == null)
552                 {
553                     _resolvedDataSource = 
554                         DataSourceHelper.GetResolvedDataSource(DataSource, DataMember);
555                 }
556                 return _resolvedDataSource;
557             }
558         }
559
560         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateChildControls"]/*' />
561         protected override void CreateChildControls() 
562         {
563             Controls.Clear();
564             if (ViewState[_itemCountViewStateKey] != null)
565             {
566                 CreateChildControls(false);
567             }
568         }
569
570         private void CreateChildControls(bool doDataBind) 
571         {
572             if (IsTemplated)
573             {
574                 Controls.Clear();
575                 CreateTemplatedUI(doDataBind);
576                 ChildControlsCreated = true;
577             }
578         }
579
580         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DataBind"]/*' />
581         public override void DataBind() 
582         {
583             // Do our own databinding
584             OnDataBinding(EventArgs.Empty);
585
586             // Contained items will be databound after they have been created,
587             // so we don't want to walk the hierarchy here.
588         }
589         
590         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnDataBinding"]/*' />
591         protected override void OnDataBinding(EventArgs e) 
592         {
593             base.OnDataBinding(e);
594
595             if (ResolvedDataSource == null)
596             {
597                 ClearItemsAndControls();
598                 return;
599             }
600
601             if (AutoGenerateFields)
602             {
603                 CreateAutoGeneratedFields(ResolvedDataSource);
604             }
605
606             if ((AllFields == null || AllFields.Count == 0) 
607                 && MobilePage != null 
608                 && !MobilePage.DesignMode)
609             {
610                 throw new Exception(
611                     SR.GetString(SR.ObjectList_MustHaveOneOrMoreFields));
612             }
613             
614             CreateItems(ResolvedDataSource);
615             
616             if (!_loadingItems)
617             {
618                 // To clear the selected index, the ViewMode must be list.
619                 ViewMode = ObjectListViewMode.List;
620                 SelectedIndex = -1;    
621             }
622             else
623             {
624                 SelectItemIfLoaded(SelectedIndex);
625             }
626             
627             CreateChildControls(true);
628         }
629
630         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateTemplatedItemsList"]/*' />
631         public void CreateTemplatedItemsList(bool doDataBind)
632         {
633             ObjectListItemCollection items = Items;
634
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)
641             {
642                 alternatingItemTemplate = itemTemplate;
643             }
644
645             CreateControlItem(MobileListItemType.HeaderItem, headerTemplate, doDataBind);
646             for (int i = 0; i < items.Count; i++)
647             {
648                 if (i > 0)
649                 {
650                     CreateControlItem(MobileListItemType.SeparatorItem, 
651                                       separatorTemplate, 
652                                       doDataBind);
653                 }
654                 AddItemAsControl(i, items[i], 
655                                    ((i & 1) == 1) ? alternatingItemTemplate : itemTemplate, 
656                                    doDataBind);
657             }
658             CreateControlItem(MobileListItemType.FooterItem, footerTemplate, doDataBind);
659         }
660
661         private void AddItemAsControl(
662             int itemIndex,
663             MobileListItem item,
664             ITemplate itemTemplate, 
665             bool doDataBind)
666         {
667             if (itemTemplate != null)
668             {
669                 // No need to do it again, since CreateItems already does it.
670                 item.Controls.Clear();                
671                 item.ID = null;
672                 Controls.Add(item);
673                 CheckedInstantiateTemplate (itemTemplate, item, this);
674                 if (doDataBind)
675                 {
676                     item.DataBind();
677                 }
678             }
679         }
680
681         private void CreateControlItem(
682             MobileListItemType itemType, 
683             ITemplate itemTemplate, 
684             bool doDataBind)
685         {
686             if (itemTemplate != null)
687             {
688                 MobileListItem item = new MobileListItem(itemType);
689                 AddItemAsControl(-1, item, itemTemplate, doDataBind);
690             }
691         }
692
693         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateTemplatedItemDetails"]/*' />
694         public void CreateTemplatedItemDetails(bool doDataBind)
695         {
696             ITemplate detailsTemplate = GetTemplate(Constants.ItemDetailsTemplateTag);
697             Selection.Controls.Clear();
698
699             // Selection ID must be the same on each request.  AUI 8007.
700             Selection.ID = "_ctl";
701
702             if (detailsTemplate != null)
703             {
704                 if (!Controls.Contains (Selection))
705                 {
706                     Controls.Add (Selection);
707                 }
708                 CheckedInstantiateTemplate (detailsTemplate, Selection, this);
709                 if (doDataBind)
710                 {
711                     Selection.DataBind();
712                 }
713             }
714         }
715
716         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateItems"]/*' />
717         protected virtual void CreateItems(IEnumerable dataSource) 
718         {
719             Debug.Assert (dataSource != null, "dataSource is null");
720
721             Items.Clear();
722
723             int count = 0;
724             IEnumerator enumerator;
725
726             if(_storedDataValid  && _firstDataItem != null)
727             {
728                 enumerator = _storedEnumerator;
729                 ObjectListItem item = CreateItem(_firstDataItem);
730                 item.SetIndex(count + Items.BaseIndex);
731                 Items.Add(item);
732                 count++;
733                 _storedDataValid = false;
734                 _firstDataItem = null;
735                 _storedEnumerator = null;
736             }
737             else
738             {
739                 enumerator = dataSource.GetEnumerator();
740             }
741
742             while(enumerator.MoveNext())
743             {
744                 Object dataItem = enumerator.Current;
745                 ObjectListItem item = CreateItem(dataItem);
746                 item.SetIndex(count + Items.BaseIndex);
747                 Items.Add(item);
748                 count++;
749             }
750         }
751
752         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateItem"]/*' />
753         protected virtual ObjectListItem CreateItem(Object dataItem)
754         {
755             ObjectListItem item = new ObjectListItem(this, dataItem);
756             
757             // Set fields.
758
759             IObjectListFieldCollection allFields = AllFields;
760             int fieldIndex = 0;
761             foreach (ObjectListField field in AllFields)
762             {
763                 field.DataBindItem(fieldIndex, item);
764                 fieldIndex++;
765             }
766
767             // Use delegated data binding, if specified.
768
769             if (dataItem != null)
770             {
771                 OnItemDataBind(new ObjectListDataBindEventArgs(item, dataItem));
772             }
773
774             return item;
775         }
776
777         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnPreRender"]/*' />
778         protected override void OnPreRender(EventArgs e)
779         {
780             base.OnPreRender(e);
781
782             if (IsTemplated)
783             {
784                 int firstVisibleItem = FirstVisibleItemIndex;
785                 int pageSize = VisibleItemCount;
786                 int lastVisibleItem = firstVisibleItem + pageSize - 1;
787                 int itemIndex = 0;
788                 int separatorIndex = 0;
789                 foreach(Control ctl in Controls)
790                 {
791                     MobileListItem item = ctl as MobileListItem;
792                     if (item != null)
793                     {
794                         if (item.ItemType == MobileListItemType.ListItem)
795                         {
796                             item.Visible = itemIndex >= firstVisibleItem && itemIndex <= lastVisibleItem;
797                             itemIndex++;
798                         }
799                         else if (item.ItemType == MobileListItemType.SeparatorItem)
800                         {
801                             item.Visible = separatorIndex >= firstVisibleItem && 
802                                                 separatorIndex < lastVisibleItem;
803                             separatorIndex++;
804                         }
805                     }
806                 }
807             }
808         }
809
810         /////////////////////////////////////////////////////////////////////////
811         //  FIELD AUTO-GENERATION
812         /////////////////////////////////////////////////////////////////////////
813
814         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CreateAutoGeneratedFields"]/*' />
815         protected void CreateAutoGeneratedFields(IEnumerable dataSource)
816         {
817             if (dataSource == null)
818             {
819                 return;
820             }
821
822             ArrayList list = new ArrayList();
823             PropertyDescriptorCollection propertyDescriptors = null;
824
825             if (dataSource is ITypedList)
826             {
827                 propertyDescriptors = 
828                     ((ITypedList)dataSource).GetItemProperties(new PropertyDescriptor[0]);
829             }
830
831             if (propertyDescriptors == null)
832             {
833                 IEnumerator enumerator = dataSource.GetEnumerator();
834                 if (enumerator.MoveNext())
835                 {
836                     Object sampleItem = enumerator.Current;
837                     StoreEnumerator(enumerator, sampleItem);
838                     if (IsBindableType(sampleItem.GetType()))
839                     {
840                         list.Add(CreateAutoGeneratedField(
841                                         SR.GetString(SR.ObjectList_ItemTitle), 
842                                         null));
843                     }
844                     else
845                     {
846                         propertyDescriptors = TypeDescriptor.GetProperties(sampleItem);
847                     }
848                 }
849             }
850
851             if (propertyDescriptors != null && propertyDescriptors.Count > 0)
852             {
853                 foreach (PropertyDescriptor pd in propertyDescriptors)
854                 {
855                     if (IsBindableType(pd.PropertyType))
856                     {
857                         String title;
858                         ObjectListTitleAttribute attr = 
859                             (ObjectListTitleAttribute)pd.Attributes[typeof(ObjectListTitleAttribute)];
860                         if (attr != null)
861                         {
862                             title = attr.Title;
863                         }
864                         else
865                         {
866                             title = pd.Name;
867                         }
868                         list.Add(CreateAutoGeneratedField(title, pd.Name));
869                     }
870                 }
871             }
872
873             _autoGeneratedFields = new ObjectListFieldCollection(this, list);
874         }
875
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) 
879         {
880             _storedEnumerator = enumerator;
881             _firstDataItem = firstDataItem;
882             _storedDataValid = true;
883         }
884
885         private bool IsBindableType(Type type)
886         {
887             return(type.IsPrimitive ||
888                    (type == typeof(String)) ||
889                    (type == typeof(DateTime)) ||
890                    (type == typeof(Decimal)));
891         }
892
893         private ObjectListField CreateAutoGeneratedField(String title, String dataField)
894         {
895             ObjectListField field = new ObjectListField();
896             ((IStateManager)field).TrackViewState();
897             field.Title = title;
898             if (dataField != null)
899             {
900                 field.DataField = dataField;
901             }
902             else
903             {
904                 field.SelfReference = true;
905             }
906             return field;
907         }
908
909         Object SaveAutoFieldsState()
910         {
911             int autoGeneratedCount = (_autoGeneratedFields != null) ? _autoGeneratedFields.Count : 0;
912             if (autoGeneratedCount != 0)
913             {
914                 Object[] fieldStates = new Object[autoGeneratedCount];
915                 for (int i = 0; i < autoGeneratedCount; i++)
916                 {
917                     fieldStates[i] = ((IStateManager)_autoGeneratedFields[i]).SaveViewState();
918                 }
919                 return fieldStates;
920             }
921             else
922             {
923                 return null;
924             }
925         }
926
927         void LoadAutoFieldsState(Object state)
928         {
929             if (state != null)
930             {
931                 Object[] fieldStates = (Object[])state;
932                 int count = fieldStates.Length;
933                 ArrayList list = new ArrayList(count);
934                 foreach (Object fieldState in fieldStates)
935                 {
936                     ObjectListField field = new ObjectListField();
937                     ((IStateManager)field).TrackViewState();
938                     ((IStateManager)field).LoadViewState (fieldState);
939                     list.Add(field);
940                 }
941                 _autoGeneratedFields = new ObjectListFieldCollection(this, list);
942             }
943         }
944
945         internal void OnFieldChanged(bool fieldAddedOrRemoved)
946         {
947             // Called when a field is added, removed, etc.
948             if (IsTrackingViewState)
949             {
950                 _items = null;
951                 // avoid view state being out of sync with fields.
952                 _ignoreFieldsItemsViewModeViewState = true;
953                 if (fieldAddedOrRemoved)
954                 {
955                     _allFields = null;
956                 }
957                 InvalidateDisplayFieldIndices();
958             }
959         }
960
961         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.InternalItemCount"]/*' />
962         protected override int InternalItemCount
963         {
964             get
965             {
966                 if (_items != null && Items.Count > 0)
967                 {
968                     return Items.Count;
969                 }
970                 else
971                 {
972                     return 0;
973                 }
974             }
975             
976         }
977
978         /////////////////////////////////////////////////////////////////////////
979         //  EVENT HANDLING
980         /////////////////////////////////////////////////////////////////////////
981
982         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ItemDataBind"]/*' />
983         [
984             MobileCategory(SR.Category_Action),
985             MobileSysDescription(SR.ObjectList_OnItemDataBind)
986         ]
987         public event ObjectListDataBindEventHandler ItemDataBind 
988         {
989             add
990             {
991                 Events.AddHandler(EventItemDataBind, value);
992             }
993             remove 
994             {
995                 Events.RemoveHandler(EventItemDataBind, value);
996             }
997         }
998
999         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnItemDataBind"]/*' />
1000         protected virtual void OnItemDataBind(ObjectListDataBindEventArgs e) 
1001         {
1002             ObjectListDataBindEventHandler onItemDataBindHandler = 
1003                 (ObjectListDataBindEventHandler)Events[EventItemDataBind];
1004             if (onItemDataBindHandler != null)
1005             {
1006                 onItemDataBindHandler(this, e);
1007             }
1008         }
1009
1010         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ItemCommand"]/*' />
1011         [
1012             MobileCategory(SR.Category_Action),
1013             MobileSysDescription(SR.ObjectList_OnItemCommand)
1014         ]
1015         public event ObjectListCommandEventHandler ItemCommand 
1016         {
1017             add
1018             {
1019                 Events.AddHandler(EventItemCommand, value);
1020             }
1021             remove 
1022             {
1023                 Events.RemoveHandler(EventItemCommand, value);
1024             }
1025         }
1026
1027         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnItemCommand"]/*' />
1028         protected virtual void OnItemCommand(ObjectListCommandEventArgs e) 
1029         {
1030             ObjectListCommandEventHandler onItemCommandHandler = (ObjectListCommandEventHandler)Events[EventItemCommand];
1031             if (onItemCommandHandler != null)
1032             {
1033                 onItemCommandHandler(this, e);
1034             }
1035         }
1036
1037         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ItemSelect"]/*' />
1038         [
1039             MobileCategory(SR.Category_Action),
1040             MobileSysDescription(SR.ObjectList_OnItemSelect)
1041         ]
1042         public event ObjectListSelectEventHandler ItemSelect 
1043         {
1044             add
1045             {
1046                 Events.AddHandler(EventItemSelect, value);
1047             }
1048             remove 
1049             {
1050                 Events.RemoveHandler(EventItemSelect, value);
1051             }
1052         }
1053
1054         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnItemSelect"]/*' />
1055         protected virtual void OnItemSelect(ObjectListSelectEventArgs e) 
1056         {
1057             ObjectListSelectEventHandler onItemSelectHandler = (ObjectListSelectEventHandler)Events[EventItemSelect];
1058             if (onItemSelectHandler != null)
1059             {
1060                 onItemSelectHandler(this, e);
1061             }
1062         }
1063
1064         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.HasItemCommandHandler"]/*' />
1065         [
1066             Bindable(false),
1067             Browsable(false),
1068             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1069         ]
1070         public bool HasItemCommandHandler
1071         {
1072             get
1073             {
1074                 return Events[EventItemCommand] != null;
1075             }
1076         }
1077
1078         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ShowItemCommands"]/*' />
1079         [
1080             MobileCategory(SR.Category_Action),
1081             MobileSysDescription(SR.ObjectList_OnShowItemCommands)
1082         ]
1083         public event ObjectListShowCommandsEventHandler ShowItemCommands 
1084         {
1085             add 
1086             {
1087                 Events.AddHandler(EventShowItemCommands, value);
1088             }
1089             remove
1090             {
1091                 Events.RemoveHandler(EventShowItemCommands, value);
1092             }
1093         }
1094
1095         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnShowItemCommands"]/*' />
1096         protected virtual void OnShowItemCommands(ObjectListShowCommandsEventArgs e) 
1097         {
1098             ObjectListShowCommandsEventHandler onShowItemCommandsHandler
1099                 = (ObjectListShowCommandsEventHandler)Events[EventShowItemCommands];
1100             if (onShowItemCommandsHandler != null)
1101             {
1102                 onShowItemCommandsHandler(this, e);
1103             }
1104         }
1105
1106         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnBubbleEvent"]/*' />
1107         protected override bool OnBubbleEvent(Object sender, EventArgs e) 
1108         {
1109             bool handled = false;
1110
1111             if (e is CommandEventArgs)
1112             {
1113                 if (e is ObjectListCommandEventArgs) 
1114                 {
1115                     OnItemCommand((ObjectListCommandEventArgs)e);
1116                     handled = true;
1117                 }
1118             }
1119
1120             return handled;
1121         }
1122
1123         /// <internalonly/>
1124         protected void RaisePostBackEvent(String eventArgument)
1125         {
1126             if (!Adapter.HandlePostBackEvent(eventArgument))
1127             {
1128                 OnItemCommand(new ObjectListCommandEventArgs(Selection, eventArgument));
1129             }
1130         }
1131
1132         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.RaiseDefaultItemEvent"]/*' />
1133         public void RaiseDefaultItemEvent(int itemIndex)
1134         {
1135             EnsureItemLoaded (itemIndex);
1136             int itemCollIndex = TranslateVirtualItemIndex(itemIndex);
1137             SelectedIndex = itemIndex;
1138             OnItemCommand(new ObjectListCommandEventArgs(Items[itemCollIndex], DefaultCommand));
1139         }
1140
1141         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SelectListItem"]/*' />
1142         public bool SelectListItem(int itemIndex, bool selectMore)
1143         {
1144             EnsureItemLoaded (itemIndex);
1145             int itemCollIndex = TranslateVirtualItemIndex(itemIndex);
1146
1147             ObjectListSelectEventArgs args = new ObjectListSelectEventArgs(
1148                                                         Items[itemCollIndex], 
1149                                                         selectMore);
1150             SelectedIndex = itemIndex;
1151             OnItemSelect(args);
1152             return args.UseDefaultHandling;
1153         }
1154
1155         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.PreShowItemCommands"]/*' />
1156         public void PreShowItemCommands(int itemIndex)
1157         {
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.
1162
1163             if (_commands != null)
1164             {
1165                 _globalCommands = _commands;
1166                 _commands.GlobalStateSet();
1167             }
1168
1169             SelectedIndex = itemIndex;
1170
1171             ObjectListShowCommandsEventArgs eventArgs = 
1172                 new ObjectListShowCommandsEventArgs(Selection, Commands);
1173             OnShowItemCommands(eventArgs);
1174             if (eventArgs.Commands != _commands)
1175             {
1176                 _commands = eventArgs.Commands;
1177             }
1178         }
1179
1180         private void EnsureItemLoaded(int virtualIndex)
1181         {
1182             Debug.Assert (virtualIndex >= 0, "virtualIndex < 0");
1183             if (ItemCount > 0 &&
1184                     (_items == null || 
1185                     virtualIndex < Items.BaseIndex || 
1186                     Items.Count <= virtualIndex - Items.BaseIndex))
1187             {
1188                 OnLoadItems(new LoadItemsEventArgs(virtualIndex, 1));
1189             }
1190         }
1191
1192         private int TranslateVirtualItemIndex(int virtualIndex)
1193         {
1194             Debug.Assert(ItemCount > 0 || Items.BaseIndex == 0);
1195
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;
1199         }
1200
1201         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.OnLoadItems"]/*' />
1202         protected override void OnLoadItems(LoadItemsEventArgs e)
1203         {
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.
1207
1208             if (e.ItemIndex != Items.BaseIndex || e.ItemCount != Items.Count)
1209             {
1210                 _loadingItems = true;
1211                 Items.BaseIndex = e.ItemIndex;
1212                 Items.Clear();
1213                 base.OnLoadItems(e);
1214                 _loadingItems = false;
1215             }
1216         }
1217
1218         /////////////////////////////////////////////////////////////////////////
1219         //  STATE MANAGEMENT
1220         /////////////////////////////////////////////////////////////////////////
1221
1222         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.TrackViewState"]/*' />
1223         protected override void TrackViewState()
1224         {
1225             base.TrackViewState();
1226             if (_fields != null)
1227             {
1228                 ((IStateManager)_fields).TrackViewState();
1229             }
1230             if (_commands != null)
1231             {
1232                 ((IStateManager)_commands).TrackViewState();
1233             }
1234             if (_items != null)
1235             {
1236                 ((IStateManager)_items).TrackViewState();
1237             }
1238         }
1239
1240         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SavePrivateViewState"]/*' />
1241         protected override Object SavePrivateViewState()
1242         {
1243             Object baseState = base.SavePrivateViewState();
1244             if (ViewMode != ObjectListViewMode.List || _selectedIndexDirty)
1245             {
1246                 return new Triplet(baseState, (int) ViewMode, SelectedIndex);
1247             }
1248             else if (baseState != null)
1249             {
1250                 return baseState;
1251             }
1252             return null;
1253         }
1254
1255         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LoadPrivateViewState"]/*' />
1256         protected override void LoadPrivateViewState(Object state)
1257         {
1258             if (state != null)
1259             {
1260                 Triplet stateTriplet = state as Triplet;
1261                 if (stateTriplet != null)
1262                 {
1263                     base.LoadPrivateViewState (stateTriplet.First);
1264                     ObjectListViewMode originalViewMode = _viewMode;
1265                     
1266                     // use private field because property get calls CreateChildControls.
1267                     _viewMode = (ObjectListViewMode) stateTriplet.Second;
1268                     
1269                     // use property to insure we load items if necessary and set selected index dirty.
1270                     SelectedIndex = (int)stateTriplet.Third;
1271                     
1272                     bool viewModeChanged = (originalViewMode != _viewMode);
1273                     if (ChildControlsCreated && viewModeChanged)
1274                     {
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);
1278                     }
1279                 }
1280                 else
1281                 {
1282                     base.LoadPrivateViewState(state);
1283                 }
1284             }
1285         }
1286
1287         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.SaveViewState"]/*' />
1288         protected override Object SaveViewState() 
1289         {
1290             Object baseState, fieldsState, autoFieldsState, commandsState, itemsState;
1291         
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()) 
1296             {
1297                 ViewState[_itemCountViewStateKey] = count;
1298             }
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;
1304
1305             if (itemsState != null || 
1306                 fieldsState != null || 
1307                 autoFieldsState != null || 
1308                 commandsState != null )
1309             {
1310                 return new Object[5]
1311                 { 
1312                     baseState, 
1313                     fieldsState, 
1314                     autoFieldsState, 
1315                     commandsState, 
1316                     itemsState
1317                 };
1318             }
1319             else if (baseState != null)
1320             {
1321                 return new Object[1] { baseState };
1322             }
1323             return null;
1324         }
1325
1326         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LoadViewState"]/*' />
1327         protected override void LoadViewState(Object savedState) 
1328         {
1329             // copy locally (can change during Fields.LVS).
1330             bool ignoreFieldsItemsViewModeViewState = _ignoreFieldsItemsViewModeViewState;
1331             if (savedState != null) 
1332             {
1333                 Object[] state = (Object[])savedState;
1334                 base.LoadViewState(state[0]);
1335
1336                 if (state.Length > 1)
1337                 {
1338                     // Always load items after loading fields, because field changes can wipe out
1339                     // items!
1340                     if(!ignoreFieldsItemsViewModeViewState)
1341                     {
1342                         ((IStateManager)Fields).LoadViewState(state[1]);
1343                         LoadAutoFieldsState(state[2]);
1344                     }
1345                     ((IStateManager)Commands).LoadViewState(state[3]);
1346                     if(!ignoreFieldsItemsViewModeViewState)
1347                     {
1348                         ((IStateManager)Items).LoadViewState(state[4]);
1349                         SelectItemIfLoaded(SelectedIndex);
1350                     }
1351                 }
1352             }
1353         }
1354
1355         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.ViewMode"]/*' />
1356         [
1357             Bindable(false),
1358             Browsable(false),
1359             DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
1360         ]
1361         public ObjectListViewMode ViewMode
1362         {
1363             get
1364             {
1365                 return _viewMode;
1366             }
1367             set
1368             {   
1369                 if (SelectedIndex == -1 && value != ObjectListViewMode.List)
1370                 {
1371                     throw new Exception(SR.GetString(
1372                         SR.ObjectList_CannotSetViewModeWithNoSelectedItem));
1373                 }
1374                 if (value == ObjectListViewMode.List)
1375                 {
1376                     // Set pagination state changed to refresh pagination.
1377                     Form.PaginationStateChanged = true;
1378                 }
1379                 _viewMode = value;
1380                 CreateChildControls(true);
1381             }
1382         }
1383
1384         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.DetailsCommandText"]/*' />
1385         [
1386             Bindable(true),
1387             Browsable(true),
1388             DefaultValue(""),
1389             MobileCategory(SR.Category_Appearance),
1390             MobileSysDescription(SR.ObjectList_DetailsCommandText),
1391         ]
1392         public String DetailsCommandText
1393         {
1394             get
1395             {
1396                 String detailsCommandText = (String)ViewState["DetailsCommandText"];
1397                 return detailsCommandText != null ? detailsCommandText : String.Empty;
1398             }
1399             set
1400             {
1401                 ViewState["DetailsCommandText"] = value;
1402             }
1403         }
1404
1405         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.BackCommandText"]/*' />
1406         [
1407             Bindable(true),
1408             Browsable(true),
1409             DefaultValue(""),
1410             MobileCategory(SR.Category_Appearance),
1411             MobileSysDescription(SR.ObjectList_BackCommandText),
1412         ]
1413         public String BackCommandText
1414         {
1415             get
1416             {
1417                 String backCommandText = (String) ViewState["BackCommandText"];
1418                 return backCommandText != null ? backCommandText : String.Empty;
1419             }
1420             set
1421             {
1422                 ViewState["BackCommandText"] = value;
1423             }
1424         }
1425
1426         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.MoreText"]/*' />
1427         [
1428             Bindable(true),
1429             Browsable(true),
1430             DefaultValue(""),
1431             MobileCategory(SR.Category_Appearance),
1432             MobileSysDescription(SR.ObjectList_MoreText)
1433         ]
1434         public String MoreText
1435         {
1436             get
1437             {
1438                 String moreText = (String)ViewState["MoreText"];
1439                 return moreText != null ? moreText : String.Empty;
1440             }
1441             set
1442             {
1443                 ViewState["MoreText"] = value;
1444             }
1445         }
1446
1447         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.CommandStyle"]/*' />
1448         [
1449             DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
1450             MobileCategory(SR.Category_Style),
1451             MobileSysDescription(SR.ObjectList_CommandStyle),
1452             NotifyParentProperty(true)
1453         ]
1454         public Style CommandStyle
1455         {
1456             get
1457             {
1458                 if (_commandStyle == null)
1459                 {
1460                     _commandStyle = new Style();
1461                     _commandStyle.SetControl(this);
1462                     _commandStyle.StyleReference = "subcommand";
1463                 }
1464                 return _commandStyle;
1465             }
1466             set
1467             {
1468                 _commandStyle = value;
1469             }
1470         }
1471
1472         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectList.LabelStyle"]/*' />
1473         [
1474             DefaultValue(null),
1475             DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
1476             MobileCategory(SR.Category_Style),
1477             MobileSysDescription(SR.ObjectList_LabelStyle),
1478             NotifyParentProperty(true)
1479         ]
1480         public Style LabelStyle
1481         {
1482             get
1483             {
1484                 if (_labelStyle == null)
1485                 {
1486                     _labelStyle = new Style();
1487                     _labelStyle.SetControl(this);
1488                     _labelStyle.StyleReference = "title";
1489                 }
1490                 return _labelStyle;
1491             }
1492             set
1493             {
1494                 _labelStyle = value;
1495             }
1496         }
1497
1498         internal override void InvalidateParentStyles()
1499         {
1500             if (_commandStyle != null)
1501             {
1502                 _commandStyle.InvalidateParentStyle();
1503             }
1504             if (_labelStyle != null)
1505             {
1506                 _labelStyle.InvalidateParentStyle();
1507             }
1508             base.InvalidateParentStyles();
1509         }
1510
1511         internal override void InternalItemCountChangedHandler(int newItemCount)
1512         {
1513             if (newItemCount == 0)
1514             {
1515                 ClearItemsAndControls();
1516             }
1517         }
1518
1519         private void ClearItemsAndControls()
1520         {
1521             ViewMode = ObjectListViewMode.List;
1522             SelectedIndex = -1;
1523             Items.Clear();
1524             Controls.Clear();
1525         }
1526
1527         // Wrapper to increase intelligibility at point of call.
1528         private void SelectItemIfLoaded(int virtualIndex)
1529         {
1530             SetItemSelectedPropertyIfItemLoaded(virtualIndex, true);
1531         }
1532
1533         // Wrapper to increase intelligibility at point of call.
1534         private void DeselectItemIfLoaded(int virtualIndex)
1535         {
1536             SetItemSelectedPropertyIfItemLoaded(virtualIndex, false);
1537         }
1538
1539         private void SetItemSelectedPropertyIfItemLoaded(int virtualIndex, bool newValue)
1540         {
1541             if (virtualIndex < 0)
1542             {
1543                 return;
1544             }
1545             int physicalIndex = TranslateVirtualItemIndex(virtualIndex);
1546             if (physicalIndex >= 0 && physicalIndex < Items.Count)
1547             {
1548                 Items[physicalIndex].Selected = newValue;
1549             }
1550         }
1551
1552         #region IPostBackEventHandler implementation
1553         void IPostBackEventHandler.RaisePostBackEvent(String eventArgument) {
1554             RaisePostBackEvent(eventArgument);
1555         }
1556         #endregion 
1557     }
1558
1559
1560     /*
1561      * Control builder for object lists.
1562      *
1563      * Copyright (c) 2000 Microsoft Corporation
1564      */
1565
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
1571     {
1572         /// <include file='doc\ObjectList.uex' path='docs/doc[@for="ObjectListControlBuilder.GetChildControlType"]/*' />
1573         public override Type GetChildControlType(String tagName, IDictionary attributes) 
1574         {
1575             if (String.Compare(tagName, "Field", StringComparison.OrdinalIgnoreCase) == 0) 
1576             {
1577                 return typeof(ObjectListField);
1578             }
1579             else if (String.Compare(tagName, "Command", StringComparison.OrdinalIgnoreCase) == 0) 
1580             {
1581                 return typeof(ObjectListCommand);
1582             }
1583             else
1584             {
1585                 return base.GetChildControlType(tagName, attributes);
1586             }
1587         }
1588     }
1589 }