2007-01-09 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListView.cs
index dc6b9a837ef62ec086f5bc97dff06d79e65a8017..60c76b9b70537e8dc240d9a653a2fc4d91236a76 100644 (file)
@@ -23,6 +23,7 @@
 //     Ravindra Kumar (rkumar@novell.com)
 //     Jordi Mas i Hernandez, jordi@ximian.com
 //     Mike Kestner (mkestner@novell.com)
+//     Daniel Nauck (dna(at)mono-project(dot)de)
 //
 // TODO:
 //   - Feedback for item activation, change in cursor types as mouse moves.
@@ -39,12 +40,20 @@ using System.ComponentModel.Design;
 using System.Drawing;
 using System.Runtime.InteropServices;
 using System.Globalization;
+#if NET_2_0
+using System.Collections.Generic;
+#endif
 
 namespace System.Windows.Forms
 {
        [DefaultEvent ("SelectedIndexChanged")]
        [DefaultProperty ("Items")]
        [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
+#if NET_2_0
+       [ClassInterface (ClassInterfaceType.AutoDispatch)]
+       [ComVisible (true)]
+       [Docking (DockingBehavior.Ask)]
+#endif
        public class ListView : Control
        {
                private ItemActivation activation = ItemActivation.Standard;
@@ -52,9 +61,9 @@ namespace System.Windows.Forms
                private bool allow_column_reorder = false;
                private bool auto_arrange = true;
                private bool check_boxes = false;
-               private CheckedIndexCollection checked_indices;
-               private CheckedListViewItemCollection checked_items;
-               private ColumnHeaderCollection columns;
+               private readonly CheckedIndexCollection checked_indices;
+               private readonly CheckedListViewItemCollection checked_items;
+               private readonly ColumnHeaderCollection columns;
                internal ListViewItem focused_item;
                private bool full_row_select = false;
                private bool grid_lines = false;
@@ -62,13 +71,17 @@ namespace System.Windows.Forms
                private bool hide_selection = true;
                private bool hover_selection = false;
                private IComparer item_sorter;
-               private ListViewItemCollection items;
+               private readonly ListViewItemCollection items;
+#if NET_2_0
+               private readonly ListViewGroupCollection groups;
+               private bool show_groups = true;
+#endif
                private bool label_edit = false;
                private bool label_wrap = true;
                private bool multiselect = true;
                private bool scrollable = true;
-               private SelectedIndexCollection selected_indices;
-               private SelectedListViewItemCollection selected_items;
+               private readonly SelectedIndexCollection selected_indices;
+               private readonly SelectedListViewItemCollection selected_items;
                private SortOrder sort_order = SortOrder.None;
                private ImageList state_image_list;
                private bool updating = false;
@@ -86,6 +99,9 @@ namespace System.Windows.Forms
                private string keysearch_text;
                static private readonly int keysearch_keydelay = 1000;
                private int[] reordered_column_indices;
+#if NET_2_0
+               private Size tile_size;
+#endif
 
                // internal variables
                internal ImageList large_image_list;
@@ -93,7 +109,18 @@ namespace System.Windows.Forms
                internal Size text_size = Size.Empty;
 
                #region Events
-               public event LabelEditEventHandler AfterLabelEdit;
+               static object AfterLabelEditEvent = new object ();
+               static object BeforeLabelEditEvent = new object ();
+               static object ColumnClickEvent = new object ();
+               static object ItemActivateEvent = new object ();
+               static object ItemCheckEvent = new object ();
+               static object ItemDragEvent = new object ();
+               static object SelectedIndexChangedEvent = new object ();
+
+               public event LabelEditEventHandler AfterLabelEdit {
+                       add { Events.AddHandler (AfterLabelEditEvent, value); }
+                       remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
+               }
 
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
@@ -102,11 +129,30 @@ namespace System.Windows.Forms
                        remove { base.BackgroundImageChanged -= value; }
                }
 
-               public event LabelEditEventHandler BeforeLabelEdit;
-               public event ColumnClickEventHandler ColumnClick;
-               public event EventHandler ItemActivate;
-               public event ItemCheckEventHandler ItemCheck;
-               public event ItemDragEventHandler ItemDrag;
+               public event LabelEditEventHandler BeforeLabelEdit {
+                       add { Events.AddHandler (BeforeLabelEditEvent, value); }
+                       remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
+               }
+
+               public event ColumnClickEventHandler ColumnClick {
+                       add { Events.AddHandler (ColumnClickEvent, value); }
+                       remove { Events.RemoveHandler (ColumnClickEvent, value); }
+               }
+
+               public event EventHandler ItemActivate {
+                       add { Events.AddHandler (ItemActivateEvent, value); }
+                       remove { Events.RemoveHandler (ItemActivateEvent, value); }
+               }
+
+               public event ItemCheckEventHandler ItemCheck {
+                       add { Events.AddHandler (ItemCheckEvent, value); }
+                       remove { Events.RemoveHandler (ItemCheckEvent, value); }
+               }
+
+               public event ItemDragEventHandler ItemDrag {
+                       add { Events.AddHandler (ItemDragEvent, value); }
+                       remove { Events.RemoveHandler (ItemDragEvent, value); }
+               }
 
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
@@ -115,7 +161,10 @@ namespace System.Windows.Forms
                        remove { base.Paint -= value; }
                }
 
-               public event EventHandler SelectedIndexChanged;
+               public event EventHandler SelectedIndexChanged {
+                       add { Events.AddHandler (SelectedIndexChangedEvent, value); }
+                       remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
+               }
 
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
@@ -130,11 +179,14 @@ namespace System.Windows.Forms
                public ListView ()
                {
                        background_color = ThemeEngine.Current.ColorWindow;
+                       items = new ListViewItemCollection (this);
+#if NET_2_0
+                       groups = new ListViewGroupCollection (this);
+#endif
                        checked_indices = new CheckedIndexCollection (this);
                        checked_items = new CheckedListViewItemCollection (this);
                        columns = new ColumnHeaderCollection (this);
                        foreground_color = SystemColors.WindowText;
-                       items = new ListViewItemCollection (this);
                        selected_indices = new SelectedIndexCollection (this);
                        selected_items = new SelectedListViewItemCollection (this);
 
@@ -147,10 +199,10 @@ namespace System.Windows.Forms
                        item_control = new ItemControl (this);
                        Controls.AddImplicit (item_control);
 
-                       h_scroll = new HScrollBar ();
+                       h_scroll = new ImplicitHScrollBar ();
                        Controls.AddImplicit (this.h_scroll);
 
-                       v_scroll = new VScrollBar ();
+                       v_scroll = new ImplicitVScrollBar ();
                        Controls.AddImplicit (this.v_scroll);
 
                        h_marker = v_marker = 0;
@@ -169,7 +221,11 @@ namespace System.Windows.Forms
                        LostFocus += new EventHandler (FocusChanged);
                        MouseWheel += new MouseEventHandler(ListView_MouseWheel);
 
-                       this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
+                       this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
+#if NET_2_0
+                               | ControlStyles.UseTextForAccessibility
+#endif
+                               , false);
                }
                #endregion      // Public Constructors
 
@@ -266,14 +322,8 @@ namespace System.Windows.Forms
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public override Image BackgroundImage {
-                       get { return background_image; }
-                       set {
-                               if (value == background_image)
-                                       return;
-
-                               background_image = value;
-                               OnBackgroundImageChanged (EventArgs.Empty);
-                       }
+                       get { return base.BackgroundImage; }
+                       set { base.BackgroundImage = value; }
                }
 
                [DefaultValue (BorderStyle.Fixed3D)]
@@ -475,14 +525,22 @@ namespace System.Windows.Forms
                }
 
 #if NET_2_0
