Grasshopper project system now uses csproj extension
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListView.cs
index caf4df3c886d602445f9bd01cceffdc31df8a5e5..66c32b3773557fa31670cb369f54fe44ce72e102 100644 (file)
@@ -49,6 +49,11 @@ 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;
@@ -94,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;
@@ -368,6 +376,11 @@ namespace System.Windows.Forms
                        get {
                                return focused_item;
                        }
+#if NET_2_0
+                       set {
+                               throw new NotImplementedException ();
+                       }
+#endif
                }
 
                public override Color ForeColor {
@@ -530,7 +543,9 @@ namespace System.Windows.Forms
                        }
                }
 
-               [LocalizableAttribute(true)]
+               [LocalizableAttribute (true)]
+               [MergableProperty (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
                public ListViewGroupCollection Groups {
                        get { return groups;    }
                }
@@ -616,6 +631,22 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               [Browsable (true)]
+               public Size TileSize {
+                       get {
+                               return tile_size;
+                       }
+                       set {
+                               if (value.Width <= 0 || value.Height <= 0)
+                                       throw new ArgumentOutOfRangeException ("value");
+
+                               tile_size = value;
+                               Redraw (true);
+                       }
+               }
+#endif
+
                [Browsable (false)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public ListViewItem TopItem {
@@ -636,15 +667,22 @@ namespace System.Windows.Forms
                                        return null;
                                }
                        }
+#if NET_2_0
+                       set {
+                               throw new NotImplementedException ();
+                       }
+#endif
                }
 
 #if NET_2_0
-               [MonoTODO("Implement")]
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               [DefaultValue (true)]
+               [Browsable (false)]
+               [MonoInternalNote ("Stub, not implemented")]
                public bool UseCompatibleStateImageBehavior {
                        get {
                                return false;
                        }
-
                        set {
                        }
                }
@@ -699,10 +737,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;                                   
                                        }
                                }
@@ -737,7 +775,7 @@ namespace System.Windows.Forms
                        Refresh ();
                }
 
-               const int text_padding = 5;
+               const int text_padding = 15;
 
                internal Size GetChildColumnSize (int index)
                {
@@ -747,7 +785,6 @@ namespace System.Windows.Forms
                        if (col.Width == -2) { // autosize = max(items, columnheader)
                                Size size = Size.Ceiling (this.DeviceContext.MeasureString
                                                          (col.Text, this.Font));
-                               size.Height += text_padding;
                                size.Width += text_padding;
                                ret_size = BiggestItem (index);
                                if (size.Width > ret_size.Width)
@@ -766,6 +803,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);
@@ -951,8 +990,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];
@@ -960,7 +1013,7 @@ 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]);
@@ -1023,11 +1076,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;
@@ -1037,8 +1110,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) {
@@ -1146,18 +1218,25 @@ 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 ();
@@ -1196,12 +1275,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;
                        }
@@ -1332,6 +1442,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;
 
@@ -1366,6 +1478,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;
@@ -1522,16 +1640,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;
                                        }
 
@@ -1587,28 +1706,32 @@ namespace System.Windows.Forms
                                                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;
 
@@ -1626,8 +1749,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);
 
@@ -1668,6 +1793,7 @@ 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)
@@ -1758,9 +1884,19 @@ namespace System.Windows.Forms
                                ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
                        }
 
-                       internal override void OnGotFocusInternal (EventArgs e)
+                       protected override void WndProc (ref Message m)
                        {
-                               owner.Focus ();
+                               switch ((Msg)m.Msg) {
+                               case Msg.WM_KILLFOCUS:
+                                       owner.Select (false, true);
+                                       break;
+                               case Msg.WM_SETFOCUS:
+                                       owner.Select (false, true);
+                                       break;
+                               default:
+                                       break;
+                               }
+                               base.WndProc (ref m);
                        }
                }
                
@@ -2141,8 +2277,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
@@ -2163,6 +2320,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
@@ -2195,16 +2370,62 @@ 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;
                        else if (bounds.Bottom > view_rect.Bottom)
                                v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
                }
