New tests.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListView.cs
index d2bb16d19a90428a4029dce0603d3a7af7190d1e..6702dad150c14797a7a5026b92fc7796a39f1c5b 100644 (file)
@@ -26,7 +26,6 @@
 //
 // TODO:
 //   - Feedback for item activation, change in cursor types as mouse moves.
-//   - HideSelection
 //   - LabelEdit
 //   - Drag and drop
 
@@ -143,11 +142,17 @@ namespace System.Windows.Forms
 
                        header_control = new HeaderControl (this);
                        header_control.Visible = false;
+                       Controls.AddImplicit (header_control);
+
                        item_control = new ItemControl (this);
-                       item_control.Visible = true;
+                       Controls.AddImplicit (item_control);
 
                        h_scroll = new HScrollBar ();
+                       Controls.AddImplicit (this.h_scroll);
+
                        v_scroll = new VScrollBar ();
+                       Controls.AddImplicit (this.v_scroll);
+
                        h_marker = v_marker = 0;
                        keysearch_tickcnt = 0;
 
@@ -159,8 +164,10 @@ namespace System.Windows.Forms
 
                        // event handlers
                        base.KeyDown += new KeyEventHandler(ListView_KeyDown);
-                       base.Paint += new PaintEventHandler (ListView_Paint);
                        SizeChanged += new EventHandler (ListView_SizeChanged);
+                       GotFocus += new EventHandler (FocusChanged);
+                       LostFocus += new EventHandler (FocusChanged);
+                       MouseWheel += new MouseEventHandler(ListView_MouseWheel);
 
                        this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
                }
@@ -179,9 +186,13 @@ namespace System.Windows.Forms
                        }
                }
 