-               [MonoTODO("Implement")]
+               [DefaultValue(true)]
                public bool ShowGroups {
-                       get {
-                               return false;
+                       get { return show_groups; }
+                       set 
+                       {
+                               if (show_groups != value)
+                               {
+                                       show_groups = value;
+                                       Redraw(true);
+                               }
                        }
+               }
 
-                       set {
-                       }
+               [LocalizableAttribute(true)]
+               public ListViewGroupCollection Groups {
+                       get { return groups;    }
                }
 #endif
 
@@ -556,17 +614,30 @@ namespace System.Windows.Forms
                [Browsable (false)]
                [EditorBrowsable (EditorBrowsableState.Never)]
                public override string Text {
-                       get { return text; } 
+                       get { return base.Text; } 
                        set {
-                               if (value == text)
+                               if (value == base.Text)
                                        return;
 
-                               text = value;
+                               base.Text = value;
                                this.Redraw (true);
+                       }
+               }
+
+#if NET_2_0
+               public Size TileSize {
+                       get {
+                               return tile_size;
+                       }
+                       set {
+                               if (value.Width <= 0 || value.Height <= 0)
+                                       throw new ArgumentOutOfRangeException ("value");
 
-                               OnTextChanged (EventArgs.Empty);
+                               tile_size = value;
+                               Redraw (true);
                        }
                }
+#endif
 
                [Browsable (false)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
@@ -651,10 +722,10 @@ namespace System.Windows.Forms
                        get {                                                   
                                for (int i = FirstVisibleIndex; i < Items.Count; i++) {
                                        if (View == View.List || Alignment == ListViewAlignment.Left) {
-                                               if (Items[i].Bounds.X > ClientRectangle.Right)
+                                               if (Items[i].Bounds.X > item_control.ClientRectangle.Right)
                                                        return i - 1;                                   
                                        } else {
-                                               if (Items[i].Bounds.Y > ClientRectangle.Bottom)
+                                               if (Items[i].Bounds.Y > item_control.ClientRectangle.Bottom)
                                                        return i - 1;                                   
                                        }
                                }
@@ -663,6 +734,12 @@ namespace System.Windows.Forms
                        }
                }
                
+               internal void OnSelectedIndexChanged ()
+               {
+                       if (IsHandleCreated)
+                               OnSelectedIndexChanged (EventArgs.Empty);
+               }
+
                internal int TotalWidth {
                        get { return Math.Max (this.Width, this.layout_wd); }
                }
@@ -683,6 +760,8 @@ namespace System.Windows.Forms
                        Refresh ();
                }
 
+               const int text_padding = 5;
+
                internal Size GetChildColumnSize (int index)
                {
                        Size ret_size = Size.Empty;
@@ -691,6 +770,7 @@ namespace System.Windows.Forms
                        if (col.Width == -2) { // autosize = max(items, columnheader)
                                Size size = Size.Ceiling (this.DeviceContext.MeasureString
                                                          (col.Text, this.Font));
+                               size.Width += text_padding;
                                ret_size = BiggestItem (index);
                                if (size.Width > ret_size.Width)
                                        ret_size = size;
@@ -708,6 +788,8 @@ namespace System.Windows.Forms
                                }
                        }
 
+                       ret_size.Height += text_padding;
+
                        // adjust the size for icon and checkbox for 0th column
                        if (index == 0) {
                                ret_size.Width += (this.CheckBoxSize.Width + 4);
@@ -893,8 +975,22 @@ namespace System.Windows.Forms
                                item_control.Width -= v_scroll.Width;
                        }
                }
+
+#if NET_2_0
+               internal int GetReorderedColumnIndex (ColumnHeader column)
+               {
+                       if (reordered_column_indices == null)
+                               return column.Index;
+
+                       for (int i = 0; i < Columns.Count; i++)
+                               if (reordered_column_indices [i] == column.Index)
+                                       return i;
+
+                       return -1;
+               }
+#endif
                
-               ColumnHeader GetReorderedColumn (int index)
+               internal ColumnHeader GetReorderedColumn (int index)
                {
                        if (reordered_column_indices == null)
                                return Columns [index];
@@ -902,8 +998,21 @@ namespace System.Windows.Forms
                                return Columns [reordered_column_indices [index]];
                }
 
