ListView.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / Orcas / RTM / ndp / fx / src / xsp / System / Web / Extensions / ui / webcontrols / ListView.cs / 1 / ListView.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Drawing; 
using System.Drawing.Design;
using System.Globalization; 
using System.Web; 
using System.Web.Resources;
using System.Web.UI; 
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

 
namespace System.Web.UI.WebControls {
 
    [DefaultProperty("SelectedValue")] 
    [Designer("System.Web.UI.Design.WebControls.ListViewDesigner, " + AssemblyRef.SystemWebExtensionsDesign)]
    [ControlValueProperty("SelectedValue")] 
    [DefaultEvent("SelectedIndexChanged")]
    [SupportsEventValidation]
    [ToolboxBitmap(typeof(ListView), "ListView.ico")]
    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] 
    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class ListView : DataBoundControl, INamingContainer, IPageableItemContainer { 
        internal const string ItemCountViewStateKey = "_!ItemCount"; 

        private ITemplate _itemTemplate; 
        private ITemplate _editItemTemplate;
        private ITemplate _insertItemTemplate;
        private ITemplate _layoutTemplate;
        private ITemplate _selectedItemTemplate; 
        private ITemplate _groupTemplate;
        private ITemplate _itemSeparatorTemplate; 
        private ITemplate _groupSeparatorTemplate; 
        private ITemplate _emptyItemTemplate;
        private ITemplate _emptyDataTemplate; 
        private ITemplate _alternatingItemTemplate;

        private static readonly object EventTotalRowCountAvailable = new object();
        private static readonly object EventPagePropertiesChanged = new object(); 
        private static readonly object EventPagePropertiesChanging = new object();
        private static readonly object EventItemCanceling = new object(); 
        private static readonly object EventItemCommand = new object(); 
        private static readonly object EventItemCreated = new object();
        private static readonly object EventItemDataBound = new object(); 
        private static readonly object EventItemDeleted = new object();
        private static readonly object EventItemDeleting = new object();
        private static readonly object EventItemEditing = new object();
        private static readonly object EventItemInserted = new object(); 
        private static readonly object EventItemInserting = new object();
        private static readonly object EventItemUpdated = new object(); 
        private static readonly object EventItemUpdating = new object(); 
        private static readonly object EventLayoutCreated = new object();
        private static readonly object EventSelectedIndexChanging = new object(); 
        private static readonly object EventSelectedIndexChanged = new object();
        private static readonly object EventSorted = new object();
        private static readonly object EventSorting = new object();
 
        private int _editIndex = -1;
        private int _selectedIndex = -1; 
        private int _groupItemCount = 1; 
        private string _sortExpression = String.Empty;
        private SortDirection _sortDirection = SortDirection.Ascending; 

        private int _startRowIndex = 0;
        private int _maximumRows = -1;
        private int _totalRowCount = -1; 

        private IList _itemList; 
        private ListViewItem _insertItem; 

        private string[] _dataKeyNames; 
        private DataKeyArray _dataKeyArray;
        private ArrayList _dataKeysArrayList;
        private OrderedDictionary _boundFieldValues;
 
        private int _deletedItemIndex;
        private IOrderedDictionary _deleteKeys; 
        private IOrderedDictionary _deleteValues; 
        private IOrderedDictionary _insertValues;
        private IOrderedDictionary _updateKeys; 
        private IOrderedDictionary _updateOldValues;
        private IOrderedDictionary _updateNewValues;

        private int _autoIDIndex = 0; 
        private const string _automaticIDPrefix = "ctrl";
 
        private bool _instantiatedEmptyDataTemplate = false; 

        // Keep track of where we instantiated templates when we're not using grouping 
        private int _noGroupsOriginalIndexOfItemPlaceholderInContainer = -1;
        private int _noGroupsItemCreatedCount;
        private Control _noGroupsItemPlaceholderContainer;
 
        // Keep track of where we instantiated templates when we're using grouping
        private int _groupsOriginalIndexOfGroupPlaceholderInContainer = -1; 
        private int _groupsItemCreatedCount; 
        private Control _groupsGroupPlaceholderContainer;
 

        public ListView() {
        }
 
        // Override style properties and throw from setter, and set Browsable(false).
        // Don't throw from getters because designer calls getters through reflection. 
        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        EditorBrowsable(EditorBrowsableState.Never)
        ]
        public override string AccessKey {
            get { 
                return base.AccessKey;
            } 
            set { 
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported);
            } 
        }

        [
        Browsable(false), 
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty), 
        TemplateContainer(typeof(ListViewDataItem), BindingDirection.TwoWay), 
        ResourceDescription("ListView_AlternatingItemTemplate")
        ] 
        public virtual ITemplate AlternatingItemTemplate {
            get {
                return _alternatingItemTemplate;
            } 
            set {
                _alternatingItemTemplate = value; 
            } 
        }
 
        // Override style properties and throw from setter, and set Browsable(false).
        // Don't throw from getters because designer calls getters through reflection.
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never) 
        ] 
        public override Color BackColor {
            get { 
                return base.BackColor;
            }
            set {
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported); 
            }
        } 
 
        // Override style properties and throw from setter, and set Browsable(false).
        // Don't throw from getters because designer calls getters through reflection. 
        [
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never) 
        ]
        public override Color BorderColor { 
            get { 
                return base.BorderColor;
            } 
            set {
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported);
            }
        } 

 
        // Override style properties and throw from setter, and set Browsable(false). 
        // Don't throw from getters because designer calls getters through reflection.
        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never)
        ] 
        public override Unit BorderWidth {
            get { 
                return base.BorderWidth; 
            }
            set { 
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported);
            }
        }
 

        // Override style properties and throw from setter, and set Browsable(false). 
        // Don't throw from getters because designer calls getters through reflection. 
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never)
        ]
        public override BorderStyle BorderStyle { 
            get {
                return base.BorderStyle; 
            } 
            set {
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported); 
            }
        }

        private IOrderedDictionary BoundFieldValues { 
            get {
                if (_boundFieldValues == null) { 
                    _boundFieldValues = new OrderedDictionary(); 
                }
                return _boundFieldValues; 
            }
        }

        public override ControlCollection Controls { 
            get {
                EnsureChildControls(); 
                return base.Controls; 
            }
        } 

        /// 
        ///    Gets or sets the property that determines whether the control treats empty string as
        ///    null when the item values are extracted. 
        /// 
        [ 
        Category("Behavior"), 
        DefaultValue(true),
        ResourceDescription("ListView_ConvertEmptyStringToNull"), 
        ]
        public virtual bool ConvertEmptyStringToNull {
            get {
                object o = ViewState["ConvertEmptyStringToNull"]; 
                if (o != null) {
                    return (bool)o; 
                } 
                return true;
            } 
            set {
                ViewState["ConvertEmptyStringToNull"] = value;
            }
        } 

        // Override style properties and throw from setter, and set Browsable(false). 
        // Don't throw from getters because designer calls getters through reflection. 
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never),
        CssClassPropertyAttribute
        ] 
        public override string CssClass {
            get { 
                return base.CssClass; 
            }
            set { 
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported);
            }
        }
 
        /// 
        /// An array of ordered dictionaries that represents each key 
        ///  
        private ArrayList DataKeysArrayList {
            get { 
                if (_dataKeysArrayList == null) {
                    _dataKeysArrayList = new ArrayList();
                }
                return _dataKeysArrayList; 
            }
        } 
 
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        ResourceDescription("ListView_DataKeys")
        ]
        public virtual DataKeyArray DataKeys { 
            get {
                if (_dataKeyArray == null) { 
                    _dataKeyArray = new DataKeyArray(this.DataKeysArrayList); 
                    if (IsTrackingViewState)
                        ((IStateManager)_dataKeyArray).TrackViewState(); 
                }
                return _dataKeyArray;
            }
        } 

        [ 
        DefaultValue(null), 
        Editor("System.Web.UI.Design.WebControls.DataFieldEditor, " + AssemblyRef.SystemDesign, typeof(UITypeEditor)),
        Category("Data"), 
        ResourceDescription("ListView_DataKeyNames"),
        SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays",
                        Justification = "Required by ASP.NET parser."),
        TypeConverterAttribute(typeof(StringArrayConverter)), 
        ]
        public virtual string[] DataKeyNames { 
            get { 
                object o = _dataKeyNames;
                if (o != null) { 
                    return (string[])((string[])o).Clone();
                }
                return new string[0];
            } 
            set {
                if (!DataBoundControlHelper.CompareStringArrays(value, DataKeyNamesInternal)) { 
                    if (value != null) { 
                        _dataKeyNames = (string[])value.Clone();
                    } 
                    else {
                        _dataKeyNames = null;
                    }
 
                    ClearDataKeys();
                    SetRequiresDataBindingIfInitialized(); 
                } 
            }
        } 

        // This version doesn't clone the array
        private string[] DataKeyNamesInternal {
            get { 
                object o = _dataKeyNames;
                if (o != null) { 
                    return (string[])o; 
                }
                return new string[0]; 
            }
        }

        [ 
        Category("Default"),
        DefaultValue(-1), 
        ResourceDescription("ListView_EditIndex") 
        ]
        public virtual int EditIndex { 
            get {
                return _editIndex;
            }
            set { 
                if (value < -1) {
                    throw new ArgumentOutOfRangeException("value"); 
                } 
                if (value != _editIndex) {
                    if (value == -1) { 
                        BoundFieldValues.Clear();
                    }
                    _editIndex = value;
                    SetRequiresDataBindingIfInitialized(); 
                }
            } 
        } 

        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        ResourceDescription("ListView_EditItem")
        ] 
        public virtual ListViewItem EditItem {
            get { 
                if (_editIndex > 0 && _editIndex < Items.Count) { 
                    return Items[_editIndex];
                } 
                return null;
            }
        }
 
        [
        Browsable(false), 
        DefaultValue(null), 
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(ListViewDataItem), BindingDirection.TwoWay), 
        ResourceDescription("ListView_EditItemTemplate"),
        ]
        public virtual ITemplate EditItemTemplate {
            get { 
                return _editItemTemplate;
            } 
            set { 
                _editItemTemplate = value;
            } 
        }

        [
        Browsable(false), 
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty), 
        TemplateContainer(typeof(ListView)), 
        ResourceDescription("ListView_EmptyDataTemplate"),
        ] 
        public virtual ITemplate EmptyDataTemplate {
            get {
                return _emptyDataTemplate;
            } 
            set {
                _emptyDataTemplate = value; 
            } 
        }
 
        [
        Browsable(false),
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty), 
        TemplateContainer(typeof(ListViewItem)),
        ResourceDescription("ListView_EmptyItemTemplate"), 
        ] 
        public virtual ITemplate EmptyItemTemplate {
            get { 
                return _emptyItemTemplate;
            }
            set {
                _emptyItemTemplate = value; 
            }
        } 
 
        // Override style properties and throw from setter, and set Browsable(false).
        // Don't throw from getters because designer calls getters through reflection. 
        [
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never) 
        ]
        public override FontInfo Font { 
            get { 
                return base.Font;
            } 
        }

        // Override style properties and throw from setter, and set Browsable(false).
        // Don't throw from getters because designer calls getters through reflection. 
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        EditorBrowsable(EditorBrowsableState.Never)
        ] 
        public override Color ForeColor {
            get {
                return base.ForeColor;
            } 
            set {
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported); 
            } 
        }
 
        [
        DefaultValue("groupPlaceholder"),
        Category("Behavior"),
        ResourceDescription("ListView_GroupPlaceholderID"), 
        SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId = "Member"),
        ] 
        public virtual String GroupPlaceholderID { 
            get {
                object o = ViewState["GroupPlaceholderID"]; 
                if (o != null) {
                    return (String)o;
                }
                return "groupPlaceholder"; 
            }
            set { 
                if (String.IsNullOrEmpty(value)) { 
                    throw new ArgumentOutOfRangeException("value", String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_ContainerNameMustNotBeEmpty, "GroupPlaceholderID"));
                } 
                ViewState["GroupPlaceholderID"] = value;
            }
        }
 
        [
        Category("Default"), 
        DefaultValue(1), 
        ResourceDescription("ListView_GroupItemCount"),
        ] 
        public virtual int GroupItemCount {
            get {
                return _groupItemCount;
            } 
            set {
                if (value < 1) { 
                    throw new ArgumentOutOfRangeException("value"); 
                }
                _groupItemCount = value; 
                SetRequiresDataBindingIfInitialized();
            }
        }
 
        [
        Browsable(false), 
        DefaultValue(null), 
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(ListViewItem)), 
        ResourceDescription("ListView_GroupSeparatorTemplate"),
        ]
        public virtual ITemplate GroupSeparatorTemplate {
            get { 
                return _groupSeparatorTemplate;
            } 
            set { 
                _groupSeparatorTemplate = value;
            } 
        }

        [
        Browsable(false), 
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty), 
        TemplateContainer(typeof(ListViewItem)), 
        ResourceDescription("ListView_GroupTemplate"),
        ] 
        public virtual ITemplate GroupTemplate {
            get {
                return _groupTemplate;
            } 
            set {
                _groupTemplate = value; 
            } 
        }
 
        // Override style properties and throw from setter, and set Browsable(false).
        // Don't throw from getters because designer calls getters through reflection.
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never) 
        ] 
        public override Unit Height {
            get { 
                return base.Height;
            }
            set {
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported); 
            }
        } 
 
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        ResourceDescription("ListView_InsertItem")
        ]
        public virtual ListViewItem InsertItem { 
            get {
                return _insertItem; 
            } 
        }
 
        [
        Category("Default"),
        DefaultValue(InsertItemPosition.None),
        ResourceDescription("ListView_InsertItemPosition") 
        ]
        public virtual InsertItemPosition InsertItemPosition { 
            get { 
                object o = ViewState["InsertItemPosition"];
                if (o != null) { 
                    return (InsertItemPosition)o;
                }
                return InsertItemPosition.None;
            } 
            set {
                if (InsertItemPosition != value) { 
                    ViewState["InsertItemPosition"] = value; 
                    SetRequiresDataBindingIfInitialized();
                } 
            }
        }

        [ 
        Browsable(false),
        DefaultValue(null), 
        PersistenceMode(PersistenceMode.InnerProperty), 
        TemplateContainer(typeof(ListViewItem), BindingDirection.TwoWay),
        ResourceDescription("ListView_InsertItemTemplate"), 
        ]
        public virtual ITemplate InsertItemTemplate {
            get {
                return _insertItemTemplate; 
            }
            set { 
                _insertItemTemplate = value; 
            }
        } 

        [
        DefaultValue("itemPlaceholder"),
        Category("Behavior"), 
        ResourceDescription("ListView_ItemPlaceholderID"),
        SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId = "Member"), 
        ] 
        public virtual String ItemPlaceholderID {
            get { 
                object o = ViewState["ItemPlaceholderID"];
                if (o != null) {
                    return (String)o;
                } 
                return "itemPlaceholder";
            } 
            set { 
                if (String.IsNullOrEmpty(value)) {
                    throw new ArgumentOutOfRangeException("value", String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_ContainerNameMustNotBeEmpty, "ItemPlaceholderID")); 
                }
                ViewState["ItemPlaceholderID"] = value;
            }
        } 

        [ 
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        ResourceDescription("ListView_Items") 
        ]
        public virtual IList Items {
            get {
                if (_itemList == null) { 
                    _itemList = new List();
                } 
                return _itemList; 
            }
        } 

        [
        Browsable(false),
        DefaultValue(null), 
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(ListViewItem)), 
        ResourceDescription("ListView_ItemSeparatorTemplate"), 
        ]
        public virtual ITemplate ItemSeparatorTemplate { 
            get {
                return _itemSeparatorTemplate;
            }
            set { 
                _itemSeparatorTemplate = value;
            } 
        } 

        [ 
        Browsable(false),
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(ListViewDataItem), BindingDirection.TwoWay), 
        ResourceDescription("ListView_ItemTemplate"),
        ] 
        public virtual ITemplate ItemTemplate { 
            get {
                return _itemTemplate; 
            }
            set {
                _itemTemplate = value;
            } 
        }
 
        [ 
        Browsable(false),
        DefaultValue(null), 
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(ListView)),
        ResourceDescription("ListView_LayoutTemplate"),
        ] 
        public virtual ITemplate LayoutTemplate {
            get { 
                return _layoutTemplate; 
            }
            set { 
                _layoutTemplate = value;
            }
        }
 
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 
        ]
        public virtual DataKey SelectedDataKey { 
            get {
                if (DataKeyNamesInternal == null || DataKeyNamesInternal.Length == 0) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_DataKeyNamesMustBeSpecified, ID));
                } 

                DataKeyArray keys = DataKeys; 
                int selectedIndex = SelectedIndex; 
                if (keys != null && selectedIndex < keys.Count && selectedIndex > -1) {
                    return keys[selectedIndex]; 
                }
                return null;
            }
        } 

        [ 
        Category("Default"), 
        DefaultValue(-1),
        ResourceDescription("ListView_SelectedIndex") 
        ]
        public virtual int SelectedIndex {
            get {
                return _selectedIndex; 
            }
            set { 
                if (value < -1) { 
                    throw new ArgumentOutOfRangeException("value");
                } 
                if (value != _selectedIndex) {
                    _selectedIndex = value;
                    // we're going to rebind here for a new template
                    SetRequiresDataBindingIfInitialized(); 
                }
            } 
        } 

        [ 
        Browsable(false),
        DefaultValue(null),
        PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(ListViewDataItem), BindingDirection.TwoWay), 
        ResourceDescription("ListView_SelectedItemTemplate"),
        ] 
        public virtual ITemplate SelectedItemTemplate { 
            get {
                return _selectedItemTemplate; 
            }
            set {
                _selectedItemTemplate = value;
            } 
        }
 
        [ 
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden) 
        ]
        public object SelectedValue {
            get {
                DataKey selectedDataKey = SelectedDataKey; 
                if (selectedDataKey != null) {
                    return SelectedDataKey.Value; 
                } 
                return null;
            } 
        }

        [
        Browsable(false), 
        DefaultValue(SortDirection.Ascending),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        PersistenceMode(PersistenceMode.InnerProperty), 
        ResourceDescription("ListView_SortDirection"),
        ResourceCategory("Sorting"), 
        ]
        public virtual SortDirection SortDirection {
            get {
                return SortDirectionInternal; 
            }
        } 
 
        /// 
        ///    Internal member for setting sort direction 
        /// 
        private SortDirection SortDirectionInternal {
            get {
                return _sortDirection; 
            }
            set { 
                if (value < SortDirection.Ascending || value > SortDirection.Descending) { 
                    throw new ArgumentOutOfRangeException("value");
                } 
                if (_sortDirection != value) {
                    _sortDirection = value;
                    SetRequiresDataBindingIfInitialized();
                } 
            }
        } 
 
        /// 
        /// Gets a value that specifies the current column being sorted on in the 
        /// .
        /// 
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        ResourceDescription("ListView_SortExpression"), 
        ResourceCategory("Sorting"), 
        ]
        public virtual string SortExpression { 
            get {
                return SortExpressionInternal;
            }
        } 

        ///  
        ///    Internal member for setting sort expression 
        /// 
        private string SortExpressionInternal { 
            get {
                return _sortExpression;
            }
            set { 
                if (_sortExpression != value) {
                    _sortExpression = value; 
                    SetRequiresDataBindingIfInitialized(); 
                }
            } 
        }

        // Override style properties and throw from setter, and set Browsable(false).
        // Don't throw from getters because designer calls getters through reflection. 
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), 
        EditorBrowsable(EditorBrowsableState.Never)
        ] 
        public override short TabIndex {
            get {
                return base.TabIndex;
            } 
            set {
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported); 
            } 
        }
 
        // Override style properties and throw from setter, and set Browsable(false).
        // Don't throw from getters because designer calls getters through reflection.
        [
        Browsable(false), 
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never) 
        ] 
        public override string ToolTip {
            get { 
                return base.ToolTip;
            }
            set {
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported); 
            }
        } 
 
        // Override style properties and throw from setter, and set Browsable(false).
        // Don't throw from getters because designer calls getters through reflection. 
        [
        Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
        EditorBrowsable(EditorBrowsableState.Never) 
        ]
        public override Unit Width { 
            get { 
                return base.Width;
            } 
            set {
                throw new NotSupportedException(AtlasWeb.ListView_StylePropertiesNotSupported);
            }
        } 

        ///  
        /// Occurs when a control bubbles an event to the  with a 
        /// .
        ///  
        [
        Category("Action"),
        ResourceDescription("ListView_OnItemDeleted")
        ] 
        public event EventHandler ItemDeleted {
            add { 
                Events.AddHandler(EventItemDeleted, value); 
            }
            remove { 
                Events.RemoveHandler(EventItemDeleted, value);
            }
        }
 
        /// 
        /// Occurs when a control bubbles an event to the  with a 
        /// . 
        /// 
        [ 
        Category("Action"),
        ResourceDescription("ListView_OnItemInserted")
        ]
        public event EventHandler ItemInserted { 
            add {
                Events.AddHandler(EventItemInserted, value); 
            } 
            remove {
                Events.RemoveHandler(EventItemInserted, value); 
            }
        }

        ///  
        /// Occurs when a control bubbles an event to the  with a
        /// . 
        ///  
        [
        Category("Action"), 
        ResourceDescription("ListView_OnItemUpdated")
        ]
        public event EventHandler ItemUpdated {
            add { 
                Events.AddHandler(EventItemUpdated, value);
            } 
            remove { 
                Events.RemoveHandler(EventItemUpdated, value);
            } 
        }

        /// 
        /// Occurs when a control bubbles an event to the  with a 
        ///  property of
        /// . 
        ///  
        [
        Category("Action"), 
        ResourceDescription("ListView_OnItemCanceling")
        ]
        public event EventHandler ItemCanceling {
            add { 
                Events.AddHandler(EventItemCanceling, value);
            } 
            remove { 
                Events.RemoveHandler(EventItemCanceling, value);
            } 
        }

        /// Occurs when a control bubbles an event to the  not covered by
        /// , ,  or 
        /// .
        ///  
        [ 
        Category("Action"),
        ResourceDescription("ListView_OnItemCommand") 
        ]
        public event EventHandler ItemCommand {
            add {
                Events.AddHandler(EventItemCommand, value); 
            }
            remove { 
                Events.RemoveHandler(EventItemCommand, value); 
            }
        } 

        /// 
        ///    Occurs on the server when a control a created.
        ///  
        [
        Category("Behavior"), 
        ResourceDescription("ListView_OnItemCreated") 
        ]
        public event EventHandler ItemCreated { 
            add {
                Events.AddHandler(EventItemCreated, value);
            }
            remove { 
                Events.RemoveHandler(EventItemCreated, value);
            } 
        } 

        ///  
        ///    Occurs when an Item is data bound to the control.
        /// 
        [
        Category("Data"), 
        ResourceDescription("ListView_OnItemDataBound")
        ] 
        public event EventHandler ItemDataBound { 
            add {
                Events.AddHandler(EventItemDataBound, value); 
            }
            remove {
                Events.RemoveHandler(EventItemDataBound, value);
            } 
        }
 
        ///  
        /// Occurs when a control bubbles an event to the  with a
        /// . 
        /// 
        [
        Category("Action"),
        ResourceDescription("ListView_OnItemDeleting") 
        ]
        public event EventHandler ItemDeleting { 
            add { 
                Events.AddHandler(EventItemDeleting, value);
            } 
            remove {
                Events.RemoveHandler(EventItemDeleting, value);
            }
        } 

        ///  
        /// Occurs when a control bubbles an event to the  with a 
        ///  property of
        /// . 
        /// 
        [
        Category("Action"),
        ResourceDescription("ListView_OnItemEditing") 
        ]
        public event EventHandler ItemEditing { 
            add { 
                Events.AddHandler(EventItemEditing, value);
            } 
            remove {
                Events.RemoveHandler(EventItemEditing, value);
            }
        } 

        ///  
        /// Occurs when a control bubbles an event to the  with a 
        /// .
        ///  
        [
        Category("Action"),
        ResourceDescription("ListView_OnItemInserting")
        ] 
        public event EventHandler ItemInserting {
            add { 
                Events.AddHandler(EventItemInserting, value); 
            }
            remove { 
                Events.RemoveHandler(EventItemInserting, value);
            }
        }
 
        /// 
        /// Occurs when a control bubbles an event to the  with a 
        /// . 
        /// 
        [ 
        Category("Action"),
        ResourceDescription("ListView_OnItemUpdating")
        ]
        public event EventHandler ItemUpdating { 
            add {
                Events.AddHandler(EventItemUpdating, value); 
            } 
            remove {
                Events.RemoveHandler(EventItemUpdating, value); 
            }
        }

        ///  
        /// Occurs on the server when a control layout is created.
        ///  
        [ 
        Category("Behavior"),
        ResourceDescription("ListView_OnLayoutCreated") 
        ]
        public event EventHandler LayoutCreated {
            add {
                Events.AddHandler(EventLayoutCreated, value); 
            }
            remove { 
                Events.RemoveHandler(EventLayoutCreated, value); 
            }
        } 

        /// 
        /// Occurs on the server when the page properties have changed.
        ///  
        [
        Category("Behavior"), 
        ResourceDescription("ListView_OnPagePropertiesChanged") 
        ]
        public event EventHandler PagePropertiesChanged { 
            add {
                Events.AddHandler(EventPagePropertiesChanged, value);
            }
            remove { 
                Events.RemoveHandler(EventPagePropertiesChanged, value);
            } 
        } 

        ///  
        /// Occurs on the server when the page properties are changing.
        /// 
        [
        Category("Behavior"), 
        ResourceDescription("ListView_OnPagePropertiesChanging")
        ] 
        public event EventHandler PagePropertiesChanging { 
            add {
                Events.AddHandler(EventPagePropertiesChanging, value); 
            }
            remove {
                Events.RemoveHandler(EventPagePropertiesChanging, value);
            } 
        }
 
        ///  
        ///    Occurs when an Item on the list is selected.
        ///  
        [
        Category("Action"),
        ResourceDescription("ListView_OnSelectedIndexChanged")
        ] 
        public event EventHandler SelectedIndexChanged {
            add { 
                Events.AddHandler(EventSelectedIndexChanged, value); 
            }
            remove { 
                Events.RemoveHandler(EventSelectedIndexChanged, value);
            }
        }
 
        /// 
        ///    Occurs when an Item on the list is selected. 
        ///  
        [
        Category("Action"), 
        ResourceDescription("ListView_OnSelectedIndexChanging")
        ]
        public event EventHandler SelectedIndexChanging {
            add { 
                Events.AddHandler(EventSelectedIndexChanging, value);
            } 
            remove { 
                Events.RemoveHandler(EventSelectedIndexChanging, value);
            } 
        }

        /// 
        ///    Occurs when a field is sorted. 
        /// 
        [ 
        Category("Action"), 
        ResourceDescription("ListView_OnSorted")
        ] 
        public event EventHandler Sorted {
            add {
                Events.AddHandler(EventSorted, value);
            } 
            remove {
                Events.RemoveHandler(EventSorted, value); 
            } 
        }
 
        /// 
        ///    Occurs when a field is sorting.
        /// 
        [ 
        Category("Action"),
        ResourceDescription("ListView_OnSorting") 
        ] 
        public event EventHandler Sorting {
            add { 
                Events.AddHandler(EventSorting, value);
            }
            remove {
                Events.RemoveHandler(EventSorting, value); 
            }
        } 
 
        protected virtual void AddControlToContainer(Control control, Control container, int addLocation) {
            // The ListView packages up everything in the ItemTemplate in a ListViewDataItem or ListViewItem. 
            // The ListViewItem is being added to the control tree.  Since ListViewItems can't be children of HtmlTables or
            // HtmlTableRows, we put them in a derived HtmlTable or HtmlTableRow, which just renders out its children.
            // Since ListViewItems don't have any rendering, only the child HtmlTableRow or HtmlTableCell will be rendered.
 
            if (container is HtmlTable) {
                ListViewTableRow listViewTableRow = new ListViewTableRow(); 
                container.Controls.AddAt(addLocation, listViewTableRow); 
                listViewTableRow.Controls.Add(control);
            } 
            else {
                if (container is HtmlTableRow) {
                    ListViewTableCell listViewTableCell = new ListViewTableCell();
                    container.Controls.AddAt(addLocation, listViewTableCell); 
                    listViewTableCell.Controls.Add(control);
                } 
                else { 
                    container.Controls.AddAt(addLocation, control);
                } 
            }
        }

        private void AutoIDControl(Control control) { 
            // We have to do our own auto-id'ing because we create the LayoutTemplate, add controls
            // to the item or group container, then clear those controls out when we bind again. 
            // Because the item or group container isn't necessarily a naming container, clearing 
            // out its controls collection doesn't reset the auto-id counter and you get new ids.
            // On postback, controls that have post data won't be found because their generated 
            // ids won't match the prior ones.  By creating our own auto-id'ing, we don't get
            // Control's auto-id, and we can reset the auto id index when we remove all items from
            // the item or group container.
            control.ID = _automaticIDPrefix + _autoIDIndex++.ToString(CultureInfo.InvariantCulture); 
        }
 
        private void ClearDataKeys() { 
            _dataKeysArrayList = null;
        } 

        /// 
        /// Overriden by DataBoundControl to determine if the control should
        /// recreate its control hierarchy based on values in view state. 
        /// If the control hierarchy should be created, i.e. view state does
        /// exist, it calls CreateChildControls with a dummy (empty) data source 
        /// which is usable for enumeration purposes only. 
        /// 
        protected internal override void CreateChildControls() { 
            object controlCount = ViewState[ItemCountViewStateKey];

            if (controlCount == null && RequiresDataBinding) {
                EnsureDataBound(); 
            }
 
            if (controlCount != null && ((int)controlCount) != -1) { 
                object[] dummyDataSource = new object[(int)controlCount];
                CreateChildControls(dummyDataSource, false); 
                ClearChildViewState();
            }
        }
 
        /// 
        /// Performs the work of creating the control hierarchy based on a data source. 
        /// When dataBinding is true, the specified data source contains real 
        /// data, and the data is supposed to be pushed into the UI.
        /// When dataBinding is false, the specified data source is a dummy data 
        /// source, that allows enumerating the right number of items, but the items
        /// themselves are null and do not contain data. In this case, the recreated
        /// control hierarchy reinitializes its state from view state.
        /// It enables a DataBoundControl to encapsulate the logic of creating its 
        /// control hierarchy in both modes into a single code path.
        ///  
        ///  
        /// The data source to be used to enumerate items.
        ///  
        /// 
        /// Whether the method has been called from DataBind or not.
        /// 
        ///  
        /// The number of items created based on the data source. Put another way, its
        /// the number of items enumerated from the data source. 
        ///  
        protected virtual int CreateChildControls(IEnumerable dataSource, bool dataBinding) {
            ListViewPagedDataSource pagedDataSource = null; 

            // Create the LayoutTemplate so the pager control in it can set page properties.
            // We'll only create the layout template once.
 
            EnsureLayoutTemplate();
            RemoveItems(); 
 
            // if we should render the insert item, make a dummy empty datasource and go through
            // the regular code path. 
            if (dataSource == null && InsertItemPosition != InsertItemPosition.None) {
                dataSource = new object[0];
            }
 
            bool usePaging = (_startRowIndex > 0 || _maximumRows > 0);
 
            if (dataBinding) { 
                DataSourceView view = GetData();
                DataSourceSelectArguments arguments = SelectArguments; 
                if (view == null) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_NullView, ID));
                }
 
                bool useServerPaging = view.CanPage && usePaging;
 
                if (!view.CanPage && useServerPaging) { 
                    if (dataSource != null && !(dataSource is ICollection)) {
                        arguments.StartRowIndex = _startRowIndex; 
                        arguments.MaximumRows = _maximumRows;
                        // This should throw an exception saying the data source can't page.
                        // We do this because the data source can provide a better error message than we can.
                        view.Select(arguments, SelectCallback); 
                    }
                } 
 
                if (useServerPaging) {
                    int totalRowCount; 
                    if (view.CanRetrieveTotalRowCount) {
                        totalRowCount = arguments.TotalRowCount;
                    }
                    else { 
                        ICollection dataSourceCollection = dataSource as ICollection;
                        if (dataSourceCollection == null) { 
                            throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_NeedICollectionOrTotalRowCount, GetType().Name)); 
                        }
                        totalRowCount = checked(_startRowIndex + dataSourceCollection.Count); 
                    }
                    pagedDataSource = CreateServerPagedDataSource(totalRowCount);

                } 
                else {
                    pagedDataSource = CreatePagedDataSource(); 
                } 
            }
            else { 
                pagedDataSource = CreatePagedDataSource();
            }

            ArrayList keyArray = DataKeysArrayList; 
            _dataKeyArray = null;
 
            ICollection collection = dataSource as ICollection; 

            if (dataBinding) { 
                keyArray.Clear();
                if ((dataSource != null) && (collection == null) && !pagedDataSource.IsServerPagingEnabled && usePaging) {
                    // If we got to here, it's because the data source view said it could page, but then returned
                    // something that wasn't an ICollection.  Probably a data source control author error. 
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_Missing_VirtualItemCount, ID));
                } 
            } 
            else {
                if (collection == null) { 
                    throw new InvalidOperationException(AtlasWeb.ListView_DataSourceMustBeCollectionWhenNotDataBinding);
                }
            }
 
            if (dataSource != null) {
                pagedDataSource.DataSource = dataSource; 
                if (dataBinding && usePaging) { 
                    keyArray.Capacity = pagedDataSource.DataSourceCount;
                } 

                if (_groupTemplate != null) {
                    _itemList = CreateItemsInGroups(pagedDataSource, dataBinding, InsertItemPosition, keyArray);
                } 
                else {
                    if (GroupItemCount != 1) { 
                        throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_GroupItemCountNoGroupTemplate, ID, GroupPlaceholderID)); 
                    }
 
                    _itemList = CreateItemsWithoutGroups(pagedDataSource, dataBinding, InsertItemPosition, keyArray);
                }

                _totalRowCount = usePaging ? pagedDataSource.DataSourceCount : _itemList.Count; 
                OnTotalRowCountAvailable(new PageEventArgs(_startRowIndex, _maximumRows, _totalRowCount));
 
                if (_itemList.Count == 0) { 
                    if (InsertItemPosition == InsertItemPosition.None) {
                        // remove the layout template 
                        Controls.Clear();
                        CreateEmptyDataItem();
                    }
                } 
            }
            else { 
                // remove the layout template 
                Controls.Clear();
                CreateEmptyDataItem(); 
            }

            return _totalRowCount;
        } 

        // Style properties won't be honored on ListView, so throw if someone tries to set any style properties 
        protected override Style CreateControlStyle() { 
            // The designer reflects on properties at design time.  Don't throw then.
            if (!DesignMode) { 
                throw new NotSupportedException(AtlasWeb.ListView_StyleNotSupported);
            }
            return base.CreateControlStyle();
        } 

        protected override DataSourceSelectArguments CreateDataSourceSelectArguments() { 
            DataSourceSelectArguments arguments = new DataSourceSelectArguments(); 
            DataSourceView view = GetData();
            bool useServerPaging = view.CanPage; 

            string sortExpression = SortExpressionInternal;
            if (SortDirectionInternal == SortDirection.Descending && !String.IsNullOrEmpty(sortExpression)) {
                sortExpression += " DESC"; 
            }
            arguments.SortExpression = sortExpression; 
 
            // decide if we should use server-side paging
            if (useServerPaging) { 
                if (view.CanRetrieveTotalRowCount) {
                    arguments.RetrieveTotalRowCount = true;
                    arguments.MaximumRows = _maximumRows;
                } 
                else {
                    arguments.MaximumRows = -1; 
                } 
                arguments.StartRowIndex = _startRowIndex;
            } 
            return arguments;
        }

        protected virtual void CreateEmptyDataItem() { 
            if (_emptyDataTemplate != null) {
                _instantiatedEmptyDataTemplate = true; 
                ListViewItem item = CreateItem(ListViewItemType.EmptyItem); 
                AutoIDControl(item);
                InstantiateEmptyDataTemplate(item); 
                OnItemCreated(new ListViewItemEventArgs(item));
                AddControlToContainer(item, this, 0);
            }
        } 

        protected virtual ListViewItem CreateEmptyItem() { 
            if (_emptyItemTemplate != null) { 
                ListViewItem emptyItem = CreateItem(ListViewItemType.EmptyItem);
                AutoIDControl(emptyItem); 
                InstantiateEmptyItemTemplate(emptyItem);
                OnItemCreated(new ListViewItemEventArgs(emptyItem));
                return emptyItem;
            } 
            return null;
        } 
 
        protected virtual ListViewItem CreateInsertItem() {
            if (InsertItemTemplate == null) { 
                throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_InsertTemplateRequired, ID));
            }

            ListViewItem item = CreateItem(ListViewItemType.InsertItem); 
            AutoIDControl(item);
            InstantiateInsertItemTemplate(item); 
            OnItemCreated(new ListViewItemEventArgs(item)); 
            return item;
        } 

        protected virtual ListViewItem CreateItem(ListViewItemType itemType) {
            ListViewItem item = new ListViewItem(itemType);
            if (itemType == ListViewItemType.InsertItem) { 
                _insertItem = item;
            } 
            return item; 
        }
 
        protected virtual ListViewDataItem CreateDataItem(int dataItemIndex, int displayIndex) {
            return new ListViewDataItem(dataItemIndex, displayIndex);
        }
 
        protected virtual IList CreateItemsWithoutGroups(ListViewPagedDataSource dataSource, bool dataBinding, InsertItemPosition insertPosition, ArrayList keyArray) {
            // If this is the first time we're creating the control items, we need 
            // to locate the itemPlaceholder container. 
            // If this is a scenario where we are recreating control items, we already
            // have the cached itemPlaceholder container. 
            if (_noGroupsOriginalIndexOfItemPlaceholderInContainer == -1) {
                _noGroupsItemPlaceholderContainer = GetPreparedContainerInfo(this, true, out _noGroupsOriginalIndexOfItemPlaceholderInContainer);
            }
 
            // We need to keep track of where we're inserting items and how many items we have
            // inserted so that if we need to remove them we know what to do. 
            int itemInsertLocation = _noGroupsOriginalIndexOfItemPlaceholderInContainer; 

            List items = new List(); 
            int itemIndex = 0;
            int dataItemIndex = 0;

            if (insertPosition == InsertItemPosition.FirstItem) { 
                ListViewItem insertItem = CreateInsertItem();
                AddControlToContainer(insertItem, _noGroupsItemPlaceholderContainer, itemInsertLocation); 
                itemInsertLocation++; 
                itemIndex++;
            } 

            foreach (object o in dataSource) {
                if (itemIndex != 0 && _itemSeparatorTemplate != null) {
                    ListViewContainer itemSeparatorContainer = new ListViewContainer(); 
                    AutoIDControl(itemSeparatorContainer);
                    InstantiateItemSeparatorTemplate(itemSeparatorContainer); 
                    AddControlToContainer(itemSeparatorContainer, _noGroupsItemPlaceholderContainer, itemInsertLocation); 
                    itemInsertLocation++;
                } 

                ListViewDataItem item = CreateDataItem(dataItemIndex + dataSource.StartRowIndex, dataItemIndex);
                AutoIDControl(item);
                InstantiateItemTemplate(item, dataItemIndex); 

                if (dataBinding) { 
                    item.DataItem = o; 
                    OrderedDictionary keyTable = new OrderedDictionary(DataKeyNamesInternal.Length);
                    foreach (string keyName in DataKeyNamesInternal) { 
                        object keyValue = DataBinder.GetPropertyValue(o, keyName);
                        keyTable.Add(keyName, keyValue);
                    }
                    if (keyArray.Count == dataItemIndex) { 
                        keyArray.Add(new DataKey(keyTable, DataKeyNamesInternal));
                    } 
                    else { 
                        keyArray[dataItemIndex] = new DataKey(keyTable, DataKeyNamesInternal);
                    } 
                }

                OnItemCreated(new ListViewItemEventArgs(item));
                AddControlToContainer(item, _noGroupsItemPlaceholderContainer, itemInsertLocation); 
                itemInsertLocation++;
                items.Add(item); 
 
                if (dataBinding) {
                    item.DataBind(); 
                    OnItemDataBound(new ListViewItemEventArgs(item));
                    item.DataItem = null;
                }
 
                dataItemIndex++;
                itemIndex++; 
            } 

            if (insertPosition == InsertItemPosition.LastItem) { 
                if (_itemSeparatorTemplate != null) {
                    ListViewContainer itemSeparatorContainer = new ListViewContainer();
                    AutoIDControl(itemSeparatorContainer);
                    InstantiateItemSeparatorTemplate(itemSeparatorContainer); 
                    AddControlToContainer(itemSeparatorContainer, _noGroupsItemPlaceholderContainer, itemInsertLocation);
                    itemInsertLocation++; 
                } 

                ListViewItem insertItem = CreateInsertItem(); 
                AddControlToContainer(insertItem, _noGroupsItemPlaceholderContainer, itemInsertLocation);
                itemInsertLocation++;
                itemIndex++;
            } 

            _noGroupsItemCreatedCount = itemInsertLocation - _noGroupsOriginalIndexOfItemPlaceholderInContainer; 
 
            return items;
        } 

        protected virtual IList CreateItemsInGroups(ListViewPagedDataSource dataSource, bool dataBinding, InsertItemPosition insertPosition, ArrayList keyArray) {
            // If this is the first time we're creating the control items, we need
            // to locate the groupPlaceholder container. 
            // If this is a scenario where we are recreating control items, we already
            // have the cached groupPlaceholder container. 
            if (_groupsOriginalIndexOfGroupPlaceholderInContainer == -1) { 
                _groupsGroupPlaceholderContainer = GetPreparedContainerInfo(this, false, out _groupsOriginalIndexOfGroupPlaceholderInContainer);
            } 

            int groupInsertLocation = _groupsOriginalIndexOfGroupPlaceholderInContainer;
            _groupsItemCreatedCount = 0;
 
            int itemInsertLocation = 0;
            Control itemPlaceholderContainer = null; 
 

            List items = new List(); 
            int itemIndex = 0;
            int dataItemIndex = 0;

            if (insertPosition == InsertItemPosition.FirstItem) { 
                ListViewContainer groupContainer = new ListViewContainer();
                AutoIDControl(groupContainer); 
                InstantiateGroupTemplate(groupContainer); 
                AddControlToContainer(groupContainer, _groupsGroupPlaceholderContainer, groupInsertLocation);
                groupInsertLocation++; 

                itemPlaceholderContainer = GetPreparedContainerInfo(groupContainer, true, out itemInsertLocation);

                ListViewItem insertItem = CreateInsertItem(); 
                AddControlToContainer(insertItem, itemPlaceholderContainer, itemInsertLocation);
                itemInsertLocation++; 
                itemIndex++; 
            }
 
            foreach (object o in dataSource) {
                if (itemIndex % _groupItemCount == 0) {
                    if (itemIndex != 0 && _groupSeparatorTemplate != null) {
                        ListViewContainer groupSeparatorContainer = new ListViewContainer(); 
                        AutoIDControl(groupSeparatorContainer);
                        InstantiateGroupSeparatorTemplate(groupSeparatorContainer); 
                        AddControlToContainer(groupSeparatorContainer, _groupsGroupPlaceholderContainer, groupInsertLocation); 
                        groupInsertLocation++;
                    } 
                    ListViewContainer groupContainer = new ListViewContainer();
                    AutoIDControl(groupContainer);
                    InstantiateGroupTemplate(groupContainer);
                    AddControlToContainer(groupContainer, _groupsGroupPlaceholderContainer, groupInsertLocation); 
                    groupInsertLocation++;
 
                    itemPlaceholderContainer = GetPreparedContainerInfo(groupContainer, true, out itemInsertLocation); 
                }
 
                ListViewDataItem item = CreateDataItem(dataItemIndex + StartRowIndex, dataItemIndex);
                InstantiateItemTemplate(item, dataItemIndex);

                if (dataBinding) { 
                    item.DataItem = o;
                    OrderedDictionary keyTable = new OrderedDictionary(DataKeyNamesInternal.Length); 
                    foreach (string keyName in DataKeyNamesInternal) { 
                        object keyValue = DataBinder.GetPropertyValue(o, keyName);
                        keyTable.Add(keyName, keyValue); 
                    }
                    if (keyArray.Count == dataItemIndex) {
                        keyArray.Add(new DataKey(keyTable, DataKeyNamesInternal));
                    } 
                    else {
                        keyArray[dataItemIndex] = new DataKey(keyTable, DataKeyNamesInternal); 
                    } 
                }
 
                OnItemCreated(new ListViewItemEventArgs(item));

                if (itemIndex % _groupItemCount != 0 && _itemSeparatorTemplate != null) {
                    ListViewContainer itemSeparatorContainer = new ListViewContainer(); 
                    InstantiateItemSeparatorTemplate(itemSeparatorContainer);
                    AddControlToContainer(itemSeparatorContainer, itemPlaceholderContainer, itemInsertLocation); 
                    itemInsertLocation++; 
                }
 

                AddControlToContainer(item, itemPlaceholderContainer, itemInsertLocation);
                itemInsertLocation++;
                items.Add(item); 

                if (dataBinding) { 
                    item.DataBind(); 
                    OnItemDataBound(new ListViewItemEventArgs(item));
                    item.DataItem = null; 
                }

                itemIndex++;
                dataItemIndex++; 
            }
 
            if (insertPosition == InsertItemPosition.LastItem) { 
                if (itemIndex % _groupItemCount == 0) {
                    // start a new group 
                    if (itemIndex != 0 && _groupSeparatorTemplate != null) {
                        ListViewContainer groupSeparatorContainer = new ListViewContainer();
                        AutoIDControl(groupSeparatorContainer);
                        InstantiateGroupSeparatorTemplate(groupSeparatorContainer); 
                        AddControlToContainer(groupSeparatorContainer, _groupsGroupPlaceholderContainer, groupInsertLocation);
                        groupInsertLocation++; 
                    } 
                    ListViewContainer groupContainer = new ListViewContainer();
                    AutoIDControl(groupContainer); 
                    InstantiateGroupTemplate(groupContainer);
                    AddControlToContainer(groupContainer, _groupsGroupPlaceholderContainer, groupInsertLocation);
                    groupInsertLocation++;
 
                    itemPlaceholderContainer = GetPreparedContainerInfo(groupContainer, true, out itemInsertLocation);
                } 
 
                // use the existing group
                if (itemIndex % _groupItemCount != 0 && _itemSeparatorTemplate != null) { 
                    ListViewContainer itemSeparatorContainer = new ListViewContainer();
                    InstantiateItemSeparatorTemplate(itemSeparatorContainer);
                    AddControlToContainer(itemSeparatorContainer, itemPlaceholderContainer, itemInsertLocation);
                    itemInsertLocation++; 
                }
 
                ListViewItem insertItem = CreateInsertItem(); 
                AddControlToContainer(insertItem, itemPlaceholderContainer, itemInsertLocation);
                itemInsertLocation++; 
                itemIndex++;
            }

            // fill in the rest of the items if there's an emptyItemTemplate 
            if (_emptyItemTemplate != null) {
                while (itemIndex % _groupItemCount != 0) { 
                    if (_itemSeparatorTemplate != null) { 
                        ListViewContainer itemSeparatorContainer = new ListViewContainer();
                        InstantiateItemSeparatorTemplate(itemSeparatorContainer); 
                        AddControlToContainer(itemSeparatorContainer, itemPlaceholderContainer, itemInsertLocation);
                        itemInsertLocation++;
                    }
 
                    ListViewItem emptyItem = CreateEmptyItem();
                    AddControlToContainer(emptyItem, itemPlaceholderContainer, itemInsertLocation); 
                    itemInsertLocation++; 
                    itemIndex++;
                } 
            }

            _groupsItemCreatedCount = groupInsertLocation - _groupsOriginalIndexOfGroupPlaceholderInContainer;
 
            return items;
        } 
 
        protected virtual void CreateLayoutTemplate() {
            // Reset data concerning where things are in the layout template since we're about to recreate it 
            _noGroupsOriginalIndexOfItemPlaceholderInContainer = -1;
            _noGroupsItemCreatedCount = 0;
            _noGroupsItemPlaceholderContainer = null;
 
            _groupsOriginalIndexOfGroupPlaceholderInContainer = -1;
            _groupsItemCreatedCount = 0; 
            _groupsGroupPlaceholderContainer = null; 

            Control containerControl = new Control(); 
            if (_layoutTemplate != null) {
                _layoutTemplate.InstantiateIn(containerControl);
                Controls.Add(containerControl);
            } 
            OnLayoutCreated(new EventArgs());
        } 
 
        private ListViewPagedDataSource CreatePagedDataSource() {
            ListViewPagedDataSource pagedDataSource = new ListViewPagedDataSource(); 

            pagedDataSource.StartRowIndex = _startRowIndex;
            pagedDataSource.MaximumRows = _maximumRows;
            pagedDataSource.AllowServerPaging = false; 
            pagedDataSource.TotalRowCount = 0;
 
            return pagedDataSource; 
        }
 
        private ListViewPagedDataSource CreateServerPagedDataSource(int totalRowCount) {
            ListViewPagedDataSource pagedDataSource = new ListViewPagedDataSource();

            pagedDataSource.StartRowIndex = _startRowIndex; 
            pagedDataSource.MaximumRows = _maximumRows;
            pagedDataSource.AllowServerPaging = true; 
            pagedDataSource.TotalRowCount = totalRowCount; 

            return pagedDataSource; 
        }

        public virtual void DeleteItem(int itemIndex) {
            HandleDelete(null, itemIndex); 
        }
 
        protected virtual void EnsureLayoutTemplate() { 
            if (this.Controls.Count == 0 || _instantiatedEmptyDataTemplate) {
                Controls.Clear(); 
                CreateLayoutTemplate();
            }
        }
 
        public virtual void ExtractItemValues(IOrderedDictionary itemValues, ListViewItem item, bool includePrimaryKey) {
            if (itemValues == null) { 
                throw new ArgumentNullException("itemValues"); 
            }
 
            IBindableTemplate bindableTemplate = null;
            if (item.ItemType == ListViewItemType.DataItem) {
                ListViewDataItem dataItem = item as ListViewDataItem;
                if (dataItem == null) { 
                    throw new InvalidOperationException(AtlasWeb.ListView_ItemsNotDataItems);
                } 
 
                if (dataItem.DisplayIndex == EditIndex) {
                    bindableTemplate = EditItemTemplate as IBindableTemplate; 
                }
                else if (dataItem.DisplayIndex == SelectedIndex) {
                    bindableTemplate = SelectedItemTemplate as IBindableTemplate;
                } 
                else if (dataItem.DisplayIndex % 2 == 1 && AlternatingItemTemplate != null) {
                    bindableTemplate = AlternatingItemTemplate as IBindableTemplate; 
                } 
                else {
                    bindableTemplate = ItemTemplate as IBindableTemplate; 
                }
            }
            else if (item.ItemType == ListViewItemType.InsertItem) {
                if (InsertItemTemplate != null) { 
                    bindableTemplate = InsertItemTemplate as IBindableTemplate;
                } 
            } 

            if (bindableTemplate != null) { 
                OrderedDictionary newValues = new OrderedDictionary();

                bool convertEmptyStringToNull = ConvertEmptyStringToNull;
                foreach (DictionaryEntry entry in bindableTemplate.ExtractValues(item)) { 
                    object value = entry.Value;
                    if (convertEmptyStringToNull && value is string && ((string)value).Length == 0) { 
                        newValues[entry.Key] = null; 
                    }
                    else { 
                        newValues[entry.Key] = value;
                    }
                }
 
                foreach (DictionaryEntry entry in newValues) {
                    if (includePrimaryKey || (Array.IndexOf(DataKeyNamesInternal, entry.Key) == -1)) { 
                        itemValues[entry.Key] = entry.Value; 
                    }
                } 
            }
        }

        [SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", MessageId = "0#")] 
        protected virtual Control FindPlaceholder(string containerID, Control container) {
            return container.FindControl(containerID); 
        } 

        private DataPager FindDataPager(Control control) { 
            foreach (Control c in control.Controls) {
                DataPager pager = c as DataPager;
                if (pager != null) {
                    return pager; 
                }
            } 
 
            foreach (Control c in control.Controls) {
                if (c is IPageableItemContainer) { 
                    // Exit out if we've ventured into another ListView or pageable container, since that is the likely
                    // target of any embedded pagers.
                    return null;
                } 

                DataPager pager = FindDataPager(c); 
                if (pager != null) { 
                    return pager;
                } 
            }
            return null;
        }
 
        private int GetItemIndex(ListViewItem item, string commandArgument) {
            if (item != null) { 
                ListViewDataItem dataItem = item as ListViewDataItem; 
                if (dataItem != null) {
                    return dataItem.DisplayIndex; 
                }
                return -1;
            }
            return Convert.ToInt32(commandArgument, CultureInfo.InvariantCulture); 
        }
 
        private Control GetPreparedContainerInfo(Control outerContainer, bool isItem, out int placeholderIndex) { 
            // This function locates the ItemPlaceholder for a given container and prepares
            // it for child controls. Strategy: 
            // - Locate ItemPlaceholder (throw if it's not found)
            // - Store the placeholder's container and the placeholder's location in the container
            // - Remove the ItemPlaceholder
 
            string placeholderID = isItem ? ItemPlaceholderID : GroupPlaceholderID;
            Control placeholder = FindPlaceholder(placeholderID, outerContainer); 
            if (placeholder == null) { 
                if (isItem) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_NoItemPlaceholder, ID, ItemPlaceholderID)); 
                }
                else {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_NoGroupPlaceholder, ID, GroupPlaceholderID));
                } 
            }
 
            // Save the information about where we found the itemPlaceholder because 
            // in RemoveItems() we need to know where to delete whatever we create.
            // This only applies to certain usages of this function. 
            Control placeholderContainer = placeholder.Parent;
            placeholderIndex = placeholderContainer.Controls.IndexOf(placeholder);

            // Remove the item placeholder since we're going to be 
            // adding real items starting at the index where it used to be.
            placeholderContainer.Controls.Remove(placeholder); 
 
            return placeholderContainer;
        } 

        private void HandleCancel(int itemIndex) {
            ListViewCancelMode cancelMode = ListViewCancelMode.CancelingInsert;
            if (itemIndex == EditIndex && itemIndex >= 0) { 
                cancelMode = ListViewCancelMode.CancelingEdit;
            } 
            else if (itemIndex != -1) { 
                throw new InvalidOperationException(AtlasWeb.ListView_InvalidCancel);
            } 

            ListViewCancelEventArgs e = new ListViewCancelEventArgs(itemIndex, cancelMode);
            OnItemCanceling(e);
 
            if (e.Cancel) {
                return; 
            } 

            if (IsBoundUsingDataSourceID) { 
                if (e.CancelMode == ListViewCancelMode.CancelingEdit) {
                    EditIndex = -1;
                }
                else { 
                    // cancel on an insert is simply "redatabind to clear"?
                } 
            } 

            RequiresDataBinding = true; 
        }

        private void HandleDelete(ListViewItem item, int itemIndex) {
            ListViewDataItem dataItem = item as ListViewDataItem; 
            if (itemIndex < 0 && dataItem == null) {
                throw new InvalidOperationException(AtlasWeb.ListView_InvalidDelete); 
            } 

            DataSourceView view = null; 
            bool isBoundToDataSourceControl = IsBoundUsingDataSourceID;

            if (isBoundToDataSourceControl) {
                view = GetData(); 
                if (view == null) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_NullView, ID)); 
                } 
            }
 
            if (item == null && itemIndex < Items.Count) {
                item = Items[itemIndex];
            }
 
            ListViewDeleteEventArgs e = new ListViewDeleteEventArgs(itemIndex);
 
            if (isBoundToDataSourceControl) { 
                if (item != null) {
                    ExtractItemValues(e.Values, item, false/*includePrimaryKey*/); 
                }
                if (DataKeys.Count > itemIndex) {
                    foreach (DictionaryEntry entry in DataKeys[itemIndex].Values) {
                        e.Keys.Add(entry.Key, entry.Value); 
                        if (e.Values.Contains(entry.Key)) {
                            e.Values.Remove(entry.Key); 
                        } 
                    }
                } 
            }

            OnItemDeleting(e);
 
            if (e.Cancel) {
                return; 
            } 

            _deletedItemIndex = itemIndex; 

            if (isBoundToDataSourceControl) {
                _deleteKeys = e.Keys;
                _deleteValues = e.Values; 

                view.Delete(e.Keys, e.Values, HandleDeleteCallback); 
            } 
        }
 
        private bool HandleDeleteCallback(int affectedRows, Exception ex) {
            ListViewDeletedEventArgs e = new ListViewDeletedEventArgs(affectedRows, ex);
            e.SetKeys(_deleteKeys);
            e.SetValues(_deleteValues); 

            OnItemDeleted(e); 
            _deleteKeys = null; 
            _deleteValues = null;
 
            if (ex != null && !e.ExceptionHandled) {
                return false;
            }
            EditIndex = -1; 

            if (affectedRows > 0) { 
                // Patch up the selected index if we deleted the last item on the last page. 
                if ((_totalRowCount > 0) &&
                    (_deletedItemIndex == SelectedIndex) && 
                    (_deletedItemIndex + _startRowIndex == _totalRowCount)) {
                    SelectedIndex--;
                }
            } 
            _deletedItemIndex = -1;
 
            RequiresDataBinding = true; 
            return true;
        } 

        private void HandleEdit(int itemIndex) {
            if (itemIndex < 0) {
                throw new InvalidOperationException(AtlasWeb.ListView_InvalidEdit); 
            }
 
            ListViewEditEventArgs e = new ListViewEditEventArgs(itemIndex); 
            OnItemEditing(e);
 
            if (e.Cancel) {
                return;
            }
 
            if (IsBoundUsingDataSourceID) {
                EditIndex = e.NewEditIndex; 
            } 

            RequiresDataBinding = true; 
        }

        private bool HandleEvent(EventArgs e, bool causesValidation, string validationGroup) {
            bool handled = false; 

            if (causesValidation) { 
                Page.Validate(validationGroup); 
            }
 
            ListViewCommandEventArgs dce = e as ListViewCommandEventArgs;

            if (dce != null) {
 
                OnItemCommand(dce);
                handled = true; 
 
                string command = dce.CommandName;
 
                if (String.Equals(command, DataControlCommands.SelectCommandName, StringComparison.OrdinalIgnoreCase)) {
                    HandleSelect(GetItemIndex(dce.Item, (string)dce.CommandArgument));
                }
                else if (String.Equals(command, DataControlCommands.SortCommandName, StringComparison.OrdinalIgnoreCase)) { 
                    HandleSort((string)dce.CommandArgument);
                } 
                else if (String.Equals(command, DataControlCommands.EditCommandName, StringComparison.OrdinalIgnoreCase)) { 
                    HandleEdit(GetItemIndex(dce.Item, (string)dce.CommandArgument));
                } 
                else if (String.Equals(command, DataControlCommands.CancelCommandName, StringComparison.OrdinalIgnoreCase)) {
                    HandleCancel(GetItemIndex(dce.Item, (string)dce.CommandArgument));
                }
                else if (String.Equals(command, DataControlCommands.UpdateCommandName, StringComparison.OrdinalIgnoreCase)) { 
                    HandleUpdate(dce.Item, GetItemIndex(dce.Item, (string)dce.CommandArgument), causesValidation);
                } 
                else if (String.Equals(command, DataControlCommands.DeleteCommandName, StringComparison.OrdinalIgnoreCase)) { 
                    HandleDelete(dce.Item, GetItemIndex(dce.Item, (string)dce.CommandArgument));
                } 
                else if (String.Equals(command, DataControlCommands.InsertCommandName, StringComparison.OrdinalIgnoreCase)) {
                    HandleInsert(dce.Item, causesValidation);
                }
            } 

            return handled; 
        } 

        private void HandleInsert(ListViewItem item, bool causesValidation) { 
            if (item != null && item.ItemType != ListViewItemType.InsertItem) {
                throw new InvalidOperationException(AtlasWeb.ListView_InvalidInsert);
            }
 
            if (causesValidation && Page != null && !Page.IsValid) {
                return; 
            } 

            if (item == null) { 
                item = _insertItem;
            }
            if (item == null) {
                throw new InvalidOperationException(AtlasWeb.ListView_NoInsertItem); 
            }
 
            DataSourceView view = null; 
            bool isBoundToDataSourceControl = IsBoundUsingDataSourceID;
 
            if (isBoundToDataSourceControl) {
                view = GetData();
                if (view == null) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_NullView, ID)); 
                }
            } 
 
            ListViewInsertEventArgs e = new ListViewInsertEventArgs(item);
 
            if (isBoundToDataSourceControl) {
                ExtractItemValues(e.Values, item, true/*includeKeys*/);
            }
 
            OnItemInserting(e);
 
            if (e.Cancel) { 
                return;
            } 

            if (isBoundToDataSourceControl) {
                _insertValues = e.Values;
                view.Insert(e.Values, HandleInsertCallback); 
            }
        } 
 
        private bool HandleInsertCallback(int affectedRows, Exception ex) {
            ListViewInsertedEventArgs e = new ListViewInsertedEventArgs(affectedRows, ex); 
            e.SetValues(_insertValues);

            OnItemInserted(e);
 
            _insertValues = null;
            if (ex != null && !e.ExceptionHandled) { 
                return false; 
            }
 
            if (!e.KeepInInsertMode) {
                RequiresDataBinding = true;
            }
            return true; 
        }
 
        private void HandleSelect(int itemIndex) { 
            if (itemIndex < 0) {
                throw new InvalidOperationException(AtlasWeb.ListView_InvalidSelect); 
            }

            ListViewSelectEventArgs e = new ListViewSelectEventArgs(itemIndex);
            OnSelectedIndexChanging(e); 

            if (e.Cancel) { 
                return; 
            }
 
            if (IsBoundUsingDataSourceID) {
                SelectedIndex = e.NewSelectedIndex;
            }
 
            OnSelectedIndexChanged(EventArgs.Empty);
            RequiresDataBinding = true; 
        } 

        private void HandleSort(string sortExpression) { 
            SortDirection futureSortDirection = SortDirection.Ascending;

            if ((SortExpressionInternal == sortExpression) && (SortDirectionInternal == SortDirection.Ascending)) {
                // switch direction 
                futureSortDirection = SortDirection.Descending;
            } 
            HandleSort(sortExpression, futureSortDirection); 
        }
 
        private void HandleSort(string sortExpression, SortDirection sortDirection) {
            ListViewSortEventArgs e = new ListViewSortEventArgs(sortExpression, sortDirection);
            OnSorting(e);
 
            if (e.Cancel) {
                return; 
            } 

            if (IsBoundUsingDataSourceID) { 
                ClearDataKeys();
                DataSourceView view = GetData();
                if (view == null) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_NullView, ID)); 
                }
 
                EditIndex = -1; 

                SortExpressionInternal = e.SortExpression; 
                SortDirectionInternal = e.SortDirection;
                _startRowIndex = 0;
            }
 
            OnSorted(EventArgs.Empty);
            RequiresDataBinding = true; 
        } 

        private void HandleUpdate(ListViewItem item, int itemIndex, bool causesValidation) { 
            ListViewDataItem dataItem = item as ListViewDataItem;
            if (itemIndex < 0 && dataItem == null) {
                throw new InvalidOperationException(AtlasWeb.ListView_InvalidUpdate);
            } 

            if (causesValidation && Page != null && !Page.IsValid) { 
                return; 
            }
 
            DataSourceView view = null;
            bool isBoundToDataSourceControl = IsBoundUsingDataSourceID;

            if (isBoundToDataSourceControl) { 
                view = GetData();
                if (view == null) { 
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_NullView, ID)); 
                }
            } 

            ListViewUpdateEventArgs e = new ListViewUpdateEventArgs(itemIndex);

            if (isBoundToDataSourceControl) { 
                foreach (DictionaryEntry entry in BoundFieldValues) {
                    e.OldValues.Add(entry.Key, entry.Value); 
                } 

                if (DataKeys.Count > itemIndex) { 
                    foreach (DictionaryEntry entry in DataKeys[itemIndex].Values) {
                        e.Keys.Add(entry.Key, entry.Value);
                    }
                } 

                if (dataItem == null && Items.Count > itemIndex) { 
                    dataItem = Items[itemIndex]; 
                }
 
                if (dataItem != null) {
                    ExtractItemValues(e.NewValues, dataItem, true/*includePrimaryKey*/);
                }
            } 

            OnItemUpdating(e); 
 
            if (e.Cancel) {
                return; 
            }

            if (isBoundToDataSourceControl) {
                _updateKeys = e.Keys; 
                _updateOldValues = e.OldValues;
                _updateNewValues = e.NewValues; 
 
                view.Update(e.Keys, e.NewValues, e.OldValues, HandleUpdateCallback);
            } 
        }

        private bool HandleUpdateCallback(int affectedRows, Exception ex) {
            ListViewUpdatedEventArgs e = new ListViewUpdatedEventArgs(affectedRows, ex); 
            e.SetKeys(_updateKeys);
            e.SetOldValues(_updateOldValues); 
            e.SetNewValues(_updateNewValues); 

            OnItemUpdated(e); 
            _updateKeys = null;
            _updateOldValues = null;
            _updateNewValues = null;
            if (ex != null && !e.ExceptionHandled) { 
                return false;
            } 
            // We need to databind here event if no records were affected because 
            // changing the EditIndex required a rebind.  The event args give the programmer
            // the chance to cancel the bind so the edits aren't lost. 
            if (!e.KeepInEditMode) {
                EditIndex = -1;
                RequiresDataBinding = true;
            } 
            return true;
        } 
 
        public virtual void InsertNewItem(bool causesValidation) {
            HandleInsert(null, causesValidation); 
        }

        protected virtual void InstantiateEmptyDataTemplate(Control container) {
            if (_emptyDataTemplate != null) { 
                _emptyDataTemplate.InstantiateIn(container);
            } 
        } 

        protected virtual void InstantiateEmptyItemTemplate(Control container) { 
            if (_emptyItemTemplate != null) {
                _emptyItemTemplate.InstantiateIn(container);
            }
        } 

        protected virtual void InstantiateGroupTemplate(Control container) { 
            if (_groupTemplate != null) { 
                _groupTemplate.InstantiateIn(container);
            } 
        }

        protected virtual void InstantiateGroupSeparatorTemplate(Control container) {
            if (_groupSeparatorTemplate != null) { 
                _groupSeparatorTemplate.InstantiateIn(container);
            } 
        } 

        protected virtual void InstantiateInsertItemTemplate(Control container) { 
            if (_insertItemTemplate != null) {
                _insertItemTemplate.InstantiateIn(container);
            }
        } 

        protected virtual void InstantiateItemSeparatorTemplate(Control container) { 
            if (_itemSeparatorTemplate != null) { 
                _itemSeparatorTemplate.InstantiateIn(container);
            } 
        }

        protected virtual void InstantiateItemTemplate(Control container, int displayIndex) {
            ITemplate contentTemplate = _itemTemplate; 

            if (contentTemplate == null) { 
                throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_ItemTemplateRequired, ID)); 
            }
 
            if (displayIndex % 2 == 1 && _alternatingItemTemplate != null) {
                contentTemplate = _alternatingItemTemplate;
            }
            if (displayIndex == _selectedIndex && _selectedItemTemplate != null) { 
                contentTemplate = _selectedItemTemplate;
            } 
            if (displayIndex == _editIndex && _editItemTemplate != null) { 
                contentTemplate = _editItemTemplate;
            } 

            contentTemplate.InstantiateIn(container);
        }
 
        protected internal override void LoadControlState(object savedState) {
            // Any properties that could have been set in the persistance need to be 
            // restored to their defaults if they're not in ControlState, or they will 
            // be restored to their persisted state instead of their empty state.
            _editIndex = -1; 
            _selectedIndex = -1;
            _groupItemCount = 1;
            _sortExpression = String.Empty;
            _sortDirection = SortDirection.Ascending; 
            _dataKeyNames = new string[0];
            object[] state = savedState as object[]; 
 
            if (state != null) {
                base.LoadControlState(state[0]); 

                if (state[1] != null) {
                    _editIndex = (int)state[1];
                } 

                if (state[2] != null) { 
                    _selectedIndex = (int)state[2]; 
                }
 
                if (state[3] != null) {
                    _groupItemCount = (int)state[3];
                }
 
                if (state[4] != null) {
                    _sortExpression = (string)state[4]; 
                } 

                if (state[5] != null) { 
                    _sortDirection = (SortDirection)state[5];
                }

                if (state[6] != null) { 
                    _dataKeyNames = (string[])state[6];
                } 
 
                if (state[7] != null) {
                    LoadDataKeysState(state[7]); 
                }

                if (state[8] != null) {
                    _totalRowCount = (int)state[8]; 
                }
            } 
            else { 
                base.LoadControlState(null);
            } 
            // DataPager handles the TotalRowCountAvailable event in order to create its pager fields.  Normally this
            // is fired from CreateChildControls, but when ViewState is disabled this is not getting called until after
            // postback data has been handled.  In this case the event will be fired using the control count from the
            // last request so that the pager fields can be initialized. 
            if (!IsViewStateEnabled) {
                OnTotalRowCountAvailable(new PageEventArgs(_startRowIndex, _maximumRows, _totalRowCount)); 
            } 
        }
 
        private void LoadDataKeysState(object state) {
            if (state != null) {
                object[] dataKeysState = (object[])state;
                string[] dataKeyNames = DataKeyNamesInternal; 
                int dataKeyNamesLength = dataKeyNames.Length;
 
                for (int i = 0; i < dataKeysState.Length; i++) { 
                    DataKeysArrayList.Add(new DataKey(new OrderedDictionary(dataKeyNamesLength), dataKeyNames));
                    ((IStateManager)DataKeysArrayList[i]).LoadViewState(dataKeysState[i]); 
                }
            }
        }
 
        protected override void LoadViewState(object savedState) {
            if (savedState != null) { 
                object[] state = (object[])savedState; 

                base.LoadViewState(state[0]); 
                if (state[1] != null) {
                    OrderedDictionaryStateHelper.LoadViewState((OrderedDictionary)BoundFieldValues, (ArrayList)state[1]);
                }
            } 
            else {
                base.LoadViewState(savedState); 
            } 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "1#")]
        protected override bool OnBubbleEvent(object source, EventArgs e) {
            bool causesValidation = false;
            string validationGroup = String.Empty; 

            ListViewCommandEventArgs commandEventArgs = e as ListViewCommandEventArgs; 
            // todo: rethink this.  Should everything in the layout template be bubbled 
            // up as a ListViewCommand?
            if (commandEventArgs == null && e is CommandEventArgs) { 
                // Use a new EmptyItem ListViewItem here so when HandleEvent tries to parse out the data item index,
                // the user gets a nice message about how this button should be in a data item.
                commandEventArgs = new ListViewCommandEventArgs(new ListViewItem(ListViewItemType.EmptyItem), source, (CommandEventArgs)e);
            } 

            if (commandEventArgs != null) { 
                IButtonControl button = commandEventArgs.CommandSource as IButtonControl; 
                if (button != null) {
                    causesValidation = button.CausesValidation; 
                    validationGroup = button.ValidationGroup;
                }
            }
            return HandleEvent(commandEventArgs, causesValidation, validationGroup); 
        }
 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected internal override void OnInit(EventArgs e) {
            base.OnInit(e); 
            if (Page != null) {
                if (DataKeyNames.Length > 0) {
                    Page.RegisterRequiresViewStateEncryption();
                } 
                Page.RegisterRequiresControlState(this);
            } 
        } 

        ///  
        /// Raises the event.
        /// 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnItemCanceling(ListViewCancelEventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventItemCanceling];
            if (handler != null) { 
                handler(this, e); 
            }
            else { 
                if (IsBoundUsingDataSourceID == false && e.Cancel == false) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_UnhandledEvent, ID, "ItemCanceling"));
                }
            } 
        }
 
        ///  
        /// Raises the  event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnItemCommand(ListViewCommandEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventItemCommand];
            if (handler != null) { 
                handler(this, e);
            } 
        } 

        ///  
        /// Raises the  event.
        /// 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnItemCreated(ListViewItemEventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventItemCreated];
            if (handler != null) { 
                handler(this, e); 
            }
        } 

        /// 
        /// Raises the  event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnItemDataBound(ListViewItemEventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventItemDataBound]; 
            if (handler != null) {
                handler(this, e); 
            }
        }

        ///  
        /// Raises the event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnItemDeleted(ListViewDeletedEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventItemDeleted]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        ///  
        /// Raises the  event. 
        /// 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnItemDeleting(ListViewDeleteEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventItemDeleting];
            if (handler != null) {
                handler(this, e); 
            }
            else { 
                if (IsBoundUsingDataSourceID == false && e.Cancel == false) { 
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_UnhandledEvent, ID, "ItemDeleting"));
                } 
            }
        }

        ///  
        /// Raises the  event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnItemEditing(ListViewEditEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventItemEditing]; 
            if (handler != null) {
                handler(this, e);
            }
            else { 
                if (IsBoundUsingDataSourceID == false && e.Cancel == false) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_UnhandledEvent, ID, "ItemEditing")); 
                } 
            }
        } 

        /// 
        /// Raises the event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnItemInserted(ListViewInsertedEventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventItemInserted]; 
            if (handler != null) {
                handler(this, e); 
            }
        }

        ///  
        /// Raises the  event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnItemInserting(ListViewInsertEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventItemInserting]; 
            if (handler != null) {
                handler(this, e);
            }
            else { 
                if (IsBoundUsingDataSourceID == false && e.Cancel == false) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_UnhandledEvent, ID, "ItemInserting")); 
                } 
            }
        } 

        /// 
        /// Raises the event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnItemUpdated(ListViewUpdatedEventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventItemUpdated]; 
            if (handler != null) handler(this, e);
        } 

        /// 
        /// Raises the  event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnItemUpdating(ListViewUpdateEventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventItemUpdating]; 
            if (handler != null) {
                handler(this, e); 
            }
            else {
                if (IsBoundUsingDataSourceID == false && e.Cancel == false) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_UnhandledEvent, ID, "ItemUpdating")); 
                }
            } 
        } 

        ///  
        /// Raises the  event.
        /// 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnLayoutCreated(EventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventLayoutCreated];
            if (handler != null) { 
                handler(this, e); 
            }
        } 

        /// 
        /// Raises the  event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnPagePropertiesChanged(EventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventPagePropertiesChanged]; 
            if (handler != null) {
                handler(this, e); 
            }
        }

        ///  
        /// Raises the  event.
        ///  
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnPagePropertiesChanging(PagePropertiesChangingEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventPagePropertiesChanging]; 
            if (handler != null) {
                handler(this, e);
            }
        } 

        ///  
        /// Raises the event of a . 
        /// 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnTotalRowCountAvailable(PageEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventTotalRowCountAvailable];
            if (handler != null) {
                handler(this, e); 
            }
        } 
 
        /// 
        /// Raises the event of a . 
        /// 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnSelectedIndexChanged(EventArgs e) {
            EventHandler handler = (EventHandler)Events[EventSelectedIndexChanged]; 
            if (handler != null) {
                handler(this, e); 
            } 
        }
 
        /// 
        /// Raises the event of a .
        /// 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnSelectedIndexChanging(ListViewSelectEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventSelectedIndexChanging]; 
            if (handler != null) { 
                handler(this, e);
            } 
            else {
                if (IsBoundUsingDataSourceID == false && e.Cancel == false) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_UnhandledEvent, ID, "SelectedIndexChanging"));
                } 
            }
        } 
 
        /// 
        /// Raises the event of a . 
        /// 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")]
        protected virtual void OnSorted(EventArgs e) {
            EventHandler handler = (EventHandler)Events[EventSorted]; 
            if (handler != null) {
                handler(this, e); 
            } 
        }
 
        /// 
        /// Raises the  event.
        /// 
        [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] 
        protected virtual void OnSorting(ListViewSortEventArgs e) {
            EventHandler handler = (EventHandler)Events[EventSorting]; 
            if (handler != null) { 
                handler(this, e);
            } 
            else {
                if (IsBoundUsingDataSourceID == false && e.Cancel == false) {
                    throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_UnhandledEvent, ID, "Sorting"));
                } 
            }
        } 
 
        /// 
        /// Overriden by DataBoundControl to use its properties to determine the real 
        /// data source that the control should bind to. It then clears the existing
        /// control hierarchy, and calls createChildControls to create a new control
        /// hierarchy based on the resolved data source.
        /// The implementation resolves various data source related properties to 
        /// arrive at the appropriate IEnumerable implementation to use as the real
        /// data source. 
        /// When resolving data sources, the DataSourceControlID takes highest precedence. 
        /// In this mode, DataMember is used to access the appropriate list from the
        /// DataControl. 
        /// If DataSourceControlID is not set, the value of the DataSource property is used.
        /// In this second alternative, DataMember is used to extract the appropriate
        /// list if the control has been handed an IListSource as a data source.
        ///  
        protected internal override void PerformDataBinding(IEnumerable data) {
            base.PerformDataBinding(data); 
 
            TrackViewState();
 
            int controlCount = CreateChildControls(data, true);
            ChildControlsCreated = true;
            ViewState[ItemCountViewStateKey] = controlCount;
 
            int editIndex = EditIndex;
            if (IsBoundUsingDataSourceID && editIndex != -1 && editIndex < Items.Count && IsViewStateEnabled) { 
                BoundFieldValues.Clear(); 
                ExtractItemValues(BoundFieldValues, Items[editIndex], false/*includePrimaryKey*/);
            } 

        }

        protected override void PerformSelect() { 
            EnsureLayoutTemplate();
 
            if (DesignMode) { 
                // Try to find a pager that will control the paging on this control.
                // In design mode, an embedded pager will not have a designer but will 
                // be the runtime control itself.  We want the max rows so the ListView
                // renders with the right page size.
                DataPager pager = FindDataPager(this);
                if (pager != null) { 
                    _maximumRows = pager.PageSize;
                } 
            } 

            base.PerformSelect(); 
        }

        protected virtual void RemoveItems() {
            if (_groupTemplate != null) { 
                // If we're in grouped mode, delete all the items created in CreateItemsInGroups().
                if (_groupsItemCreatedCount > 0) { 
                    for (int i = 0; i < _groupsItemCreatedCount; i++) { 
                        _groupsGroupPlaceholderContainer.Controls.RemoveAt(_groupsOriginalIndexOfGroupPlaceholderInContainer);
                    } 
                    _groupsItemCreatedCount = 0;
                }
            }
            else { 
                // If we're not in grouped mode, delete all the items
                // created in CreateItemsWithoutGroups(). 
                if (_noGroupsItemCreatedCount > 0) { 
                    for (int i = 0; i < _noGroupsItemCreatedCount; i++) {
                        _noGroupsItemPlaceholderContainer.Controls.RemoveAt(_noGroupsOriginalIndexOfItemPlaceholderInContainer); 
                    }
                    _noGroupsItemCreatedCount = 0;
                }
            } 
            _autoIDIndex = 0;
        } 
 
        protected internal override void Render(HtmlTextWriter writer) {
            // Render only the contents.  We don't want a rendered span tag around the control. 
            RenderContents(writer);
        }

        ///  
        /// Saves the control state for those properties that should persist across postbacks
        ///   even when EnableViewState=false. 
        ///  
        protected internal override object SaveControlState() {
            object baseState = base.SaveControlState(); 
            if (baseState != null ||
                _editIndex != -1 ||
                _selectedIndex != -1 ||
                _groupItemCount != 1 || 
                (_sortExpression != null && _sortExpression.Length != 0) ||
                _sortDirection != SortDirection.Ascending || 
                _totalRowCount != -1 || 
                (_dataKeyNames != null && _dataKeyNames.Length != 0) ||
                (_dataKeysArrayList != null && _dataKeysArrayList.Count > 0)) { 

                object[] state = new object[9];

                state[0] = baseState; 
                state[1] = (_editIndex == -1) ? null : (object)_editIndex;
                state[2] = (_selectedIndex == -1) ? null : (object)_selectedIndex; 
                state[3] = (_groupItemCount == 1) ? null : (object)_groupItemCount; 
                state[4] = (_sortExpression == null || _sortExpression.Length == 0) ? null : (object)_sortExpression;
                state[5] = (_sortDirection == SortDirection.Ascending) ? null : (object)((int)_sortDirection); 
                state[6] = (_dataKeyNames == null || _dataKeyNames.Length == 0) ? null : (object)_dataKeyNames;
                state[7] = SaveDataKeysState();
                state[8] = (_totalRowCount == -1) ? null : (object)_totalRowCount;
 
                return state;
            } 
            return true;    // return a dummy that ensures LoadControlState gets called but minimizes persisted size. 
        }
 
        private object SaveDataKeysState() {
            object keyState = new object();
            int dataKeyCount = 0;
 
            if (_dataKeysArrayList != null && _dataKeysArrayList.Count > 0) {
                dataKeyCount = _dataKeysArrayList.Count; 
                keyState = new object[dataKeyCount]; 
                for (int i = 0; i < dataKeyCount; i++) {
                    ((object[])keyState)[i] = ((IStateManager)_dataKeysArrayList[i]).SaveViewState(); 
                }
            }
            return (_dataKeysArrayList == null || dataKeyCount == 0) ? null : keyState;
        } 

        protected override object SaveViewState() { 
            object baseState = base.SaveViewState(); 
            object boundFieldValuesState = (_boundFieldValues != null) ? OrderedDictionaryStateHelper.SaveViewState(_boundFieldValues) : null;
 
            object[] state = new object[2];
            state[0] = baseState;
            state[1] = boundFieldValuesState;
 
            return state;
        } 
 
        private void SelectCallback(IEnumerable data) {
            // The data source should have thrown.  If we're here, it didn't.  We'll throw for it 
            // with a generic message.
            throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.ListView_DataSourceDoesntSupportPaging, DataSourceID));
        }
 
        private void SetRequiresDataBindingIfInitialized() {
            if (Initialized) { 
                RequiresDataBinding = true; 
            }
        } 

        public virtual void Sort(string sortExpression, SortDirection sortDirection) {
            HandleSort(sortExpression, sortDirection);
        } 

        public virtual void UpdateItem(int itemIndex, bool causesValidation) { 
            HandleUpdate(null, itemIndex, causesValidation); 
        }
 
        #region IPageableItemContainer
        int IPageableItemContainer.StartRowIndex {
            get {
                return StartRowIndex; 
            }
        } 
 
        // Overridable version
        protected virtual int StartRowIndex { 
            get {
                return _startRowIndex;
            }
        } 

        int IPageableItemContainer.MaximumRows { 
            get { 
                return MaximumRows;
            } 
        }

        // Overridable version
        protected virtual int MaximumRows { 
            get {
                return _maximumRows; 
            } 
        }
 
        void IPageableItemContainer.SetPageProperties(int startRowIndex, int maximumRows, bool databind) {
            SetPageProperties(startRowIndex, maximumRows, databind);
        }
 
        // Overridable version
        protected virtual void SetPageProperties(int startRowIndex, int maximumRows, bool databind) { 
            if (maximumRows < 1) { 
                throw new ArgumentOutOfRangeException("maximumRows");
            } 
            if (startRowIndex < 0) {
                throw new ArgumentOutOfRangeException("startRowIndex");
            }
 
            if (_startRowIndex != startRowIndex || _maximumRows != maximumRows) {
                PagePropertiesChangingEventArgs args = new PagePropertiesChangingEventArgs(startRowIndex, maximumRows); 
                if (databind) { 
                    // This event is cancellable, and its properties aren't settable, because changing them would
                    // create a strange disconnect between the pager and the ListView.  You have to set 
                    // these properties on the pager if you want to change them.  This is a notification event.
                    OnPagePropertiesChanging(args);
                }
 
                _startRowIndex = args.StartRowIndex;
                _maximumRows = args.MaximumRows; 
 
                if (databind) {
                    OnPagePropertiesChanged(EventArgs.Empty); 
                }
            }

            if (databind) { 
                RequiresDataBinding = true;
            } 
        } 

        [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", 
                         Justification = "Unlikely that a derived type would re-implement this event.")]
        event EventHandler IPageableItemContainer.TotalRowCountAvailable {
            add {
                Events.AddHandler(EventTotalRowCountAvailable, value); 
            }
            remove { 
                Events.RemoveHandler(EventTotalRowCountAvailable, value); 
            }
        } 
        #endregion IPageableItemContainer
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK