ListView.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / 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)]
    [ToolboxItemFilterAttribute(AssemblyRef.SystemWebExtensions, ToolboxItemFilterType.Require)] 
    public class ListView : DataBoundControl, INamingContainer, IPageableItemContainer, IPersistedSelector { 
        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 _modelValidationGroup; 
        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 DataKey _persistedDataKey; 
 
        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 > -1 && _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;
            } 
        }

        [
        WebCategory("Behavior"), 
        DefaultValue(false),
        ResourceDescription("ListView_EnableModelValidation") 
        ] 
        public virtual bool EnableModelValidation {
            get { 
                object o = ViewState["EnableModelValidation"];
                if (o != null) {
                    return (bool)o;
                } 
                return false;
            } 
            set { 
                ViewState["EnableModelValidation"] = 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", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId="ID") 
        ]
        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", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId="ID")
        ]
        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);
            } 
        }

        [
        Browsable(false) 
        ]
        public virtual DataKey SelectedPersistedDataKey { 
            get { 
                return _persistedDataKey;
            } 
            set {
                _persistedDataKey = value;
                if (IsTrackingViewState && (_persistedDataKey != null)) {
                    ((IStateManager)_persistedDataKey).TrackViewState(); 
                }
            } 
        } 

        // 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");
            } 

            DataBoundControlHelper.ExtractValuesFromBindableControls(itemValues, item);

            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", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID")] 
        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) { 
                // If there is no validator in the validation group that could make sense
                // of the error, return false to proceed with standard exception handling. 
                // But if there is one, we want to let it display its error instead of throwing. 
                if (PageIsValidAfterModelException()) {
                    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;
 
            _modelValidationGroup = null;
            if (causesValidation) { 
                Page.Validate(validationGroup); 
                if (EnableModelValidation) {
                    _modelValidationGroup = 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) { 
                // If there is no validator in the validation group that could make sense
                // of the error, return false to proceed with standard exception handling.
                // But if there is one, we want to let it display its error instead of throwing.
                if (PageIsValidAfterModelException()) { 
                    return false;
                } 
                e.KeepInInsertMode = true; 
            }
 
            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) { 
                // If there is no validator in the validation group that could make sense
                // of the error, return false to proceed with standard exception handling. 
                // But if there is one, we want to let it display its error instead of throwing. 
                if (PageIsValidAfterModelException()) {
                    return false; 
                }
                e.KeepInEditMode = true;
            }
            // 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];
                }

                if (state[9] != null) { 
                    if ((_dataKeyNames != null) && (_dataKeyNames.Length > 0)) {
                        _persistedDataKey = new DataKey(new OrderedDictionary(_dataKeyNames.Length), _dataKeyNames); 
                        ((IStateManager)_persistedDataKey).LoadViewState(state[9]); 
                    }
                } 
            }
            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; 

                ClearDataKeys();
                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) { 
            if (DataKeyNamesInternal.Length > 0) {
                // update the virtual selection to use the new selection
                SelectedPersistedDataKey = SelectedDataKey;
            } 

            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"));
                } 
            } 
        }
 
        private bool PageIsValidAfterModelException() {
            if (_modelValidationGroup == null) {
                return true;
            } 
            Page.Validate(_modelValidationGroup);
            return Page.IsValid; 
        } 

        ///  
        /// 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*/); 
            }

            // default the virtual selection to the first item
            if (_persistedDataKey == null) { 
                DataKeyArray keys = DataKeys;
                if (keys != null && keys.Count > 0) { 
                    _persistedDataKey = keys[0]; 
                }
            } 
        }

        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[10];

                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;
                state[9] = (_persistedDataKey == null) ? null :
                    ((IStateManager)_persistedDataKey).SaveViewState(); 

                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 
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "databind", 
            Justification = "Cannot change to 'dataBind' as would break binary compatibility with legacy code.")]
        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 

        #region IPersistedSelector implementation 
 
        DataKey IPersistedSelector.DataKey {
            get { 
                return SelectedPersistedDataKey;
            }
            set {
                SelectedPersistedDataKey = value; 
            }
        } 
        #endregion 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     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)]
    [ToolboxItemFilterAttribute(AssemblyRef.SystemWebExtensions, ToolboxItemFilterType.Require)] 
    public class ListView : DataBoundControl, INamingContainer, IPageableItemContainer, IPersistedSelector { 
        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 _modelValidationGroup; 
        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 DataKey _persistedDataKey; 
 
        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 > -1 && _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;
            } 
        }

        [
        WebCategory("Behavior"), 
        DefaultValue(false),
        ResourceDescription("ListView_EnableModelValidation") 
        ] 
        public virtual bool EnableModelValidation {
            get { 
                object o = ViewState["EnableModelValidation"];
                if (o != null) {
                    return (bool)o;
                } 
                return false;
            } 
            set { 
                ViewState["EnableModelValidation"] = 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", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId="ID") 
        ]
        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", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId="ID")
        ]
        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);
            } 
        }

        [
        Browsable(false) 
        ]
        public virtual DataKey SelectedPersistedDataKey { 
            get { 
                return _persistedDataKey;
            } 
            set {
                _persistedDataKey = value;
                if (IsTrackingViewState && (_persistedDataKey != null)) {
                    ((IStateManager)_persistedDataKey).TrackViewState(); 
                }
            } 
        } 

        // 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");
            } 

            DataBoundControlHelper.ExtractValuesFromBindableControls(itemValues, item);

            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", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID")] 
        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) { 
                // If there is no validator in the validation group that could make sense
                // of the error, return false to proceed with standard exception handling. 
                // But if there is one, we want to let it display its error instead of throwing. 
                if (PageIsValidAfterModelException()) {
                    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;
 
            _modelValidationGroup = null;
            if (causesValidation) { 
                Page.Validate(validationGroup); 
                if (EnableModelValidation) {
                    _modelValidationGroup = 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) { 
                // If there is no validator in the validation group that could make sense
                // of the error, return false to proceed with standard exception handling.
                // But if there is one, we want to let it display its error instead of throwing.
                if (PageIsValidAfterModelException()) { 
                    return false;
                } 
                e.KeepInInsertMode = true; 
            }
 
            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) { 
                // If there is no validator in the validation group that could make sense
                // of the error, return false to proceed with standard exception handling. 
                // But if there is one, we want to let it display its error instead of throwing. 
                if (PageIsValidAfterModelException()) {
                    return false; 
                }
                e.KeepInEditMode = true;
            }
            // 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];
                }

                if (state[9] != null) { 
                    if ((_dataKeyNames != null) && (_dataKeyNames.Length > 0)) {
                        _persistedDataKey = new DataKey(new OrderedDictionary(_dataKeyNames.Length), _dataKeyNames); 
                        ((IStateManager)_persistedDataKey).LoadViewState(state[9]); 
                    }
                } 
            }
            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; 

                ClearDataKeys();
                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) { 
            if (DataKeyNamesInternal.Length > 0) {
                // update the virtual selection to use the new selection
                SelectedPersistedDataKey = SelectedDataKey;
            } 

            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"));
                } 
            } 
        }
 
        private bool PageIsValidAfterModelException() {
            if (_modelValidationGroup == null) {
                return true;
            } 
            Page.Validate(_modelValidationGroup);
            return Page.IsValid; 
        } 

        ///  
        /// 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*/); 
            }

            // default the virtual selection to the first item
            if (_persistedDataKey == null) { 
                DataKeyArray keys = DataKeys;
                if (keys != null && keys.Count > 0) { 
                    _persistedDataKey = keys[0]; 
                }
            } 
        }

        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[10];

                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;
                state[9] = (_persistedDataKey == null) ? null :
                    ((IStateManager)_persistedDataKey).SaveViewState(); 

                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 
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "databind", 
            Justification = "Cannot change to 'dataBind' as would break binary compatibility with legacy code.")]
        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 

        #region IPersistedSelector implementation 
 
        DataKey IPersistedSelector.DataKey {
            get { 
                return SelectedPersistedDataKey;
            }
            set {
                SelectedPersistedDataKey = value; 
            }
        } 
        #endregion 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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