-               void ReorderColumn (ColumnHeader col, int index)
+               internal void ReorderColumn (ColumnHeader col, int index)
                {
+#if NET_2_0
+                       ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
+                       if (eh != null){
+                               ColumnReorderedEventArgs args = new ColumnReorderedEventArgs (col.Index, index, col);
+
+                               eh (this, args);
+                               if (args.Cancel){
+                                       header_control.Invalidate ();
+                                       item_control.Invalidate ();
+                                       return;
+                               }
+                       }
+#endif
                        if (reordered_column_indices == null) {
                                reordered_column_indices = new int [Columns.Count];
                                for (int i = 0; i < Columns.Count; i++)
@@ -952,11 +1061,31 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               Size TileItemSize {
+                       get {
+                               // Calculate tile size if needed
+                               // It appears that using Font.Size instead of a SizeF value can give us
+                               // a slightly better approach to the proportions defined in .Net
+                               if (tile_size == Size.Empty) {
+                                       int image_w = LargeImageList == null ? 0 : LargeImageList.ImageSize.Width;
+                                       int image_h = LargeImageList == null ? 0 : LargeImageList.ImageSize.Height;
+                                       int w = (int)Font.Size * ThemeEngine.Current.ListViewTileWidthFactor + image_w + 4;
+                                       int h = Math.Max ((int)Font.Size * ThemeEngine.Current.ListViewTileHeightFactor, image_h);
+
+                                       tile_size = new Size (w, h);
+                               }
+
+                               return tile_size;
+                       }
+               }
+#endif
+
                int rows;
                int cols;
                ListViewItem[,] item_matrix;
 
-               void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
+               void LayoutIcons (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
                {
                        header_control.Visible = false;
                        header_control.Size = Size.Empty;
@@ -966,8 +1095,7 @@ namespace System.Windows.Forms
                        if (items.Count == 0)
                                return;
 
-                       Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
-
+                       Size sz = item_size;
                        Rectangle area = ClientRectangle;
 
                        if (left_aligned) {
@@ -1075,42 +1203,30 @@ namespace System.Windows.Forms
                                break;
 
                        case View.SmallIcon:
-                               LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
+                               LayoutIcons (SmallIconItemSize, alignment == ListViewAlignment.Left, 4, 2);
                                break;
 
                        case View.LargeIcon:
-                               LayoutIcons (true, alignment == ListViewAlignment.Left,
+                               LayoutIcons (LargeIconItemSize, alignment == ListViewAlignment.Left,
                                             ThemeEngine.Current.ListViewHorizontalSpacing,
                                             ThemeEngine.Current.ListViewVerticalSpacing);
                                break;
 
                        case View.List:
-                               LayoutIcons (false, true, 4, 2);
+                               LayoutIcons (SmallIconItemSize, true, 4, 2);
+                               break;
+#if NET_2_0
+                       case View.Tile:
+                               LayoutIcons (TileItemSize, alignment == ListViewAlignment.Left, 
+                                               ThemeEngine.Current.ListViewHorizontalSpacing,
+                                               ThemeEngine.Current.ListViewVerticalSpacing);
                                break;
+#endif
                        }
 
                         CalculateScrollBars ();
                }
 
-               bool HaveModKeys {
-                       get {
-                               return (XplatUI.State.ModifierKeys & (Keys.Control | Keys.Shift)) != 0;
-                       }
-               }
-
-               internal void UpdateSelection (ListViewItem item)
-               {
-                       if (item.Selected) {
-                               if (!MultiSelect && SelectedItems.Count > 0)
-                                       SelectedItems.Clear ();
-
-                               if (!SelectedItems.list.Contains (item))
-                                       SelectedItems.list.Add (item);
-                       } else {
-                               SelectedItems.list.Remove (item);
-                       }
-               }
-
                private bool KeySearchString (KeyEventArgs ke)
                {
                        int current_tickcnt = Environment.TickCount;
@@ -1144,12 +1260,43 @@ namespace System.Windows.Forms
                        int result = -1;
 
                        if (View == View.Details) {
-                               if (key == Keys.Up)
+                               switch (key) {
+                               case Keys.Up:
                                        result = FocusedItem.Index - 1;
-                               else if (key == Keys.Down) {
+                                       break;
+                               case Keys.Down:
                                        result = FocusedItem.Index + 1;
                                        if (result == items.Count)
                                                result = -1;
+                                       break;
+                               case Keys.PageDown:
+                                       int last_index = LastVisibleIndex;
+                                       if (Items [last_index].Bounds.Bottom > item_control.ClientRectangle.Bottom)
+                                               last_index--;
+                                       if (FocusedItem.Index == last_index) {
+                                               if (FocusedItem.Index < Items.Count - 1) {
+                                                       int page_size = item_control.Height / items [0].Bounds.Height - 1;
+                                                       result = FocusedItem.Index + page_size - 1;
+                                                       if (result >= Items.Count)
+                                                               result = Items.Count - 1;
+                                               }
+                                       } else
+                                               result = last_index;
+                                       break;
+                               case Keys.PageUp:
+                                       int first_index = FirstVisibleIndex;
+                                       if (Items [first_index].Bounds.Y < 0)
+                                               first_index++;
+                                       if (FocusedItem.Index == first_index) {
+                                               if (first_index > 0) {
+                                                       int page_size = item_control.Height / items [0].Bounds.Height - 1;
+                                                       result = first_index - page_size + 1;
+                                                       if (result < 0)
+                                                               result = 0;
+                                               }
+                                       } else
+                                               result = first_index;
+                                       break;
                                }
                                return result;
                        }
@@ -1166,8 +1313,11 @@ namespace System.Windows.Forms
                        case Keys.Right:
                                if (col == (cols - 1))
                                        return -1;
-                               while (item_matrix [row, col + 1] == null)
-                                      row--;   
+                               while (item_matrix [row, col + 1] == null) {
+                                       row--;  
+                                       if (row < 0)
+                                               return -1;
+                               }
                                return item_matrix [row, col + 1].Index;
 
                        case Keys.Up:
@@ -1178,8 +1328,11 @@ namespace System.Windows.Forms
                        case Keys.Down:
                                if (row == (rows - 1) || row == Items.Count - 1)
                                        return -1;
-                               while (item_matrix [row + 1, col] == null)
-                                      col--;   
+                               while (item_matrix [row + 1, col] == null) {
+                                       col--;  
+                                       if (col < 0)
+                                               return -1;
+                               }
                                return item_matrix [row + 1, col].Index;
 
                        default:
@@ -1192,7 +1345,7 @@ namespace System.Windows.Forms
                private bool SelectItems (ArrayList sel_items)
                {
                        bool changed = false;
-                       ArrayList curr_items = (ArrayList) SelectedItems.list.Clone ();
+                       ArrayList curr_items = SelectedItems.List;
                        foreach (ListViewItem item in curr_items)
                                if (!sel_items.Contains (item)) {
                                        item.Selected = false;
@@ -1274,6 +1427,8 @@ namespace System.Windows.Forms
                        case Keys.Right:
                        case Keys.Up:                           
                        case Keys.Down:
+                       case Keys.PageUp:
+                       case Keys.PageDown:
                                SelectIndex (GetAdjustedIndex (key_data));
                                break;
 
@@ -1308,6 +1463,12 @@ namespace System.Windows.Forms
                        ke.Handled = KeySearchString (ke);
                }
 
+               private MouseEventArgs TranslateMouseEventArgs (MouseEventArgs args)
+               {
+                       Point loc = PointToClient (Control.MousePosition);
+                       return new MouseEventArgs (args.Button, args.Clicks, loc.X, loc.Y, args.Delta);
+               }
+
                internal class ItemControl : Control {
 
                        ListView owner;
@@ -1315,6 +1476,10 @@ namespace System.Windows.Forms
                        ListViewItem last_clicked_item;
                        bool hover_processed = false;
                        bool checking = false;
+                       
+                       ListViewLabelEditTextBox edit_text_box;
+                       internal ListViewItem edit_item;
+                       LabelEditEventArgs edit_args;
 
                        public ItemControl (ListView owner)
                        {
@@ -1328,8 +1493,8 @@ namespace System.Windows.Forms
 
                        void ItemsDoubleClick (object sender, EventArgs e)
                        {
-                               if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
-                                       owner.ItemActivate (this, e);
+                               if (owner.activation == ItemActivation.Standard)
+                                       owner.OnItemActivate (EventArgs.Empty);
                        }
 
                        enum BoxSelect {
@@ -1460,16 +1625,17 @@ namespace System.Windows.Forms
 
                        private void ItemsMouseDown (object sender, MouseEventArgs me)
                        {
-                               if (owner.items.Count == 0)
+                               if (owner.items.Count == 0) {
+                                       owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
                                        return;
+                               }
 
                                Point pt = new Point (me.X, me.Y);
                                foreach (ListViewItem item in owner.items) {
                                        if (me.Clicks == 1 && item.CheckRectReal.Contains (pt)) {
                                                checking = true;
-                                               if (me.Clicks > 1)
-                                                       return;
                                                ToggleCheckState (item);
+                                               owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
                                                return;
                                        }
 
@@ -1504,8 +1670,11 @@ namespace System.Windows.Forms
                                                owner.OnDoubleClick (EventArgs.Empty);
                                                if (owner.CheckBoxes)
                                                        ToggleCheckState (clicked_item);
-                                       } else if (me.Clicks == 1)
+                                       } else if (me.Clicks == 1) {
                                                owner.OnClick (EventArgs.Empty);
+                                               if (owner.LabelEdit && !changed)
+                                                       BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
+                                       }
                                } else {
                                        if (owner.MultiSelect) {
                                                Keys mods = XplatUI.State.ModifierKeys;
@@ -1516,34 +1685,38 @@ namespace System.Windows.Forms
                                                else
                                                        box_select_mode = BoxSelect.Normal;
                                                box_select_start = pt; 
-                                               prev_selection = (ArrayList) owner.SelectedItems.list.Clone ();
-                                       } else if (owner.selected_indices.Count > 0) {
+                                               prev_selection = owner.SelectedItems.List;
+                                       } else if (owner.SelectedItems.Count > 0) {
                                                owner.SelectedItems.Clear ();
                                                owner.OnSelectedIndexChanged (EventArgs.Empty);
                                        }
                                }
+
+                               owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
                        }
 
                        private void ItemsMouseMove (object sender, MouseEventArgs me)
                        {
-                               if (PerformBoxSelection (new Point (me.X, me.Y)))
-                                       return;
+                               bool done = PerformBoxSelection (new Point (me.X, me.Y));
 
-                               if (owner.HoverSelection && hover_processed) {
+                               if (!done && owner.HoverSelection && hover_processed) {
 
                                        Point pt = PointToClient (Control.MousePosition);
                                        ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
-                                       if (item == null || item.Selected)
-                                               return;
-
-                                       hover_processed = false;
-                                       XplatUI.ResetMouseHover (Handle);
+                                       if (item != null && !item.Selected) {
+                                               hover_processed = false;
+                                               XplatUI.ResetMouseHover (Handle);
+                                       }
                                }
+
+                               owner.OnMouseMove (owner.TranslateMouseEventArgs (me));
                        }
 
 
                        private void ItemsMouseHover (object sender, EventArgs e)
                        {
+                               owner.OnMouseHover(e);
+
                                if (Capture || !owner.HoverSelection)
                                        return;
 
@@ -1561,8 +1734,10 @@ namespace System.Windows.Forms
                        private void ItemsMouseUp (object sender, MouseEventArgs me)
                        {
                                Capture = false;
-                               if (owner.Items.Count == 0)
+                               if (owner.Items.Count == 0) {
+                                       owner.OnMouseUp (owner.TranslateMouseEventArgs (me));
                                        return;
+                               }
 
                                Point pt = new Point (me.X, me.Y);
 
@@ -1603,6 +1778,90 @@ namespace System.Windows.Forms
                                prev_selection = null;
                                box_select_mode = BoxSelect.None;
                                checking = false;
+                               owner.OnMouseUp (owner.TranslateMouseEventArgs (me));
+                       }
+                       
+                       internal void LabelEditFinished (object sender, EventArgs e)
+                       {
+                               EndEdit (edit_item);
+                       }
+                       
+                       internal void BeginEdit (ListViewItem item)
+                       {
+                               if (edit_item != null)
+                                       EndEdit (edit_item);
+                               
+                               if (edit_text_box == null) {
+                                       edit_text_box = new ListViewLabelEditTextBox ();
+                                       edit_text_box.BorderStyle = BorderStyle.FixedSingle;
+                                       edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
+                                       edit_text_box.Visible = false;
+                                       Controls.Add (edit_text_box);
+                               }
+                               
+                               item.EnsureVisible();
+                               
+                               edit_text_box.Reset ();
+                               
+                               switch (owner.view) {
+                                       case View.List:
+                                       case View.SmallIcon:
+                                       case View.Details:
+                                               edit_text_box.TextAlign = HorizontalAlignment.Left;
+                                               edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
+                                               SizeF sizef = DeviceContext.MeasureString (item.Text, item.Font);
+                                               edit_text_box.Width = (int)sizef.Width + 4;
+                                               edit_text_box.MaxWidth = owner.ClientRectangle.Width - edit_text_box.Bounds.X;
+                                               edit_text_box.WordWrap = false;
+                                               edit_text_box.Multiline = false;
+                                               break;
+                                       case View.LargeIcon:
+                                               edit_text_box.TextAlign = HorizontalAlignment.Center;
+                                               edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
+                                               sizef = DeviceContext.MeasureString (item.Text, item.Font);
+                                               edit_text_box.Width = (int)sizef.Width + 4;
+                                               edit_text_box.MaxWidth = item.GetBounds(ItemBoundsPortion.Entire).Width;
+                                               edit_text_box.MaxHeight = owner.ClientRectangle.Height - edit_text_box.Bounds.Y;
+                                               edit_text_box.WordWrap = true;
+                                               edit_text_box.Multiline = true;
+                                               break;
+                               }
+                               
+                               edit_text_box.Text = item.Text;
+                               edit_text_box.Font = item.Font;
+                               edit_text_box.Visible = true;
+                               edit_text_box.Focus ();
+                               edit_text_box.SelectAll ();
+                               
+                               edit_args = new LabelEditEventArgs (owner.Items.IndexOf(edit_item));
+                               owner.OnBeforeLabelEdit (edit_args);
+                               
+                               if (edit_args.CancelEdit)
+                                       EndEdit (item);
+                               
+                               edit_item = item;
+                       }
+                       
+                       internal void EndEdit (ListViewItem item)
+                       {
+                               if (edit_text_box != null && edit_text_box.Visible) {
+                                       edit_text_box.Visible = false;
+                               }
+                               
+                               if (edit_item != null && edit_item == item) {
+                                       owner.OnAfterLabelEdit (edit_args);
+                                       
+                                       if (!edit_args.CancelEdit) {
+                                               if (edit_args.Label != null)
+                                                       edit_item.Text = edit_args.Label;
+                                               else
+                                                       edit_item.Text = edit_text_box.Text;
+                                       }
+                                       
+                               }
+                               
+                               
+                               edit_item = null;
                        }
 
                        internal override void OnPaintInternal (PaintEventArgs pe)
@@ -1612,7 +1871,169 @@ namespace System.Windows.Forms
 
                        internal override void OnGotFocusInternal (EventArgs e)
                        {
-                               owner.Focus ();
+                               owner.Select (false, true);
+                       }
+
+                       internal override void OnLostFocusInternal (EventArgs e)
+                       {
+                               owner.Select (false, true);
+                       }
+               }
+               
+               internal class ListViewLabelEditTextBox : TextBox
+               {
+                       int max_width = -1;
+                       int min_width = -1;
+                       
+                       int max_height = -1;
+                       int min_height = -1;
+                       
+                       int old_number_lines = 1;
+                       
+                       SizeF text_size_one_char;
+                       
+                       public ListViewLabelEditTextBox ()
+                       {
+                               min_height = DefaultSize.Height;
+                               text_size_one_char = DeviceContext.MeasureString ("B", Font);
+                       }
+                       
+                       public int MaxWidth {
+                               set {
+                                       if (value < min_width)
+                                               max_width = min_width;
+                                       else
+                                               max_width = value;
+                               }
+                       }
+                       
+                       public int MaxHeight {
+                               set {
+                                       if (value < min_height)
+                                               max_height = min_height;
+                                       else
+                                               max_height = value;
+                               }
+                       }
+                       
+                       public new int Width {
+                               get {
+                                       return base.Width;
+                               }
+                               set {
+                                       min_width = value;
+                                       base.Width = value;
+                               }
+                       }
+                       
+                       public override Font Font {
+                               get {
+                                       return base.Font;
+                               }
+                               set {
+                                       base.Font = value;
+                                       text_size_one_char = DeviceContext.MeasureString ("B", Font);
+                               }
+                       }
+                       
+                       protected override void OnTextChanged (EventArgs e)
+                       {
+                               SizeF text_size = DeviceContext.MeasureString (Text, Font);
+                               
+                               int new_width = (int)text_size.Width + 8;
+                               
+                               if (!Multiline)
+                                       ResizeTextBoxWidth (new_width);
+                               else {
+                                       if (Width != max_width)
+                                               ResizeTextBoxWidth (new_width);
+                                       
+                                       int number_lines = Lines.Length;
+                                       
+                                       if (number_lines != old_number_lines) {
+                                               int new_height = number_lines * (int)text_size_one_char.Height + 4;
+                                               old_number_lines = number_lines;
+                                               
+                                               ResizeTextBoxHeight (new_height);
+                                       }
+                               }
+                               
+                               base.OnTextChanged (e);
+                       }
+                       
+                       protected override bool IsInputKey (Keys key_data)
+                       {
+                               if ((key_data & Keys.Alt) == 0) {
+                                       switch (key_data & Keys.KeyCode) {
+                                               case Keys.Enter:
+                                                       return true;
+                                       }
+                               }
+                               return base.IsInputKey (key_data);
+                       }
+                       
+                       protected override void OnKeyDown (KeyEventArgs e)
+                       {
+                               if (e.KeyCode == Keys.Return && Visible) {
+                                       this.Visible = false;
+                                       OnEditingFinished (e);
+                               }
+                       }
+                       
+                       protected override void OnLostFocus (EventArgs e)
+                       {
+                               if (Visible) {
+                                       OnEditingFinished (e);
+                               }
+                       }
+                       
+                       protected void OnEditingFinished (EventArgs e)
+                       {
+                               EventHandler eh = (EventHandler)(Events [EditingFinishedEvent]);
+                               if (eh != null)
+                                       eh (this, e);
+                       }
+                       
+                       private void ResizeTextBoxWidth (int new_width)
+                       {
+                               if (new_width > max_width)
+                                       base.Width = max_width;
+                               else 
+                               if (new_width >= min_width)
+                                       base.Width = new_width;
+                               else
+                                       base.Width = min_width;
+                       }
+                       
+                       private void ResizeTextBoxHeight (int new_height)
+                       {
+                               if (new_height > max_height)
+                                       base.Height = max_height;
+                               else 
+                               if (new_height >= min_height)
+                                       base.Height = new_height;
+                               else
+                                       base.Height = min_height;
+                       }
+                       
+                       public void Reset ()
+                       {
+                               max_width = -1;
+                               min_width = -1;
+                               
+                               max_height = -1;
+                               
+                               old_number_lines = 1;
+                               
+                               Text = String.Empty;
+                               
+                               Size = DefaultSize;
+                       }
+                       
+                       static object EditingFinishedEvent = new object ();
+                       public event EventHandler EditingFinished {
+                               add { Events.AddHandler (EditingFinishedEvent, value); }
+                               remove { Events.RemoveHandler (EditingFinishedEvent, value); }
                        }
                }
 
@@ -1677,6 +2098,8 @@ namespace System.Windows.Forms
 
                private void HorizontalScroller (object sender, EventArgs e)
                {
+                       item_control.EndEdit (item_control.edit_item);
+                       
                        // Avoid unnecessary flickering, when button is
                        // kept pressed at the end
                        if (h_marker != h_scroll.Value) {
@@ -1693,6 +2116,8 @@ namespace System.Windows.Forms
 
                private void VerticalScroller (object sender, EventArgs e)
                {
+                       item_control.EndEdit (item_control.edit_item);
+                       
                        // Avoid unnecessary flickering, when button is
                        // kept pressed at the end
                        if (v_marker != v_scroll.Value) {
@@ -1708,6 +2133,8 @@ namespace System.Windows.Forms
                protected override void CreateHandle ()
                {
                        base.CreateHandle ();
+                       for (int i = 0; i < SelectedItems.Count; i++)
+                               OnSelectedIndexChanged (EventArgs.Empty);
                }
 
                protected override void Dispose (bool disposing)
@@ -1746,20 +2173,23 @@ namespace System.Windows.Forms
 
                protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
                {
-                       if (AfterLabelEdit != null)
-                               AfterLabelEdit (this, e);
+                       LabelEditEventHandler eh = (LabelEditEventHandler)(Events [AfterLabelEditEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
                {
-                       if (BeforeLabelEdit != null)
-                               BeforeLabelEdit (this, e);
+                       LabelEditEventHandler eh = (LabelEditEventHandler)(Events [BeforeLabelEditEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnColumnClick (ColumnClickEventArgs e)
                {
-                       if (ColumnClick != null)
-                               ColumnClick (this, e);
+                       ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected override void OnEnabledChanged (EventArgs e)
@@ -1786,26 +2216,30 @@ namespace System.Windows.Forms
 
                protected virtual void OnItemActivate (EventArgs e)
                {
-                       if (ItemActivate != null)
-                               ItemActivate (this, e);
+                       EventHandler eh = (EventHandler)(Events [ItemActivateEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnItemCheck (ItemCheckEventArgs ice)
                {
-                       if (ItemCheck != null)
-                               ItemCheck (this, ice);
+                       EventHandler eh = (EventHandler)(Events [ItemCheckEvent]);
+                       if (eh != null)
+                               eh (this, ice);
                }
 
                protected virtual void OnItemDrag (ItemDragEventArgs e)
                {
-                       if (ItemDrag != null)
-                               ItemDrag (this, e);
+                       EventHandler eh = (EventHandler)(Events [ItemDragEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected virtual void OnSelectedIndexChanged (EventArgs e)
                {
-                       if (SelectedIndexChanged != null)
-                               SelectedIndexChanged (this, e);
+                       EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
+                       if (eh != null)
+                               eh (this, e);
                }
 
                protected override void OnSystemColorsChanged (EventArgs e)
@@ -1823,8 +2257,29 @@ namespace System.Windows.Forms
                        // FIXME: TODO
                }
 
+               bool refocusing = false;
+
                protected override void WndProc (ref Message m)
                {
+                       switch ((Msg)m.Msg) {
+                       case Msg.WM_KILLFOCUS:
+                               Control receiver = Control.FromHandle (m.WParam);
+                               if (receiver == item_control) {
+                                       has_focus = false;
+                                       refocusing = true;
+                                       return;
+                               }
+                               break;
+                       case Msg.WM_SETFOCUS:
+                               if (refocusing) {
+                                       has_focus = true;
+                                       refocusing = false;
+                                       return;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
                        base.WndProc (ref m);
                }
                #endregion // Protected Methods
@@ -1845,6 +2300,24 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               public void AutoResizeColumn (int columnIndex, ColumnHeaderAutoResizeStyle headerAutoResize)
+               {
+                       if (columnIndex < 0 || columnIndex >= columns.Count)
+                               throw new ArgumentOutOfRangeException ("columnIndex");
+
+                       columns [columnIndex].AutoResize (headerAutoResize);
+               }
+
+               public void AutoResizeColumns (ColumnHeaderAutoResizeStyle headerAutoResize)
+               {
+                       BeginUpdate ();
+                       foreach (ColumnHeader col in columns) 
+                               col.AutoResize (headerAutoResize);
+                       EndUpdate ();
+               }
+#endif
+
                public void BeginUpdate ()
                {
                        // flag to avoid painting
@@ -1877,10 +2350,12 @@ namespace System.Windows.Forms
                        if (view_rect.Contains (bounds))
                                return;
 
-                       if (bounds.Left < 0)
-                               h_scroll.Value += bounds.Left;
-                       else if (bounds.Right > view_rect.Right)
-                               h_scroll.Value += (bounds.Right - view_rect.Right);
+                       if (View != View.Details) {
+                               if (bounds.Left < 0)
+                                       h_scroll.Value += bounds.Left;
+                               else if (bounds.Right > view_rect.Right)
+                                       h_scroll.Value += (bounds.Right - view_rect.Right);
+                       }
 
                        if (bounds.Top < 0)
                                v_scroll.Value += bounds.Top;
@@ -1930,7 +2405,7 @@ namespace System.Windows.Forms
                                return;
                        }
                        
-                       items.list.Sort (item_sorter);
+                       items.Sort (item_sorter);
                        if (redraw)
                                this.Redraw (true);
                }
@@ -2006,10 +2481,10 @@ namespace System.Windows.Forms
                                        if (owner.AllowColumnReorder) {
                                                drag_x = me.X;
                                                drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
-                                               drag_column.column_rect = clicked_column.Rect;
+                                               drag_column.Rect = clicked_column.Rect;
                                                drag_to_index = GetReorderedIndex (clicked_column);
                                        }
-                                       clicked_column.pressed = true;
+                                       clicked_column.Pressed = true;
                                        Rectangle bounds = clicked_column.Rect;
                                        bounds.X -= owner.h_marker;
                                        Invalidate (bounds);
@@ -2017,14 +2492,28 @@ namespace System.Windows.Forms
                                }
                        }
 
+                       void StopResize ()
+                       {
+                               column_resize_active = false;
+                               resize_column = null;
+                               Capture = false;
+                               Cursor = Cursors.Default;
+                       }
+                       
                        private void HeaderMouseMove (object sender, MouseEventArgs me)
                        {
                                Point pt = new Point (me.X + owner.h_marker, me.Y);
 
                                if (column_resize_active)  {
-                                       resize_column.Width = pt.X - resize_column.X;
-                                       if (resize_column.Width < 0)
-                                               resize_column.Width = 0;
+                                       int width = pt.X - resize_column.X;
+                                       if (width < 0)
+                                               width = 0;
+
+                                       if (!owner.CanProceedWithResize (resize_column, width)){
+                                               StopResize ();
+                                               return;
+                                       }
+                                       resize_column.Width = width;
                                        return;
                                }
 
@@ -2034,9 +2523,9 @@ namespace System.Windows.Forms
                                        if (owner.AllowColumnReorder) {
                                                Rectangle r;
 
-                                               r = drag_column.column_rect;
+                                               r = drag_column.Rect;
                                                r.X = clicked_column.Rect.X + me.X - drag_x;
-                                               drag_column.column_rect = r;
+                                               drag_column.Rect = r;
 
                                                int x = me.X + owner.h_marker;
                                                ColumnHeader over = ColumnAtX (x);
@@ -2049,9 +2538,9 @@ namespace System.Windows.Forms
                                                Invalidate ();
                                        } else {
                                                ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
-                                               bool pressed = clicked_column.pressed;
-                                               clicked_column.pressed = over == clicked_column;
-                                               if (clicked_column.pressed ^ pressed) {
+                                               bool pressed = clicked_column.Pressed;
+                                               clicked_column.Pressed = over == clicked_column;
+                                               if (clicked_column.Pressed ^ pressed) {
                                                        Rectangle bounds = clicked_column.Rect;
                                                        bounds.X -= owner.h_marker;
                                                        Invalidate (bounds);
@@ -2083,14 +2572,14 @@ namespace System.Windows.Forms
                                Capture = false;
 
                                if (column_resize_active) {
-                                       column_resize_active = false;
-                                       resize_column = null;
-                                       Cursor = Cursors.Default;
+                                       int column_idx = resize_column.Index;
+                                       StopResize ();
+                                       owner.RaiseColumnWidthChanged (column_idx);
                                        return;
                                }
 
-                               if (clicked_column != null && clicked_column.pressed) {
-                                       clicked_column.pressed = false;
+                               if (clicked_column != null && clicked_column.Pressed) {
+                                       clicked_column.Pressed = false;
                                        Rectangle bounds = clicked_column.Rect;
                                        bounds.X -= owner.h_marker;
                                        Invalidate (bounds);
@@ -2284,9 +2773,10 @@ namespace System.Windows.Forms
 
                        private int [] GetIndices ()
                        {
-                               int [] indices = new int [Count];
-                               for (int i = 0; i < owner.CheckedItems.Count; i++) {
-                                       ListViewItem item = owner.CheckedItems [i];
+                               ArrayList checked_items = owner.CheckedItems.List;
+                               int [] indices = new int [checked_items.Count];
+                               for (int i = 0; i < checked_items.Count; i++) {
+                                       ListViewItem item = (ListViewItem) checked_items [i];
                                        indices [i] = item.Index;
                                }
                                return indices;
@@ -2295,14 +2785,15 @@ namespace System.Windows.Forms
 
                public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
                {
-                       internal readonly ArrayList list;
                        private readonly ListView owner;
+                       private ArrayList list;
 
                        #region Public Constructor
                        public CheckedListViewItemCollection (ListView owner)
                        {
-                               list = new ArrayList ();
                                this.owner = owner;
+                               this.owner.Items.Changed += new CollectionChangedHandler (
+                                       ItemsCollection_Changed);
                        }
                        #endregion      // Public Constructor
 
@@ -2312,7 +2803,7 @@ namespace System.Windows.Forms
                                get {
                                        if (!owner.CheckBoxes)
                                                return 0;
-                                       return list.Count;
+                                       return List.Count;
                                }
                        }
 
@@ -2322,14 +2813,24 @@ namespace System.Windows.Forms
 
                        public ListViewItem this [int index] {
                                get {
-                                       if (index < 0 || index >= Count)
+                                       ArrayList checked_items = List;
+                                       if (index < 0 || index >= checked_items.Count)
                                                throw new ArgumentOutOfRangeException ("index");
-                                       return (ListViewItem) list [index];
+                                       return (ListViewItem) checked_items [index];
+                               }
+                       }
+
+#if NET_2_0
+                       public virtual ListViewItem this [string key] {
+                               get {
+                                       int idx = IndexOfKey (key);
+                                       return idx == -1 ? null : (ListViewItem) List [idx];
                                }
                        }
+#endif
 
                        bool ICollection.IsSynchronized {
-                               get { return list.IsSynchronized; }
+                               get { return false; }
                        }
 
                        object ICollection.SyncRoot {
@@ -2351,21 +2852,28 @@ namespace System.Windows.Forms
                        {
                                if (!owner.CheckBoxes)
                                        return false;
-                               return list.Contains (item);
+                               return List.Contains (item);
                        }
 
-                       public void CopyTo (Array dest, int index)
+#if NET_2_0
+                       public virtual bool ContainsKey (string key)
+                       {
+                               return IndexOfKey (key) != -1;
+                       }
+#endif
+
+                       public void CopyTo (Array dest, int index)
                        {
                                if (!owner.CheckBoxes)
                                        return;
-                               list.CopyTo (dest, index);
+                               List.CopyTo (dest, index);
                        }
 
                        public IEnumerator GetEnumerator ()
                        {
                                if (!owner.CheckBoxes)
                                        return (new ListViewItem [0]).GetEnumerator ();
-                               return list.GetEnumerator ();
+                               return List.GetEnumerator ();
                        }
 
                        int IList.Add (object value)
@@ -2411,9 +2919,50 @@ namespace System.Windows.Forms
                        {
                                if (!owner.CheckBoxes)
                                        return -1;
-                               return list.IndexOf (item);
+                               return List.IndexOf (item);
+                       }
+
+#if NET_2_0
+                       public virtual int IndexOfKey (string key)
+                       {
+                               if (key == null || key.Length == 0)
+                                       return -1;
+
+                               ArrayList checked_items = List;
+                               for (int i = 0; i < checked_items.Count; i++) {
+                                       ListViewItem item = (ListViewItem) checked_items [i];
+                                       if (String.Compare (key, item.Name, true) == 0)
+                                               return i;
+                               }
+
+                               return -1;
                        }
+#endif
                        #endregion      // Public Methods
+
+                       internal ArrayList List {
+                               get {
+                                       if (list == null) {
+                                               list = new ArrayList ();
+                                               foreach (ListViewItem item in owner.Items) {
+                                                       if (item.Checked)
+                                                               list.Add (item);
+                                               }
+                                       }
+                                       return list;
+                               }
+                       }
+
+                       internal void Reset ()
+                       {
+                               // force re-population of list
+                               list = null;
+                       }
+
+                       private void ItemsCollection_Changed ()
+                       {
+                               Reset ();
+                       }
                }       // CheckedListViewItemCollection
 
                public class ColumnHeaderCollection : IList, ICollection, IEnumerable
@@ -2447,6 +2996,18 @@ namespace System.Windows.Forms
                                }
                        }
 
+#if NET_2_0
+                       public virtual ColumnHeader this [string key] {
+                               get {
+                                       int idx = IndexOfKey (key);
+                                       if (idx == -1)
+                                               return null;
+
+                                       return (ColumnHeader) list [idx];
+                               }
+                       }
+#endif
+
                        bool ICollection.IsSynchronized {
                                get { return true; }
                        }
@@ -2469,7 +3030,7 @@ namespace System.Windows.Forms
                        public virtual int Add (ColumnHeader value)
                        {
                                int idx;
-                               value.owner = this.owner;
+                               value.SetListView (this.owner);
                                idx = list.Add (value);
                                if (owner.IsHandleCreated) {
                                        owner.Redraw (true); 
@@ -2484,10 +3045,52 @@ namespace System.Windows.Forms
                                return colHeader;
                        }
 
+#if NET_2_0
+                       public virtual ColumnHeader Add (string text)
+                       {
+                               return Add (String.Empty, text);
+                       }
+
+                       public virtual ColumnHeader Add (string text, int iwidth)
+                       {
+                               return Add (String.Empty, text, iwidth);
+                       }
+
+                       public virtual ColumnHeader Add (string key, string text)
+                       {
+                               ColumnHeader colHeader = new ColumnHeader ();
+                               colHeader.Name = key;
+                               colHeader.Text = text;
+                               Add (colHeader);
+                               return colHeader;
+                       }
+
+                       public virtual ColumnHeader Add (string key, string text, int iwidth)
+                       {
+                               return Add (key, text, iwidth, HorizontalAlignment.Left, -1);
+                       }
+
+                       public virtual ColumnHeader Add (string key, string text, int iwidth, HorizontalAlignment textAlign, int imageIndex)
+                       {
+                               ColumnHeader colHeader = new ColumnHeader (key, text, iwidth, textAlign);
+                               colHeader.ImageIndex = imageIndex;
+                               Add (colHeader);
+                               return colHeader;
+                       }
+
+                       public virtual ColumnHeader Add (string key, string text, int iwidth, HorizontalAlignment textAlign, string imageKey)
+                       {
+                               ColumnHeader colHeader = new ColumnHeader (key, text, iwidth, textAlign);
+                               colHeader.ImageKey = imageKey;
+                               Add (colHeader);
+                               return colHeader;
+                       }
+#endif
+
                        public virtual void AddRange (ColumnHeader [] values)
                        {
                                foreach (ColumnHeader colHeader in values) {
-                                       colHeader.owner = this.owner;
+                                       colHeader.SetListView (this.owner);
                                        Add (colHeader);
                                }
                                
@@ -2505,6 +3108,13 @@ namespace System.Windows.Forms
                                return list.Contains (value);
                        }
 
+#if NET_2_0
+                       public virtual bool ContainsKey (string key)
+                       {
+                               return IndexOfKey (key) != -1;
+                       }
+#endif
+
                        public IEnumerator GetEnumerator ()
                        {
                                return list.GetEnumerator ();
@@ -2565,6 +3175,22 @@ namespace System.Windows.Forms
                                return list.IndexOf (value);
                        }
 
+#if NET_2_0
+                       public virtual int IndexOfKey (string key)
+                       {
+                               if (key == null || key.Length == 0)
+                                       return -1;
+
+                               for (int i = 0; i < list.Count; i++) {
+                                       ColumnHeader col = (ColumnHeader) list [i];
+                                       if (String.Compare (key, col.Name, true) == 0)
+                                               return i;
+                               }
+
+                               return -1;
+                       }
+#endif
+
                        public void Insert (int index, ColumnHeader value)
                        {
                                // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
@@ -2572,11 +3198,51 @@ namespace System.Windows.Forms
                                if (index < 0 || index > list.Count)
                                        throw new ArgumentOutOfRangeException ("index");
 
-                               value.owner = this.owner;
+                               value.SetListView (owner);
                                list.Insert (index, value);
                                owner.Redraw (true);
                        }
 
+#if NET_2_0
+                       public void Insert (int index, string text)
+                       {
+                               Insert (index, String.Empty, text);
+                       }
+
+                       public void Insert (int index, string text, int width)
+                       {
+                               Insert (index, String.Empty, text, width);
+                       }
+
+                       public void Insert (int index, string key, string text)
+                       {
+                               ColumnHeader colHeader = new ColumnHeader ();
+                               colHeader.Name = key;
+                               colHeader.Text = text;
+                               Insert (index, colHeader);
+                       }
+
+                       public void Insert (int index, string key, string text, int width)
+                       {
+                               ColumnHeader colHeader = new ColumnHeader (key, text, width, HorizontalAlignment.Left);
+                               Insert (index, colHeader);
+                       }
+
+                       public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
+                       {
+                               ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
+                               colHeader.ImageIndex = imageIndex;
+                               Insert (index, colHeader);
+                       }
+
+                       public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
+                       {
+                               ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
+                               colHeader.ImageKey = imageKey;
+                               Insert (index, colHeader);
+                       }
+#endif
+
                        public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
                        {
                                ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
@@ -2590,6 +3256,15 @@ namespace System.Windows.Forms
                                owner.Redraw (true);
                        }
 
+#if NET_2_0
+                       public virtual void RemoveByKey (string key)
+                       {
+                               int idx = IndexOfKey (key);
+                               if (idx != -1)
+                                       RemoveAt (idx);
+                       }
+#endif
+
                        public virtual void RemoveAt (int index)
                        {
                                if (index < 0 || index >= list.Count)
@@ -2606,7 +3281,7 @@ namespace System.Windows.Forms
 
                public class ListViewItemCollection : IList, ICollection, IEnumerable
                {
-                       internal ArrayList list;
+                       private readonly ArrayList list;
                        private readonly ListView owner;
 
                        #region Public Constructor
@@ -2641,13 +3316,29 @@ namespace System.Windows.Forms
                                        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");
 
+                                       if (value.ListView != null && value.ListView != owner)
+                                               throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value");
+
                                        value.Owner = owner;
                                        list [displayIndex] = value;
+                                       OnChange ();
 
                                        owner.Redraw (true);
                                }
                        }
 
+#if NET_2_0
+                       public virtual ListViewItem this [string key] {
+                               get {
+                                       int idx = IndexOfKey (key);
+                                       if (idx == -1)
+                                               return null;
+
+                                       return (ListViewItem) list [idx];
+                               }
+                       }
+#endif
+
                        bool ICollection.IsSynchronized {
                                get { return true; }
                        }
@@ -2667,6 +3358,7 @@ namespace System.Windows.Forms
                                                this [index] = (ListViewItem) value;
                                        else
                                                this [index] = new ListViewItem (value.ToString ());
+                                       OnChange ();
                                }
                        }
                        #endregion      // Public Properties
@@ -2677,11 +3369,19 @@ namespace System.Windows.Forms
                                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");
 
+                               if (value.ListView != null && value.ListView != owner)
+                                       throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value");
+
                                value.Owner = owner;
                                list.Add (value);
 
-                               owner.Sort (false);
-                               owner.Redraw (true);
+                               if (this.owner != null)
+                               {
+                                       owner.Sort (false);
+                                       OnChange ();
+                                       owner.Redraw (true);
+                               }
+
                                return value;
                        }
 
@@ -2697,28 +3397,56 @@ namespace System.Windows.Forms
                                return this.Add (item);
                        }
 
+#if NET_2_0
+                       public virtual ListViewItem Add (string text, string imageKey)
+                       {
+                               ListViewItem item = new ListViewItem (text, imageKey);
+                               return this.Add (item);
+                       }
+
+                       public virtual ListViewItem Add (string key, string text, int imageIndex)
+                       {
+                               ListViewItem item = new ListViewItem (text, imageIndex);
+                               item.Name = key;
+                               return this.Add (item);
+                       }
+
+                       public virtual ListViewItem Add (string key, string text, string imageKey)
+                       {
+                               ListViewItem item = new ListViewItem (text, imageKey);
+                               item.Name = key;
+                               return this.Add (item);
+                       }
+#endif
+
                        public void AddRange (ListViewItem [] values)
                        {
-                               list.Clear ();
-                               owner.SelectedItems.list.Clear ();
-                               owner.CheckedItems.list.Clear ();
+                               if (values == null)
+                                       throw new ArgumentNullException ("Argument cannot be null!", "values");
 
                                foreach (ListViewItem item in values) {
-                                       item.Owner = owner;
-                                       list.Add (item);
+                                       this.Add (item);
                                }
+                       }
 
-                               owner.Sort (false);
-                               owner.Redraw (true);
+#if NET_2_0
+                       public void AddRange (ListViewItemCollection items)
+                       {
+                               if (items == null)
+                                       throw new ArgumentNullException ("Argument cannot be null!", "items");
+
+                               ListViewItem[] itemArray = new ListViewItem[items.Count];
+                               items.CopyTo (itemArray,0);
+                               this.AddRange (itemArray);
                        }
+#endif
 
                        public virtual void Clear ()
                        {
                                owner.SetFocusedItem (null);
                                owner.h_scroll.Value = owner.v_scroll.Value = 0;
                                list.Clear ();
-                               owner.SelectedItems.list.Clear ();
-                               owner.CheckedItems.list.Clear ();
+                               OnChange ();
                                owner.Redraw (true);
                        }
 
@@ -2727,11 +3455,39 @@ namespace System.Windows.Forms
                                return list.Contains (item);
                        }
 
+#if NET_2_0
+                       public virtual bool ContainsKey (string key)
+                       {
+                               return IndexOfKey (key) != -1;
+                       }
+#endif
+
                        public void CopyTo (Array dest, int index)
                        {
                                list.CopyTo (dest, index);
                        }
 
+#if NET_2_0
+                       public ListViewItem [] Find (string key, bool searchAllSubitems)
+                       {
+                               if (key == null)
+                                       return new ListViewItem [0];
+
+                               List<ListViewItem> temp_list = new List<ListViewItem> ();
+                               
+                               for (int i = 0; i < list.Count; i++) {
+                                       ListViewItem lvi = (ListViewItem) list [i];
+                                       if (String.Compare (key, lvi.Name, true) == 0)
+                                               temp_list.Add (lvi);
+                               }
+
+                               ListViewItem [] retval = new ListViewItem [temp_list.Count];
+                               temp_list.CopyTo (retval);
+
+                               return retval;
+                       }
+#endif
+
                        public IEnumerator GetEnumerator ()
                        {
                                return list.GetEnumerator ();
@@ -2746,12 +3502,16 @@ namespace System.Windows.Forms
                                        li = (ListViewItem) item;
                                        if (list.Contains (li))
                                                throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
+
+                                       if (li.ListView != null && li.ListView != owner)
+                                               throw new ArgumentException ("Cannot add or insert the item '" + li.Text + "' in more than one place. You must first remove it from its current location or clone it.", "item");
                                }
                                else
                                        li = new ListViewItem (item.ToString ());
 
                                li.Owner = owner;
                                result = list.Add (li);
+                               OnChange ();
                                owner.Redraw (true);
 
                                return result;
@@ -2785,6 +3545,22 @@ namespace System.Windows.Forms
                                return list.IndexOf (item);
                        }
 
+#if NET_2_0
+                       public virtual int IndexOfKey (string key)
+                       {
+                               if (key == null || key.Length == 0)
+                                       return -1;
+
+                               for (int i = 0; i < list.Count; i++) {
+                                       ListViewItem lvi = (ListViewItem) list [i];
+                                       if (String.Compare (key, lvi.Name, true) == 0)
+                                               return i;
+                               }
+
+                               return -1;
+                       }
+#endif
+
                        public ListViewItem Insert (int index, ListViewItem item)
                        {
                                if (index < 0 || index > list.Count)
@@ -2793,8 +3569,12 @@ namespace System.Windows.Forms
                                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");
 
+                               if (item.ListView != null && item.ListView != owner)
+                                       throw new ArgumentException ("Cannot add or insert the item '" + item.Text + "' in more than one place. You must first remove it from its current location or clone it.", "item");
+
                                item.Owner = owner;
                                list.Insert (index, item);
+                               OnChange ();
                                owner.Redraw (true);
                                return item;
                        }
@@ -2809,27 +3589,64 @@ namespace System.Windows.Forms
                                return this.Insert (index, new ListViewItem (text, imageIndex));
                        }
 
+#if NET_2_0
+                       public ListViewItem Insert (int index, string key, string text, int imageIndex)
+                       {
+                               ListViewItem lvi = new ListViewItem (text, imageIndex);
+                               lvi.Name = key;
+                               return Insert (index, lvi);
+                       }
+#endif
+
                        public virtual void Remove (ListViewItem item)
                        {
                                if (!list.Contains (item))
                                        return;
                                        
-                               owner.SelectedItems.list.Remove (item);
-                               owner.CheckedItems.list.Remove (item);
+                               bool selection_changed = owner.SelectedItems.Contains (item);
                                list.Remove (item);
+                               OnChange ();
                                owner.Redraw (true);                            
+                               if (selection_changed)
+                                       owner.OnSelectedIndexChanged (EventArgs.Empty);
                        }
 
                        public virtual void RemoveAt (int index)
                        {
-                               ListViewItem item = this [index];
+                               if (index < 0 || index >= Count)
+                                       throw new ArgumentOutOfRangeException ("index");
+                               bool selection_changed = owner.SelectedIndices.Contains (index);
                                list.RemoveAt (index);
-                               owner.SelectedItems.list.Remove (item);
-                               owner.CheckedItems.list.Remove (item);
+                               OnChange ();
                                owner.Redraw (false);
+                               if (selection_changed)
+                                       owner.OnSelectedIndexChanged (EventArgs.Empty);
                        }
+
+#if NET_2_0
+                       public virtual void RemoveByKey (string key)
+                       {
+                               int idx = IndexOfKey (key);
+                               if (idx != -1)
+                                       RemoveAt (idx);
+                       }
+#endif
+
                        #endregion      // Public Methods
 
+                       internal event CollectionChangedHandler Changed;
+
+                       internal void Sort (IComparer comparer)
+                       {
+                               list.Sort (comparer);
+                               OnChange ();
+                       }
+
+                       internal void OnChange ()
+                       {
+                               if (Changed != null)
+                                       Changed ();
+                       }
                }       // ListViewItemCollection
 
                public class SelectedIndexCollection : IList, ICollection, IEnumerable
@@ -2852,7 +3669,13 @@ namespace System.Windows.Forms
                        }
 
                        public bool IsReadOnly {
-                               get { return true; }
+                               get { 
+#if NET_2_0
+                                       return false;
+#else
+                                       return true; 
+#endif
+                               }
                        }
 
                        public int this [int index] {
@@ -2873,7 +3696,13 @@ namespace System.Windows.Forms
                        }
 
                        bool IList.IsFixedSize {
-                               get { return true; }
+                               get { 
+#if NET_2_0
+                                       return false;
+#else
+                                       return true;
+#endif
+                               }
                        }
 
                        object IList.this [int index] {
@@ -2883,6 +3712,24 @@ namespace System.Windows.Forms
                        #endregion      // Public Properties
 
                        #region Public Methods
+#if NET_2_0
+                       public int Add (int itemIndex)
+                       {
+                               if (itemIndex < 0 || itemIndex >= owner.Items.Count)
+                                       throw new ArgumentOutOfRangeException ("index");
+
+                               owner.Items [itemIndex].Selected = true;
+                               if (!owner.IsHandleCreated)
+                                       return 0;
+
+                               return owner.SelectedItems.Count;
+                       }
+
+                       public void Clear ()
+                       {
+                               owner.SelectedItems.Clear ();
+                       }
+#endif
                        public bool Contains (int selectedIndex)
                        {
                                int [] indices = GetIndices ();
@@ -2953,30 +3800,41 @@ namespace System.Windows.Forms
                                }
                                return -1;
                        }
+
+#if NET_2_0
+                       public void Remove (int itemIndex)
+                       {
+                               if (itemIndex < 0 || itemIndex >= owner.Items.Count)
+                                       throw new ArgumentOutOfRangeException ("itemIndex");
+
+                               owner.Items [itemIndex].Selected = false;
+                       }
+#endif
                        #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];
+                               ArrayList selected_items = owner.SelectedItems.List;
+                               int [] indices = new int [selected_items.Count];
+                               for (int i = 0; i < selected_items.Count; i++) {
+                                       ListViewItem item = (ListViewItem) selected_items [i];
                                        indices [i] = item.Index;
                                }
                                return indices;
                        }
-
                }       // SelectedIndexCollection
 
                public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
                {
-                       internal ArrayList list;
                        private readonly ListView owner;
+                       private ArrayList list;
 
                        #region Public Constructor
                        public SelectedListViewItemCollection (ListView owner)
                        {
-                               list = new ArrayList ();
                                this.owner = owner;
+                               this.owner.Items.Changed += new CollectionChangedHandler (
+                                       ItemsCollection_Changed);
                        }
                        #endregion      // Public Constructor
 
@@ -2986,7 +3844,7 @@ namespace System.Windows.Forms
                                get {
                                        if (!owner.IsHandleCreated)
                                                return 0;
-                                       return list.Count;
+                                       return List.Count;
                                }
                        }
 
@@ -2996,14 +3854,27 @@ namespace System.Windows.Forms
 
                        public ListViewItem this [int index] {
                                get {
-                                       if (index < 0 || index >= Count)
+                                       ArrayList selected_items = List;
+                                       if (!owner.IsHandleCreated || index < 0 || index >= selected_items.Count)
                                                throw new ArgumentOutOfRangeException ("index");
-                                       return (ListViewItem) list [index];
+                                       return (ListViewItem) selected_items [index];
                                }
                        }
 
+#if NET_2_0
+                       public virtual ListViewItem this [string key] {
+                               get {
+                                       int idx = IndexOfKey (key);
+                                       if (idx == -1)
+                                               return null;
+
+                                       return (ListViewItem) List [idx];
+                               }
+                       }
+#endif
+
                        bool ICollection.IsSynchronized {
-                               get { return list.IsSynchronized; }
+                               get { return false; }
                        }
 
                        object ICollection.SyncRoot {
@@ -3026,32 +3897,36 @@ namespace System.Windows.Forms
                                if (!owner.IsHandleCreated)
                                        return;
 
-                               ArrayList copy = (ArrayList) list.Clone ();
-                               for (int i = 0; i < copy.Count; i++)
-                                       ((ListViewItem) copy [i]).Selected = false;
-
-                               list.Clear ();
+                               foreach (ListViewItem item in List)
+                                       item.Selected = false;
                        }
 
                        public bool Contains (ListViewItem item)
                        {
                                if (!owner.IsHandleCreated)
                                        return false;
-                               return list.Contains (item);
+                               return List.Contains (item);
+                       }
+
+#if NET_2_0
+                       public virtual bool ContainsKey (string key)
+                       {
+                               return IndexOfKey (key) != -1;
                        }
+#endif
 
                        public void CopyTo (Array dest, int index)
                        {
                                if (!owner.IsHandleCreated)
                                        return;
-                               list.CopyTo (dest, index);
+                               List.CopyTo (dest, index);
                        }
 
                        public IEnumerator GetEnumerator ()
                        {
                                if (!owner.IsHandleCreated)
                                        return (new ListViewItem [0]).GetEnumerator ();
-                               return list.GetEnumerator ();
+                               return List.GetEnumerator ();
                        }
 
                        int IList.Add (object value)
@@ -3092,12 +3967,147 @@ namespace System.Windows.Forms
                        {
                                if (!owner.IsHandleCreated)
                                        return -1;
-                               return list.IndexOf (item);
+                               return List.IndexOf (item);
+                       }
+
+#if NET_2_0
+                       public virtual int IndexOfKey (string key)
+                       {
+                               if (!owner.IsHandleCreated || key == null || key.Length == 0)
+                                       return -1;
+
+                               ArrayList selected_items = List;
+                               for (int i = 0; i < selected_items.Count; i++) {
+                                       ListViewItem item = (ListViewItem) selected_items [i];
+                                       if (String.Compare (item.Name, key, true) == 0)
+                                               return i;
+                               }
+
+                               return -1;
                        }
+#endif
                        #endregion      // Public Methods
 
+                       internal ArrayList List {
+                               get {
+                                       if (list == null) {
+                                               list = new ArrayList ();
+                                               foreach (ListViewItem item in owner.Items) {
+                                                       if (item.Selected)
+                                                               list.Add (item);
+                                               }
+                                       }
+                                       return list;
+                               }
+                       }
+
+                       internal void Reset ()
+                       {
+                               // force re-population of list
+                               list = null;
+                       }
+
+                       private void ItemsCollection_Changed ()
+                       {
+                               Reset ();
+                       }
                }       // SelectedListViewItemCollection
 
+               internal delegate void CollectionChangedHandler ();
+
                #endregion // Subclasses
+#if NET_2_0
+               protected override void OnResize (EventArgs e)
+               {
+                       base.OnResize (e);
+               }
+
+               protected override void OnMouseLeave (EventArgs e)
+               {
+                       base.OnMouseLeave (e);
+               }
+
+               //
+               // ColumnReorder event
+               //
+               static object ColumnReorderedEvent = new object ();
+               public event ColumnReorderedEventHandler ColumnReordered {
+                       add { Events.AddHandler (ColumnReorderedEvent, value); }
+                       remove { Events.RemoveHandler (ColumnReorderedEvent, value); }
+               }
+
+               protected virtual void OnColumnReordered (ColumnReorderedEventArgs e)
+               {
+                       ColumnReorderedEventHandler creh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
+
+                       if (creh != null)
+                               creh (this, e);
+               }
+
+               //
+               // ColumnWidthChanged
+               //
+               static object ColumnWidthChangedEvent = new object ();
+               public event ColumnWidthChangedEventHandler ColumnWidthChanged {
+                       add { Events.AddHandler (ColumnWidthChangedEvent, value); }
+                       remove { Events.RemoveHandler (ColumnWidthChangedEvent, value); }
+               }
+
+               protected virtual void OnColumnWidthChanged (ColumnWidthChangedEventArgs e)
+               {
+                       ColumnWidthChangedEventHandler eh = (ColumnWidthChangedEventHandler) (Events[ColumnWidthChangedEvent]);
+                       if (eh != null)
+                               eh (this, e);
+               }
+               
+               void RaiseColumnWidthChanged (int resize_column)
+               {
+                       ColumnWidthChangedEventArgs n = new ColumnWidthChangedEventArgs (resize_column);
+
+                       OnColumnWidthChanged (n);
+               }
+               
+               //
+               // ColumnWidthChanging
+               //
+               static object ColumnWidthChangingEvent = new object ();
+               public event ColumnWidthChangingEventHandler ColumnWidthChanging {
+                       add { Events.AddHandler (ColumnWidthChangingEvent, value); }
+                       remove { Events.RemoveHandler (ColumnWidthChangingEvent, value); }
+               }
+
+               protected virtual void OnColumnWidthChanging (ColumnWidthChangingEventArgs e)
+               {
+                       ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
+                       if (cwceh != null)
+                               cwceh (this, e);
+               }
+               
+               //
+               // 2.0 profile based implementation
+               //
+               bool CanProceedWithResize (ColumnHeader col, int width)
+               {
+                       ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
+                       if (cwceh == null)
+                               return true;
+                       
+                       ColumnWidthChangingEventArgs changing = new ColumnWidthChangingEventArgs (col.Index, width);
+                       cwceh (this, changing);
+                       return !changing.Cancel;
+               }
+#else
+               //
+               // 1.0 profile based implementation
+               //
+               bool CanProceedWithResize (ColumnHeader col, int width)
+               {
+                       return true;
+               }
+
+               void RaiseColumnWidthChanged (int resize_column)
+               {
+               }
+#endif
        }
 }