-               internal bool CanMultiselect {
+               bool multiselecting;
+
+               bool CanMultiselect {
                        get {
-                               if (multiselect && (XplatUI.State.ModifierKeys & (Keys.Control | Keys.Shift)) != 0)
+                               if (multiselecting)
+                                       return true;
+                               else if (multiselect && (XplatUI.State.ModifierKeys & (Keys.Control | Keys.Shift)) != 0)
                                        return true;
                                else
                                        return false;
@@ -290,6 +301,13 @@ namespace System.Windows.Forms
                        get { return check_boxes; }
                        set {
                                if (check_boxes != value) {
+#if NET_2_0
+                                       if (value && View == View.Tile)
+                                               throw new NotSupportedException ("CheckBoxes are not"
+                                                       + " supported in Tile view. Choose a different"
+                                                       + " view or set CheckBoxes to false.");
+#endif
+
                                        check_boxes = value;
                                        this.Redraw (true);
                                }
@@ -319,8 +337,6 @@ namespace System.Windows.Forms
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public ListViewItem FocusedItem {
                        get {
-                               if (focused_item == null && Focused && items.Count > 0)
-                                       focused_item = items [0];
                                return focused_item;
                        }
                }
@@ -429,8 +445,17 @@ namespace System.Windows.Forms
                [Browsable (false)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public IComparer ListViewItemSorter {
-                       get { return item_sorter; }
-                       set { item_sorter = value; }
+                       get {
+                               if (View != View.SmallIcon && View != View.LargeIcon && item_sorter is ItemComparer)
+                                       return null;
+                               return item_sorter;
+                       }
+                       set {
+                               if (item_sorter != value) {
+                                       item_sorter = value;
+                                       Sort ();
+                               }
+                       }
                }
 
                [DefaultValue (true)]
@@ -462,6 +487,18 @@ namespace System.Windows.Forms
                        get { return selected_items; }
                }
 
+#if NET_2_0
+               [MonoTODO("Implement")]
+               public bool ShowGroups {
+                       get {
+                               return false;
+                       }
+
+                       set {
+                       }
+               }
+#endif
+
                [DefaultValue (null)]
                public ImageList SmallImageList {
                        get { return small_image_list; }
@@ -475,15 +512,46 @@ namespace System.Windows.Forms
                public SortOrder Sorting {
                        get { return sort_order; }
                        set { 
-                               if (value != SortOrder.Ascending && value != SortOrder.Descending  && 
-                                       value != SortOrder.None) {
-                                       throw new InvalidEnumArgumentException (string.Format
-                                               ("Enum argument value '{0}' is not valid for Sorting", value));
+                               if (!Enum.IsDefined (typeof (SortOrder), value)) {
+                                       throw new InvalidEnumArgumentException ("value", (int) value,
+                                               typeof (SortOrder));
                                }
                                
-                               if (sort_order != value)  {                     
-                                       sort_order = value; 
+                               if (sort_order == value)
+                                       return;
+
+                               sort_order = value;
+
+                               if (value == SortOrder.None) {
+                                       if (item_sorter != null) {
+                                               // ListViewItemSorter should never be reset for SmallIcon
+                                               // and LargeIcon view
+                                               if (View != View.SmallIcon && View != View.LargeIcon)
+#if NET_2_0
+                                                       item_sorter = null;
+#else
+                                                       // in .NET 1.1, only internal IComparer would be
+                                                       // set to null
+                                                       if (item_sorter is ItemComparer)
+                                                               item_sorter = null;
+#endif
+                                       }
                                        this.Redraw (false);
+                               } else {
+                                       if (item_sorter == null)
+                                               item_sorter = new ItemComparer (value);
+                                       if (item_sorter is ItemComparer) {
+#if NET_2_0
+                                               item_sorter = new ItemComparer (value);
+#else
+                                               // in .NET 1.1, the sort order is not updated for
+                                               // SmallIcon and LargeIcon views if no custom IComparer
+                                               // is set
+                                               if (View != View.SmallIcon && View != View.LargeIcon)
+                                                       item_sorter = new ItemComparer (value);
+#endif
+                                       }
+                                       Sort ();
                                }
                        }
                }
@@ -535,17 +603,34 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               [MonoTODO("Implement")]
+               public bool UseCompatibleStateImageBehavior {
+                       get {
+                               return false;
+                       }
+
+                       set {
+                       }
+               }
+#endif
+
                [DefaultValue (View.LargeIcon)]
                public View View {
                        get { return view; }
                        set { 
-                               if (value != View.Details && value != View.LargeIcon  && 
-                                       value != View.List  && value != View.SmallIcon  ) {
-                                       throw new InvalidEnumArgumentException (string.Format
-                                               ("Enum argument value '{0}' is not valid for View", value));
-                               }
-                               
+                               if (!Enum.IsDefined (typeof (View), value))
+                                       throw new InvalidEnumArgumentException ("value", (int) value,
+                                               typeof (View));
+
                                if (view != value) {
+#if NET_2_0
+                                       if (CheckBoxes && value == View.Tile)
+                                               throw new NotSupportedException ("CheckBoxes are not"
+                                                       + " supported in Tile view. Choose a different"
+                                                       + " view or set CheckBoxes to false.");
+#endif
+
                                        h_scroll.Value = v_scroll.Value = 0;
                                        view = value; 
                                        Redraw (true);
@@ -577,9 +662,14 @@ namespace System.Windows.Forms
                
                internal int LastVisibleIndex {                 
                        get {                                                   
-                               for (int i = FirstVisibleIndex; i < Items.Count; i++) {                                         
-                                       if (Items[i].Bounds.Y > ClientRectangle.Bottom)                                         
-                                                       return i -1;                                    
+                               for (int i = FirstVisibleIndex; i < Items.Count; i++) {
+                                       if (View == View.List || Alignment == ListViewAlignment.Left) {
+                                               if (Items[i].Bounds.X > ClientRectangle.Right)
+                                                       return i - 1;                                   
+                                       } else {
+                                               if (Items[i].Bounds.Y > ClientRectangle.Bottom)
+                                                       return i - 1;                                   
+                                       }
                                }
                                
                                return Items.Count - 1;
@@ -739,9 +829,17 @@ namespace System.Windows.Forms
                        if (!this.scrollable || this.items.Count <= 0) {
                                h_scroll.Visible = false;
                                v_scroll.Visible = false;
+                               item_control.Location = new Point (0, header_control.Height);
+                               item_control.Height = ClientRectangle.Width - header_control.Height;
+                               item_control.Width = ClientRectangle.Width;
+                               header_control.Width = ClientRectangle.Width;
                                return;
                        }
 
+                       // Don't calculate if the view is not displayable
+                       if (client_area.Height < 0 || client_area.Width < 0)
+                               return;
+
                        // making a scroll bar visible might make
                        // other scroll bar visible                     
                        if (layout_wd > client_area.Right) {
@@ -875,6 +973,7 @@ namespace System.Windows.Forms
                {
                        header_control.Visible = false;
                        header_control.Size = Size.Empty;
+                       item_control.Visible = true;
                        item_control.Location = Point.Empty;
 
                        if (items.Count == 0)
@@ -885,13 +984,13 @@ namespace System.Windows.Forms
                        Rectangle area = ClientRectangle;
 
                        if (left_aligned) {
-                               rows = (int) Math.Floor ((double)area.Height / (double)(sz.Height + y_spacing));
-                               if (rows == 0)
+                               rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(sz.Height + y_spacing));
+                               if (rows <= 0)
                                        rows = 1;
                                cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
                        } else {
-                               cols = (int) Math.Floor ((double)area.Width / (double)(sz.Width + x_spacing));
-                               if (cols == 0)
+                               cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(sz.Width + x_spacing));
+                               if (cols <= 0)
                                        cols = 1;
                                rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
                        }
@@ -927,12 +1026,6 @@ namespace System.Windows.Forms
 
                void LayoutHeader ()
                {
-                       if (columns.Count == 0 || header_style == ColumnHeaderStyle.None) {
-                               header_control.Visible = false;
-                               header_control.Size = Size.Empty;
-                               return;
-                       }
-
                        int x = 0;
                        for (int i = 0; i < Columns.Count; i++) {
                                ColumnHeader col = GetReorderedColumn (i);
@@ -942,15 +1035,30 @@ namespace System.Windows.Forms
                                x += col.Wd;
                        }
 
-                       header_control.Width = x;
-                       header_control.Height = columns [0].Ht;
-                       header_control.Visible = true;
+                       if (x < ClientRectangle.Width)
+                               x = ClientRectangle.Width;
+
+                       if (header_style == ColumnHeaderStyle.None) {
+                               header_control.Visible = false;
+                               header_control.Size = Size.Empty;
+                       } else {
+                               header_control.Width = x;
+                               header_control.Height = columns [0].Ht;
+                               header_control.Visible = true;
+                       }
                }
 
                void LayoutDetails ()
                {
+                       if (columns.Count == 0) {
+                               header_control.Visible = false;
+                               item_control.Visible = false;
+                               return;
+                       }
+
                        LayoutHeader ();
 
+                       item_control.Visible = true;
                        item_control.Location = new Point (0, header_control.Height);
 
                        int y = 0; 
@@ -1003,16 +1111,13 @@ namespace System.Windows.Forms
 
                                if (!CanMultiselect && SelectedItems.Count > 0) {
                                        SelectedItems.Clear ();
-                                       SelectedIndices.list.Clear ();
                                }
 
-                               if (!SelectedItems.Contains (item)) {
+                               if (!SelectedItems.list.Contains (item)) {
                                        SelectedItems.list.Add (item);
-                                       SelectedIndices.list.Add (item.Index);
                                }
                        } else {
                                SelectedItems.list.Remove (item);
-                               SelectedIndices.list.Remove (item.Index);
                        }
                }
 
@@ -1081,7 +1186,7 @@ namespace System.Windows.Forms
                                return item_matrix [row - 1, col].Index;
 
                        case Keys.Down:
-                               if (row == (rows - 1))
+                               if (row == (rows - 1) || row == Items.Count - 1)
                                        return -1;
                                while (item_matrix [row + 1, col] == null)
                                       col--;   
@@ -1094,12 +1199,23 @@ namespace System.Windows.Forms
 
                ListViewItem selection_start;
 
-               private void SelectItems (ArrayList sel_items)
+               private bool SelectItems (ArrayList sel_items)
                {
-                       SelectedItems.Clear ();
-                       SelectedIndices.list.Clear ();
+                       bool changed = false;
+                       multiselecting = true;
+                       ArrayList curr_items = (ArrayList) SelectedItems.list.Clone ();
+                       foreach (ListViewItem item in curr_items)
+                               if (!sel_items.Contains (item)) {
+                                       item.Selected = false;
+                                       changed = true;
+                               }
                        foreach (ListViewItem item in sel_items)
-                               item.Selected = true;
+                               if (!item.Selected) {
+                                       item.Selected = true;
+                                       changed = true;
+                               }
+                       multiselecting = false;
+                       return changed;
                }
 
                private void UpdateMultiSelection (int index)
@@ -1125,23 +1241,27 @@ namespace System.Windows.Forms
                                                    curr.col >= left && curr.col <= right)
                                                        list.Add (curr);
                                }
-                               SelectItems (list);
+                               if (SelectItems (list))
+                                       OnSelectedIndexChanged (EventArgs.Empty);
                        } else if (!ctrl_pressed) {
                                SelectedItems.Clear ();
-                               SelectedIndices.list.Clear ();
                                item.Selected = true;
                                selection_start = item;
+                               OnSelectedIndexChanged (EventArgs.Empty);
                        }
                }
 
                private void ListView_KeyDown (object sender, KeyEventArgs ke)
                {                       
-                       if (ke.Handled || Items.Count == 0)
+                       if (ke.Handled || Items.Count == 0 || !item_control.Visible)
                                return;
 
                        int index = -1;
                        ke.Handled = true;
 
+                       if (FocusedItem == null)
+                               SetFocusedItem (Items [0]);
+
                        switch (ke.KeyCode) {
 
                        case Keys.End:
@@ -1169,8 +1289,10 @@ namespace System.Windows.Forms
 
                        if (MultiSelect)
                                UpdateMultiSelection (index);
-                       else
+                       else if (!items [index].Selected) {
                                items [index].Selected = true;
+                               OnSelectedIndexChanged (EventArgs.Empty);
+                       }
 
                        SetFocusedItem (items [index]);                         
                        EnsureVisible (index);
@@ -1183,19 +1305,16 @@ namespace System.Windows.Forms
                        ListViewItem clicked_item;
                        ListViewItem last_clicked_item;
                        bool hover_processed = false;
+                       bool checking = false;
 
                        public ItemControl (ListView owner)
                        {
                                this.owner = owner;
                                DoubleClick += new EventHandler(ItemsDoubleClick);
-                               KeyDown += new KeyEventHandler (ItemsKeyDown);
-                               KeyUp += new KeyEventHandler (ItemsKeyUp);
                                MouseDown += new MouseEventHandler(ItemsMouseDown);
                                MouseMove += new MouseEventHandler(ItemsMouseMove);
                                MouseHover += new EventHandler(ItemsMouseHover);
                                MouseUp += new MouseEventHandler(ItemsMouseUp);
-                               MouseWheel += new MouseEventHandler(ItemsMouseWheel);
-                               Paint += new PaintEventHandler (ItemsPaint);
                        }
 
                        void ItemsDoubleClick (object sender, EventArgs e)
@@ -1204,14 +1323,130 @@ namespace System.Windows.Forms
                                        owner.ItemActivate (this, e);
                        }
 
-                       void ItemsKeyDown (object sender, KeyEventArgs args)
+                       enum BoxSelect {
+                               None,
+                               Normal,
+                               Shift,
+                               Control
+                       }
+
+                       BoxSelect box_select_mode = BoxSelect.None;
+                       ArrayList prev_selection;
+                       Point box_select_start;
+
+                       Rectangle box_select_rect;
+                       internal Rectangle BoxSelectRectangle {
+                               get { return box_select_rect; }
+                               set {
+                                       if (box_select_rect == value)
+                                               return;
+
+                                       InvalidateBoxSelectRect ();
+                                       box_select_rect = value;
+                                       InvalidateBoxSelectRect ();
+                               }
+                       }
+
+                       void InvalidateBoxSelectRect ()
                        {
-                               owner.OnKeyDown (args);
+                               if (BoxSelectRectangle.Size.IsEmpty)
+                                       return;
+
+                               Rectangle edge = BoxSelectRectangle;
+                               edge.X -= 1;
+                               edge.Y -= 1;
+                               edge.Width += 2;
+                               edge.Height = 2;
+                               Invalidate (edge);
+                               edge.Y = BoxSelectRectangle.Bottom - 1;
+                               Invalidate (edge);
+                               edge.Y = BoxSelectRectangle.Y - 1;
+                               edge.Width = 2;
+                               edge.Height = BoxSelectRectangle.Height + 2;
+                               Invalidate (edge);
+                               edge.X = BoxSelectRectangle.Right - 1;
+                               Invalidate (edge);
                        }
 
-                       void ItemsKeyUp (object sender, KeyEventArgs args)
+                       private Rectangle CalculateBoxSelectRectangle (Point pt)
                        {
-                               owner.OnKeyUp (args);
+                               int left = Math.Min (box_select_start.X, pt.X);
+                               int right = Math.Max (box_select_start.X, pt.X);
+                               int top = Math.Min (box_select_start.Y, pt.Y);
+                               int bottom = Math.Max (box_select_start.Y, pt.Y);
+                               return Rectangle.FromLTRB (left, top, right, bottom);
+                       }
+
+                       ArrayList BoxSelectedItems {
+                               get {
+                                       ArrayList result = new ArrayList ();
+                                       foreach (ListViewItem item in owner.Items) {
+                                               Rectangle r = item.Bounds;
+                                               r.X += r.Width / 4;
+                                               r.Y += r.Height / 4;
+                                               r.Width /= 2;
+                                               r.Height /= 2;
+                                               if (BoxSelectRectangle.IntersectsWith (r))
+                                                       result.Add (item);
+                                       }
+                                       return result;
+                               }
+                       }
+
+                       private bool PerformBoxSelection (Point pt)
+                       {
+                               if (box_select_mode == BoxSelect.None)
+                                       return false;
+
+                               BoxSelectRectangle = CalculateBoxSelectRectangle (pt);
+                               
+                               ArrayList box_items = BoxSelectedItems;
+
+                               ArrayList items;
+
+                               switch (box_select_mode) {
+
+                               case BoxSelect.Normal:
+                                       items = box_items;
+                                       break;
+
+                               case BoxSelect.Control:
+                                       items = new ArrayList ();
+                                       foreach (ListViewItem item in prev_selection)
+                                               if (!box_items.Contains (item))
+                                                       items.Add (item);
+                                       foreach (ListViewItem item in box_items)
+                                               if (!prev_selection.Contains (item))
+                                                       items.Add (item);
+                                       break;
+
+                               case BoxSelect.Shift:
+                                       items = box_items;
+                                       foreach (ListViewItem item in box_items)
+                                               prev_selection.Remove (item);
+                                       foreach (ListViewItem item in prev_selection)
+                                               items.Add (item);
+                                       break;
+
+                               default:
+                                       throw new Exception ("Unexpected Selection mode: " + box_select_mode);
+                               }
+
+                               SuspendLayout ();
+                               owner.SelectItems (items);
+                               ResumeLayout ();
+
+                               return true;
+                       }
+
+                       private void ToggleCheckState (ListViewItem item)
+                       {
+                               CheckState curr_state = item.Checked ?  CheckState.Checked : CheckState.Unchecked;
+                               item.Checked = !item.Checked;
+                               CheckState new_state = item.Checked ?  CheckState.Checked : CheckState.Unchecked;
+
+                               ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
+                               owner.OnItemCheck (ice);
                        }
 
                        private void ItemsMouseDown (object sender, MouseEventArgs me)
@@ -1221,16 +1456,12 @@ namespace System.Windows.Forms
 
                                Point pt = new Point (me.X, me.Y);
                                foreach (ListViewItem item in owner.items) {
-                                       if (item.CheckRectReal.Contains (pt)) {
-                                               CheckState curr_state = item.Checked ?  CheckState.Checked : CheckState.Unchecked;
-                                               item.Checked = !item.Checked;
-
-                                               CheckState new_state = item.Checked ?  CheckState.Checked : CheckState.Unchecked;
-
-                                               // Raise the ItemCheck event
-                                               ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
-                                               owner.OnItemCheck (ice);
-                                               break;
+                                       if (me.Clicks == 1 && item.CheckRectReal.Contains (pt)) {
+                                               checking = true;
+                                               if (me.Clicks > 1)
+                                                       return;
+                                               ToggleCheckState (item);
+                                               return;
                                        }
 
                                        if (owner.View == View.Details && !owner.FullRowSelect) {
@@ -1246,9 +1477,9 @@ namespace System.Windows.Forms
                                        }
                                }
 
-                               owner.SetFocusedItem (clicked_item);
 
                                if (clicked_item != null) {
+                                       owner.SetFocusedItem (clicked_item);
                                        bool changed = !clicked_item.Selected;
                                        if (owner.MultiSelect && (XplatUI.State.ModifierKeys & Keys.Control) == 0)
                                                owner.UpdateMultiSelection (clicked_item.Index);
@@ -1260,21 +1491,35 @@ namespace System.Windows.Forms
 
                                        // Raise double click if the item was clicked. On MS the
                                        // double click is only raised if you double click an item
-                                       if (me.Clicks > 1 && clicked_item != null)
+                                       if (me.Clicks > 1) {
                                                owner.OnDoubleClick (EventArgs.Empty);
-                                       else if (me.Clicks == 1 && clicked_item != null)
+                                               if (owner.CheckBoxes)
+                                                       ToggleCheckState (clicked_item);
+                                       } else if (me.Clicks == 1)
                                                owner.OnClick (EventArgs.Empty);
-                               } else if (owner.selected_indices.Count > 0) {
-                                       // Raise the event if there was at least one item
-                                       // selected and the user click on a dead area (unselecting all)
-                                       owner.SelectedItems.Clear ();
-                                       owner.SelectedIndices.list.Clear ();
-                                       owner.OnSelectedIndexChanged (EventArgs.Empty);
+                               } else {
+                                       if (owner.MultiSelect) {
+                                               Keys mods = XplatUI.State.ModifierKeys;
+                                               if ((mods & Keys.Shift) != 0)
+                                                       box_select_mode = BoxSelect.Shift;
+                                               else if ((mods & Keys.Control) != 0)
+                                                       box_select_mode = BoxSelect.Control;
+                                               else
+                                                       box_select_mode = BoxSelect.Normal;
+                                               box_select_start = pt; 
+                                               prev_selection = (ArrayList) owner.SelectedItems.list.Clone ();
+                                       } else if (owner.selected_indices.Count > 0) {
+                                               owner.SelectedItems.Clear ();
+                                               owner.OnSelectedIndexChanged (EventArgs.Empty);
+                                       }
                                }
                        }
 
                        private void ItemsMouseMove (object sender, MouseEventArgs me)
                        {
+                               if (PerformBoxSelection (new Point (me.X, me.Y)))
+                                       return;
+
                                if (owner.HoverSelection && hover_processed) {
 
                                        Point pt = PointToClient (Control.MousePosition);
@@ -1337,49 +1582,74 @@ namespace System.Windows.Forms
                                                        break;
                                                }
                                        }
+                               } else if (!checking && owner.SelectedItems.Count > 0 && BoxSelectRectangle.Size.IsEmpty) {
+                                       // Need this to clean up background clicks
+                                       owner.SelectedItems.Clear ();
+                                       owner.OnSelectedIndexChanged (EventArgs.Empty);
                                }
 
                                clicked_item = null;
+                               box_select_start = Point.Empty;
+                               BoxSelectRectangle = Rectangle.Empty;
+                               prev_selection = null;
+                               box_select_mode = BoxSelect.None;
+                               checking = false;
                        }
 
-                       private void ItemsMouseWheel (object sender, MouseEventArgs me)
+                       internal override void OnPaintInternal (PaintEventArgs pe)
                        {
-                               if (owner.Items.Count == 0)
-                                       return;
-
-                               int lines = me.Delta / 120;
-
-                               if (lines == 0)
-                                       return;
-
-                               switch (owner.View) {
-                               case View.Details:
-                               case View.SmallIcon:
-                                       owner.Scroll (owner.v_scroll, -owner.Items [0].Bounds.Height * SystemInformation.MouseWheelScrollLines * lines);
-                                       break;
-                               case View.LargeIcon:
-                                       owner.Scroll (owner.v_scroll, -(owner.Items [0].Bounds.Height + ThemeEngine.Current.ListViewVerticalSpacing)  * lines);
-                                       break;
-                               case View.List:
-                                       owner.Scroll (owner.h_scroll, -owner.Items [0].Bounds.Width * lines);
-                                       break;
-                               }
+                               ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
                        }
 
-                       private void ItemsPaint (object sender, PaintEventArgs pe)
+                       internal override void OnGotFocusInternal (EventArgs e)
                        {
-                               ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
+                               owner.Focus ();
                        }
                }
 
-               private void ListView_Paint (object sender, PaintEventArgs pe)
+               internal override void OnPaintInternal (PaintEventArgs pe)
                {
-                       if (Width <= 0 || Height <=  0 || !Visible || updating)
+                       if (updating)
                                return; 
                                
                        CalculateScrollBars ();
                }
 
+               void FocusChanged (object o, EventArgs args)
+               {
+                       if (Items.Count == 0)
+                               return;
+
+                       if (FocusedItem == null)
+                               SetFocusedItem (Items [0]);
+
+                       item_control.Invalidate (FocusedItem.Bounds);
+               }
+
+               private void ListView_MouseWheel (object sender, MouseEventArgs me)
+               {
+                       if (Items.Count == 0)
+                               return;
+
+                       int lines = me.Delta / 120;
+
+                       if (lines == 0)
+                               return;
+
+                       switch (View) {
+                       case View.Details:
+                       case View.SmallIcon:
+                               Scroll (v_scroll, -Items [0].Bounds.Height * SystemInformation.MouseWheelScrollLines * lines);
+                               break;
+                       case View.LargeIcon:
+                               Scroll (v_scroll, -(Items [0].Bounds.Height + ThemeEngine.Current.ListViewVerticalSpacing)  * lines);
+                               break;
+                       case View.List:
+                               Scroll (h_scroll, -Items [0].Bounds.Width * lines);
+                               break;
+                       }
+               }
+
                private void ListView_SizeChanged (object sender, EventArgs e)
                {
                        CalculateListView (alignment);
@@ -1497,12 +1767,7 @@ namespace System.Windows.Forms
                protected override void OnHandleCreated (EventArgs e)
                {
                        base.OnHandleCreated (e);
-                       SuspendLayout ();
-                       Controls.AddImplicit (header_control);
-                       Controls.AddImplicit (item_control);
-                       Controls.AddImplicit (this.v_scroll);
-                       Controls.AddImplicit (this.h_scroll);
-                       ResumeLayout ();
+                       Sort ();
                }
 
                protected override void OnHandleDestroyed (EventArgs e)
@@ -1631,20 +1896,34 @@ namespace System.Windows.Forms
                public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
                {
                        if (index < 0 || index >= items.Count)
-                               throw new IndexOutOfRangeException ("Invalid Index");
+                               throw new IndexOutOfRangeException ("index");
 
                        return items [index].GetBounds (portion);
                }
 
                public void Sort ()
                {
-                       if (sort_order != SortOrder.None)
-                               items.list.Sort (item_sorter);
-
-                       if (sort_order == SortOrder.Descending)
-                               items.list.Reverse ();
-
-                       this.Redraw (true);
+                       Sort (true);
+               }
+
+               // we need this overload to reuse the logic for sorting, while allowing
+               // redrawing to be done by caller or have it done by this method when
+               // sorting is really performed
+               //
+               // ListViewItemCollection's Add and AddRange methods call this overload
+               // with redraw set to false, as they take care of redrawing themselves
+               // (they even want to redraw the listview if no sort is performed, as 
+               // an item was added), while ListView.Sort () only wants to redraw if 
+               // sorting was actually performed
+               private void Sort (bool redraw)
+               {
+                       if (!IsHandleCreated || item_sorter == null) {
+                               return;
+                       }
+                       
+                       items.list.Sort (item_sorter);
+                       if (redraw)
+                               this.Redraw (true);
                }
 
                public override string ToString ()
@@ -1677,7 +1956,6 @@ namespace System.Windows.Forms
                                MouseDown += new MouseEventHandler (HeaderMouseDown);
                                MouseMove += new MouseEventHandler (HeaderMouseMove);
                                MouseUp += new MouseEventHandler (HeaderMouseUp);
-                               Paint += new PaintEventHandler (HeaderPaint);
                        }
 
                        private ColumnHeader ColumnAtX (int x)
@@ -1753,7 +2031,9 @@ namespace System.Windows.Forms
 
                                                int x = me.X + owner.h_marker;
                                                ColumnHeader over = ColumnAtX (x);
-                                               if (x < over.X + over.Width / 2)
+                                               if (over == null)
+                                                       drag_to_index = owner.Columns.Count;
+                                               else if (x < over.X + over.Width / 2)
                                                        drag_to_index = GetReorderedIndex (over);
                                                else
                                                        drag_to_index = GetReorderedIndex (over) + 1;
@@ -1776,6 +2056,8 @@ namespace System.Windows.Forms
                                        zone.X = zone.Right - 5;
                                        zone.Width = 10;
                                        if (zone.Contains (pt)) {
+                                               if (i < owner.Columns.Count - 1 && owner.Columns [i + 1].Width == 0)
+                                                       i++;
                                                resize_column = owner.Columns [i];
                                                break;
                                        }
@@ -1819,9 +2101,9 @@ namespace System.Windows.Forms
                                clicked_column = null;
                        }
 
-                       void HeaderPaint (object sender, PaintEventArgs pe)
+                       internal override void OnPaintInternal (PaintEventArgs pe)
                        {
-                               if (Width <= 0 || Height <=  0 || !Visible || owner.updating)
+                               if (owner.updating)
                                        return; 
                                
                                Theme theme = ThemeEngine.Current;
@@ -1837,37 +2119,66 @@ namespace System.Windows.Forms
                                        target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
                                theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
                        }
-                                       
+
+                       protected override void WndProc (ref Message m)
+                       {
+                               switch ((Msg)m.Msg) {
+                               case Msg.WM_SETFOCUS:
+                                       owner.Focus ();
+                                       break;
+                               default:
+                                       base.WndProc (ref m);
+                                       break;
+                               }
+                       }
+               }
+
+               private class ItemComparer : IComparer {
+                       readonly SortOrder sort_order;
+
+                       public ItemComparer (SortOrder sortOrder)
+                       {
+                               sort_order = sortOrder;
+                       }
+
+                       public int Compare (object x, object y)
+                       {
+                               ListViewItem item_x = x as ListViewItem;
+                               ListViewItem item_y = y as ListViewItem;
+                               if (sort_order == SortOrder.Ascending)
+                                       return String.Compare (item_x.Text, item_y.Text);
+                               else
+                                       return String.Compare (item_y.Text, item_x.Text);
+                       }
                }
 
                public class CheckedIndexCollection : IList, ICollection, IEnumerable
                {
-                       internal ArrayList list;
-                       private ListView owner;
+                       private readonly ListView owner;
 
                        #region Public Constructor
                        public CheckedIndexCollection (ListView owner)
                        {
-                               list = new ArrayList ();
                                this.owner = owner;
                        }
                        #endregion      // Public Constructor
 
                        #region Public Properties
                        [Browsable (false)]
-                       int ICollection.Count {
-                               get { return list.Count; }
+                       public int Count {
+                               get { return owner.CheckedItems.Count; }
                        }
 
-                       bool IList.IsReadOnly {
+                       public bool IsReadOnly {
                                get { return true; }
                        }
 
                        public int this [int index] {
                                get {
-                                       if (index < 0 || index >= list.Count)
-                                               throw new ArgumentOutOfRangeException ("Index out of range.");
-                                       return (int) list [index];
+                                       int [] indices = GetIndices ();
+                                       if (index < 0 || index >= indices.Length)
+                                               throw new ArgumentOutOfRangeException ("index");
+                                       return indices [index];
                                }
                        }
 
@@ -1892,17 +2203,24 @@ namespace System.Windows.Forms
                        #region Public Methods
                        public bool Contains (int checkedIndex)
                        {
-                               return list.Contains (checkedIndex);
+                               int [] indices = GetIndices ();
+                               for (int i = 0; i < indices.Length; i++) {
+                                       if (indices [i] == checkedIndex)
+                                               return true;
+                               }
+                               return false;
                        }
 
-                       IEnumerator IEnumerable.GetEnumerator ()
+                       public IEnumerator GetEnumerator ()
                        {
-                               return list.GetEnumerator ();
+                               int [] indices = GetIndices ();
+                               return indices.GetEnumerator ();
                        }
 
                        void ICollection.CopyTo (Array dest, int index)
                        {
-                               list.CopyTo (dest, index);
+                               int [] indices = GetIndices ();
+                               Array.Copy (indices, 0, dest, index, indices.Length);
                        }
 
                        int IList.Add (object value)
@@ -1917,12 +2235,16 @@ namespace System.Windows.Forms
 
                        bool IList.Contains (object checkedIndex)
                        {
-                               return list.Contains (checkedIndex);
+                               if (!(checkedIndex is int))
+                                       return false;
+                               return Contains ((int) checkedIndex);
                        }
 
                        int IList.IndexOf (object checkedIndex)
                        {
-                               return list.IndexOf (checkedIndex);
+                               if (!(checkedIndex is int))
+                                       return -1;
+                               return IndexOf ((int) checkedIndex);
                        }
 
                        void IList.Insert (int index, object value)
@@ -1942,16 +2264,30 @@ namespace System.Windows.Forms
 
                        public int IndexOf (int checkedIndex)
                        {
-                               return list.IndexOf (checkedIndex);
+                               int [] indices = GetIndices ();
+                               for (int i = 0; i < indices.Length; i++) {
+                                       if (indices [i] == checkedIndex)
+                                               return i;
+                               }
+                               return -1;
                        }
                        #endregion      // Public Methods
 
+                       private int [] GetIndices ()
+                       {
+                               int [] indices = new int [Count];
+                               for (int i = 0; i < owner.CheckedItems.Count; i++) {
+                                       ListViewItem item = owner.CheckedItems [i];
+                                       indices [i] = item.Index;
+                               }
+                               return indices;
+                       }
                }       // CheckedIndexCollection
 
                public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
                {
-                       internal ArrayList list;
-                       private ListView owner;
+                       internal readonly ArrayList list;
+                       private readonly ListView owner;
 
                        #region Public Constructor
                        public CheckedListViewItemCollection (ListView owner)
@@ -1963,18 +2299,22 @@ namespace System.Windows.Forms
 
                        #region Public Properties
                        [Browsable (false)]
-                       int ICollection.Count {
-                               get { return list.Count; }
+                       public int Count {
+                               get {
+                                       if (!owner.CheckBoxes)
+                                               return 0;
+                                       return list.Count;
+                               }
                        }
 
-                       bool IList.IsReadOnly {
+                       public bool IsReadOnly {
                                get { return true; }
                        }
 
                        public ListViewItem this [int index] {
                                get {
-                                       if (index < 0 || index >= list.Count)
-                                               throw new ArgumentOutOfRangeException ("Index out of range.");
+                                       if (index < 0 || index >= Count)
+                                               throw new ArgumentOutOfRangeException ("index");
                                        return (ListViewItem) list [index];
                                }
                        }
@@ -2000,16 +2340,22 @@ namespace System.Windows.Forms
                        #region Public Methods
                        public bool Contains (ListViewItem item)
                        {
+                               if (!owner.CheckBoxes)
+                                       return false;
                                return list.Contains (item);
                        }
 
-                       void ICollection.CopyTo (Array dest, int index)
+                       public void CopyTo (Array dest, int index)
                        {
+                               if (!owner.CheckBoxes)
+                                       return;
                                list.CopyTo (dest, index);
                        }
 
-                       IEnumerator IEnumerable.GetEnumerator ()
+                       public IEnumerator GetEnumerator ()
                        {
+                               if (!owner.CheckBoxes)
+                                       return (new ListViewItem [0]).GetEnumerator ();
                                return list.GetEnumerator ();
                        }
 
@@ -2025,12 +2371,16 @@ namespace System.Windows.Forms
 
                        bool IList.Contains (object item)
                        {
-                               return list.Contains (item);
+                               if (!(item is ListViewItem))
+                                       return false;
+                               return Contains ((ListViewItem) item);
                        }
 
                        int IList.IndexOf (object item)
                        {
-                               return list.IndexOf (item);
+                               if (!(item is ListViewItem))
+                                       return -1;
+                               return IndexOf ((ListViewItem) item);
                        }
 
                        void IList.Insert (int index, object value)
@@ -2050,10 +2400,11 @@ namespace System.Windows.Forms
 
                        public int IndexOf (ListViewItem item)
                        {
+                               if (!owner.CheckBoxes)
+                                       return -1;
                                return list.IndexOf (item);
                        }
                        #endregion      // Public Methods
-
                }       // CheckedListViewItemCollection
 
                public class ColumnHeaderCollection : IList, ICollection, IEnumerable
@@ -2071,22 +2422,18 @@ namespace System.Windows.Forms
 
                        #region Public Properties
                        [Browsable (false)]
-                       int ICollection.Count {
+                       public int Count {
                                get { return list.Count; }
                        }
 
-                       internal int Count {
-                               get { return list.Count; }
-                       }
-
-                       bool IList.IsReadOnly {
+                       public bool IsReadOnly {
                                get { return false; }
                        }
 
                        public virtual ColumnHeader this [int index] {
                                get {
                                        if (index < 0 || index >= list.Count)
-                                               throw new ArgumentOutOfRangeException ("Index out of range.");
+                                               throw new ArgumentOutOfRangeException ("index");
                                        return (ColumnHeader) list [index];
                                }
                        }
@@ -2115,7 +2462,9 @@ namespace System.Windows.Forms
                                int idx;
                                value.owner = this.owner;
                                idx = list.Add (value);
-                               owner.Redraw (true); 
+                               if (owner.IsHandleCreated) {
+                                       owner.Redraw (true); 
+                               }
                                return idx;
                        }
 
@@ -2147,7 +2496,7 @@ namespace System.Windows.Forms
                                return list.Contains (value);
                        }
 
-                       IEnumerator IEnumerable.GetEnumerator ()
+                       public IEnumerator GetEnumerator ()
                        {
                                return list.GetEnumerator ();
                        }
@@ -2212,7 +2561,7 @@ namespace System.Windows.Forms
                                // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
                                // but it's really only greater.
                                if (index < 0 || index > list.Count)
-                                       throw new ArgumentOutOfRangeException ("Index out of range.");
+                                       throw new ArgumentOutOfRangeException ("index");
 
                                value.owner = this.owner;
                                list.Insert (index, value);
@@ -2235,7 +2584,7 @@ namespace System.Windows.Forms
                        public virtual void RemoveAt (int index)
                        {
                                if (index < 0 || index >= list.Count)
-                                       throw new ArgumentOutOfRangeException ("Index out of range.");
+                                       throw new ArgumentOutOfRangeException ("index");
 
                                // TODO: Update Column internal index ?
                                list.RemoveAt (index);
@@ -2249,7 +2598,7 @@ namespace System.Windows.Forms
                public class ListViewItemCollection : IList, ICollection, IEnumerable
                {
                        internal ArrayList list;
-                       private ListView owner;
+                       private readonly ListView owner;
 
                        #region Public Constructor
                        public ListViewItemCollection (ListView owner)
@@ -2261,28 +2610,24 @@ namespace System.Windows.Forms
 
                        #region Public Properties
                        [Browsable (false)]
-                       int ICollection.Count {
-                               get { return list.Count; }
-                       }
-
-                       internal int Count {
+                       public int Count {
                                get { return list.Count; }
                        }
 
-                       bool IList.IsReadOnly {
+                       public bool IsReadOnly {
                                get { return false; }
                        }
 
                        public virtual ListViewItem this [int displayIndex] {
                                get {
                                        if (displayIndex < 0 || displayIndex >= list.Count)
-                                               throw new ArgumentOutOfRangeException ("Index out of range.");
+                                               throw new ArgumentOutOfRangeException ("displayIndex");
                                        return (ListViewItem) list [displayIndex];
                                }
 
                                set {
                                        if (displayIndex < 0 || displayIndex >= list.Count)
-                                               throw new ArgumentOutOfRangeException ("Index out of range.");
+                                               throw new ArgumentOutOfRangeException ("displayIndex");
 
                                        if (list.Contains (value))
                                                throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
@@ -2326,11 +2671,8 @@ namespace System.Windows.Forms
                                value.Owner = owner;
                                list.Add (value);
 
-                               if (owner.Sorting != SortOrder.None)
-                                       owner.Sort ();
-
+                               owner.Sort (false);
                                owner.Redraw (true);
-
                                return value;
                        }
 
@@ -2350,18 +2692,14 @@ namespace System.Windows.Forms
                        {
                                list.Clear ();
                                owner.SelectedItems.list.Clear ();
-                               owner.SelectedIndices.list.Clear ();
                                owner.CheckedItems.list.Clear ();
-                               owner.CheckedIndices.list.Clear ();
 
                                foreach (ListViewItem item in values) {
                                        item.Owner = owner;
                                        list.Add (item);
                                }
 
-                               if (owner.Sorting != SortOrder.None)
-                                       owner.Sort ();
-
+                               owner.Sort (false);
                                owner.Redraw (true);
                        }
 
@@ -2371,9 +2709,7 @@ namespace System.Windows.Forms
                                owner.h_scroll.Value = owner.v_scroll.Value = 0;
                                list.Clear ();
                                owner.SelectedItems.list.Clear ();
-                               owner.SelectedIndices.list.Clear ();
                                owner.CheckedItems.list.Clear ();
-                               owner.CheckedIndices.list.Clear ();
                                owner.Redraw (true);
                        }
 
@@ -2382,12 +2718,12 @@ namespace System.Windows.Forms
                                return list.Contains (item);
                        }
 
-                       void ICollection.CopyTo (Array dest, int index)
+                       public void CopyTo (Array dest, int index)
                        {
                                list.CopyTo (dest, index);
                        }
 
-                       IEnumerator IEnumerable.GetEnumerator ()
+                       public IEnumerator GetEnumerator ()
                        {
                                return list.GetEnumerator ();
                        }
@@ -2442,10 +2778,8 @@ namespace System.Windows.Forms
 
                        public ListViewItem Insert (int index, ListViewItem item)
                        {
-                               // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
-                               // but it's really only greater.
                                if (index < 0 || index > list.Count)
-                                       throw new ArgumentOutOfRangeException ("Index out of range.");
+                                       throw new ArgumentOutOfRangeException ("index");
 
                                if (list.Contains (item))
                                        throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
@@ -2472,23 +2806,17 @@ namespace System.Windows.Forms
                                        return;
                                        
                                owner.SelectedItems.list.Remove (item);
-                               owner.SelectedIndices.list.Remove (item.Index);
                                owner.CheckedItems.list.Remove (item);
-                               owner.CheckedIndices.list.Remove (item.Index);
                                list.Remove (item);
                                owner.Redraw (true);                            
                        }
 
                        public virtual void RemoveAt (int index)
                        {
-                               if (index < 0 || index >= list.Count)
-                                       throw new ArgumentOutOfRangeException ("Index out of range.");
-
+                               ListViewItem item = this [index];
                                list.RemoveAt (index);
-                               owner.SelectedItems.list.RemoveAt (index);
-                               owner.SelectedIndices.list.RemoveAt (index);
-                               owner.CheckedItems.list.RemoveAt (index);
-                               owner.CheckedIndices.list.RemoveAt (index);
+                               owner.SelectedItems.list.Remove (item);
+                               owner.CheckedItems.list.Remove (item);
                                owner.Redraw (false);
                        }
                        #endregion      // Public Methods
@@ -2497,41 +2825,38 @@ namespace System.Windows.Forms
 
                public class SelectedIndexCollection : IList, ICollection, IEnumerable
                {
-                       internal ArrayList list;
-                       private ListView owner;
+                       private readonly ListView owner;
 
                        #region Public Constructor
                        public SelectedIndexCollection (ListView owner)
                        {
-                               list = new ArrayList ();
                                this.owner = owner;
                        }
                        #endregion      // Public Constructor
 
                        #region Public Properties
                        [Browsable (false)]
-                       int ICollection.Count {
-                               get { return list.Count; }
-                       }
-
-                       internal int Count {
-                               get { return list.Count; }
+                       public int Count {
+                               get {
+                                       return owner.SelectedItems.Count;
+                               }
                        }
 
-                       bool IList.IsReadOnly {
+                       public bool IsReadOnly {
                                get { return true; }
                        }
 
                        public int this [int index] {
                                get {
-                                       if (index < 0 || index >= list.Count)
-                                               throw new ArgumentOutOfRangeException ("Index out of range.");
-                                       return (int) list [index];
+                                       int [] indices = GetIndices ();
+                                       if (index < 0 || index >= indices.Length)
+                                               throw new ArgumentOutOfRangeException ("index");
+                                       return indices [index];
                                }
                        }
 
                        bool ICollection.IsSynchronized {
-                               get { return list.IsSynchronized; }
+                               get { return false; }
                        }
 
                        object ICollection.SyncRoot {
@@ -2551,17 +2876,24 @@ namespace System.Windows.Forms
                        #region Public Methods
                        public bool Contains (int selectedIndex)
                        {
-                               return list.Contains (selectedIndex);
+                               int [] indices = GetIndices ();
+                               for (int i = 0; i < indices.Length; i++) {
+                                       if (indices [i] == selectedIndex)
+                                               return true;
+                               }
+                               return false;
                        }
 
-                       void ICollection.CopyTo (Array dest, int index)
+                       public void CopyTo (Array dest, int index)
                        {
-                               list.CopyTo (dest, index);
+                               int [] indices = GetIndices ();
+                               Array.Copy (indices, 0, dest, index, indices.Length);
                        }
 
-                       IEnumerator IEnumerable.GetEnumerator ()
+                       public IEnumerator GetEnumerator ()
                        {
-                               return list.GetEnumerator ();
+                               int [] indices = GetIndices ();
+                               return indices.GetEnumerator ();
                        }
 
                        int IList.Add (object value)
@@ -2576,12 +2908,16 @@ namespace System.Windows.Forms
 
                        bool IList.Contains (object selectedIndex)
                        {
-                               return list.Contains (selectedIndex);
+                               if (!(selectedIndex is int))
+                                       return false;
+                               return Contains ((int) selectedIndex);
                        }
 
                        int IList.IndexOf (object selectedIndex)
                        {
-                               return list.IndexOf (selectedIndex);
+                               if (!(selectedIndex is int))
+                                       return -1;
+                               return IndexOf ((int) selectedIndex);
                        }
 
                        void IList.Insert (int index, object value)
@@ -2601,16 +2937,31 @@ namespace System.Windows.Forms
 
                        public int IndexOf (int selectedIndex)
                        {
-                               return list.IndexOf (selectedIndex);
+                               int [] indices = GetIndices ();
+                               for (int i = 0; i < indices.Length; i++) {
+                                       if (indices [i] == selectedIndex)
+                                               return i;
+                               }
+                               return -1;
                        }
                        #endregion      // Public Methods
 
+                       private int [] GetIndices ()
+                       {
+                               int [] indices = new int [Count];
+                               for (int i = 0; i < owner.SelectedItems.Count; i++) {
+                                       ListViewItem item = owner.SelectedItems [i];
+                                       indices [i] = item.Index;
+                               }
+                               return indices;
+                       }
+
                }       // SelectedIndexCollection
 
                public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
                {
                        internal ArrayList list;
-                       private ListView owner;
+                       private readonly ListView owner;
 
                        #region Public Constructor
                        public SelectedListViewItemCollection (ListView owner)
@@ -2622,22 +2973,22 @@ namespace System.Windows.Forms
 
                        #region Public Properties
                        [Browsable (false)]
-                       int ICollection.Count {
-                               get { return list.Count; }
-                       }
-
-                       internal int Count {
-                               get { return list.Count; }
+                       public int Count {
+                               get {
+                                       if (!owner.IsHandleCreated)
+                                               return 0;
+                                       return list.Count;
+                               }
                        }
 
-                       bool IList.IsReadOnly {
+                       public bool IsReadOnly {
                                get { return true; }
                        }
 
                        public ListViewItem this [int index] {
                                get {
-                                       if (index < 0 || index >= list.Count)
-                                               throw new ArgumentOutOfRangeException ("Index out of range.");
+                                       if (index < 0 || index >= Count)
+                                               throw new ArgumentOutOfRangeException ("index");
                                        return (ListViewItem) list [index];
                                }
                        }
@@ -2661,31 +3012,36 @@ namespace System.Windows.Forms
                        #endregion      // Public Properties
 
                        #region Public Methods
-                       void IList.Clear ()
+                       public void Clear ()
                        {
-                               Clear ();
-                       }
+                               if (!owner.IsHandleCreated)
+                                       return;
 
-                       internal void Clear ()
-                       {
                                ArrayList copy = (ArrayList) list.Clone ();
                                for (int i = 0; i < copy.Count; i++)
                                        ((ListViewItem) copy [i]).Selected = false;
 
                                list.Clear ();
                        }
+
                        public bool Contains (ListViewItem item)
                        {
+                               if (!owner.IsHandleCreated)
+                                       return false;
                                return list.Contains (item);
                        }
 
-                       void ICollection.CopyTo (Array dest, int index)
+                       public void CopyTo (Array dest, int index)
                        {
+                               if (!owner.IsHandleCreated)
+                                       return;
                                list.CopyTo (dest, index);
                        }
 
-                       IEnumerator IEnumerable.GetEnumerator ()
+                       public IEnumerator GetEnumerator ()
                        {
+                               if (!owner.IsHandleCreated)
+                                       return (new ListViewItem [0]).GetEnumerator ();
                                return list.GetEnumerator ();
                        }
 
@@ -2696,12 +3052,16 @@ namespace System.Windows.Forms
 
                        bool IList.Contains (object item)
                        {
-                               return list.Contains (item);
+                               if (!(item is ListViewItem))
+                                       return false;
+                               return Contains ((ListViewItem) item);
                        }
 
                        int IList.IndexOf (object item)
                        {
-                               return list.IndexOf (item);
+                               if (!(item is ListViewItem))
+                                       return -1;
+                               return IndexOf ((ListViewItem) item);
                        }
 
                        void IList.Insert (int index, object value)
@@ -2721,6 +3081,8 @@ namespace System.Windows.Forms
 
                        public int IndexOf (ListViewItem item)
                        {
+                               if (!owner.IsHandleCreated)
+                                       return -1;
                                return list.IndexOf (item);
                        }
                        #endregion      // Public Methods