+
+#if NET_2_0
+               public ListViewItem FindItemWithText (string text)
+               {
+                       if (items.Count == 0)
+                               return null;
+
+                       return FindItemWithText (text, true, 0, true);
+               }
+
+               public ListViewItem FindItemWithText (string text, bool includeSubItems, int startIndex)
+               {
+                       return FindItemWithText (text, includeSubItems, startIndex, true);
+               }
+
+               public ListViewItem FindItemWithText (string text, bool includeSubItems, int startIndex, bool prefixSearch)
+               {
+                       if (startIndex < 0 || startIndex >= items.Count)
+                               throw new ArgumentOutOfRangeException ("startIndex");
+
+                       if (text == null)
+                               throw new ArgumentNullException ("text");
+
+                       for (int i = startIndex; i < items.Count; i++) {
+                               ListViewItem lvi = items [i];
+
+                               if ((prefixSearch && lvi.Text.StartsWith (text, true, CultureInfo.CurrentCulture)) // prefix search
+                                               || String.Compare (lvi.Text, text, true) == 0) // match
+                                       return lvi;
+                       }
+
+                       if (includeSubItems) {
+                               for (int i = startIndex; i < items.Count; i++) {
+                                       ListViewItem lvi = items [i];
+                                       foreach (ListViewItem.ListViewSubItem sub_item in lvi.SubItems)
+                                               if ((prefixSearch && sub_item.Text.StartsWith (text, true, CultureInfo.CurrentCulture))
+                                                               || String.Compare (sub_item.Text, text, true) == 0)
+                                                       return lvi;
+                               }
+                       }
+
+                       return null;
+               }
+#endif
                
                public ListViewItem GetItemAt (int x, int y)
                {
@@ -2324,10 +2545,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);
@@ -2335,14 +2556,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;
                                }
 
@@ -2352,9 +2587,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);
@@ -2367,9 +2602,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);
@@ -2401,14 +2636,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);
@@ -2649,6 +2884,15 @@ namespace System.Windows.Forms
                                }
                        }
 
+#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 false; }
                        }
@@ -2675,6 +2919,13 @@ 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)
                        {
                                if (!owner.CheckBoxes)
@@ -2734,6 +2985,23 @@ namespace System.Windows.Forms
                                        return -1;
                                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 {
@@ -2826,7 +3094,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); 
@@ -2886,7 +3154,7 @@ namespace System.Windows.Forms
                        public virtual void AddRange (ColumnHeader [] values)
                        {
                                foreach (ColumnHeader colHeader in values) {
-                                       colHeader.owner = this.owner;
+                                       colHeader.SetListView (this.owner);
                                        Add (colHeader);
                                }
                                
@@ -2994,7 +3262,7 @@ 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);
                        }
@@ -3342,7 +3610,7 @@ namespace System.Windows.Forms
                        }
 
 #if NET_2_0
-                       public int IndexOfKey (string key)
+                       public virtual int IndexOfKey (string key)
                        {
                                if (key == null || key.Length == 0)
                                        return -1;
@@ -3420,7 +3688,7 @@ namespace System.Windows.Forms
                        }
 
 #if NET_2_0
-                       public void RemoveByKey (string key)
+                       public virtual void RemoveByKey (string key)
                        {
                                int idx = IndexOfKey (key);
                                if (idx != -1)
@@ -3658,7 +3926,7 @@ namespace System.Windows.Forms
                        }
 
 #if NET_2_0
-                       public ListViewItem this [string key] {
+                       public virtual ListViewItem this [string key] {
                                get {
                                        int idx = IndexOfKey (key);
                                        if (idx == -1)
@@ -3705,7 +3973,7 @@ namespace System.Windows.Forms
                        }
 
 #if NET_2_0
-                       public bool ContainsKey (string key)
+                       public virtual bool ContainsKey (string key)
                        {
                                return IndexOfKey (key) != -1;
                        }
@@ -3839,6 +4107,71 @@ namespace System.Windows.Forms
                        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
        }
 }