2005-02-23 Chris Bacon <chris.bacon@docobo.co.uk>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListView.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004 Novell, Inc. (http://www.novell.com)
21 //
22 // Author:
23 //      Ravindra (rkumar@novell.com)
24 //
25 // TODO:
26 //   - Keys to be handled ENTER/PAGE UP/PAGE DOWN/HOME/END/ARROWS/CTRL/SHIFT
27 //   - Item text editing
28 //   - Column resizing/reodering
29 //   - Feedback for item activation, change in cursor types as mouse moves.
30 //   - HideSelection
31
32
33 // NOT COMPLETE
34
35
36 using System.Collections;
37 using System.ComponentModel;
38 using System.ComponentModel.Design;
39 using System.Drawing;
40 using System.Runtime.InteropServices;
41
42 namespace System.Windows.Forms
43 {
44         [DefaultEvent ("SelectedIndexChanged")]
45         [DefaultProperty ("Items")]
46         [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, (string)null)]
47         public class ListView : Control
48         {
49                 private ItemActivation activation = ItemActivation.Standard;
50                 private ListViewAlignment alignment = ListViewAlignment.Top;
51                 private bool allow_column_reorder = false;
52                 private bool auto_arrange = true;
53                 private bool check_boxes = false;
54                 private CheckedIndexCollection checked_indices;
55                 private CheckedListViewItemCollection checked_items;
56                 private ColumnHeader clicked_column;
57                 private ListViewItem clicked_item;
58                 private ListViewItem last_clicked_item;
59                 private ColumnHeaderCollection columns;
60                 private bool ctrl_pressed;
61                 private bool shift_pressed;
62                 private bool draw_headers = true; // Used for painting. Do we need to draw column headers ?
63                 private ListViewItem focused_item;
64                 private bool full_row_select = false;
65                 private bool grid_lines = false;
66                 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
67                 private bool hide_selection = true;
68                 private bool hover_selection = false;
69                 private IComparer item_sorter;
70                 private ListViewItemCollection items;
71                 private bool label_edit = false;
72                 private bool label_wrap = true;
73                 private bool multiselect = true;
74                 private bool redraw = true;
75                 private bool scrollable = true;
76                 private SelectedIndexCollection selected_indices;
77                 private SelectedListViewItemCollection selected_items;
78                 private SortOrder sort_order = SortOrder.None;
79                 private ImageList state_image_list;
80                 private bool updating = false;
81                 private View view = View.LargeIcon;
82                 private int layout_wd;    // We might draw more than our client area
83                 private int layout_ht;    // therefore we need to have these two.
84                 //private TextBox editor;   // Used for editing an item text
85                 private ScrollBar h_scroll; // used for scrolling horizontally
86                 private ScrollBar v_scroll; // used for scrolling vertically
87                 private int h_marker;           // Position markers for scrolling
88                 private int v_marker;
89
90                 // internal variables
91                 internal ImageList large_image_list;
92                 internal ImageList small_image_list;
93                 internal Size text_size = Size.Empty;
94
95                 #region Events
96                 public event LabelEditEventHandler AfterLabelEdit;
97
98                 [Browsable (false)]
99                 [EditorBrowsable (EditorBrowsableState.Never)]
100                 public new event EventHandler BackgroundImageChanged;
101
102                 public event LabelEditEventHandler BeforeLabelEdit;
103                 public event ColumnClickEventHandler ColumnClick;
104                 public event EventHandler ItemActivate;
105                 public event ItemCheckEventHandler ItemCheck;
106                 public event ItemDragEventHandler ItemDrag;
107
108                 [Browsable (false)]
109                 [EditorBrowsable (EditorBrowsableState.Never)]
110                 public new event PaintEventHandler Paint;
111
112                 public event EventHandler SelectedIndexChanged;
113
114                 [Browsable (false)]
115                 [EditorBrowsable (EditorBrowsableState.Never)]
116                 public new event EventHandler TextChanged;
117                 #endregion // Events
118
119                 #region Public Constructors
120                 public ListView ()
121                 {
122                         background_color = ThemeEngine.Current.ColorWindow;
123                         checked_indices = new CheckedIndexCollection (this);
124                         checked_items = new CheckedListViewItemCollection (this);
125                         columns = new ColumnHeaderCollection (this);
126                         foreground_color = SystemColors.WindowText;
127                         items = new ListViewItemCollection (this);
128                         selected_indices = new SelectedIndexCollection (this);
129                         selected_items = new SelectedListViewItemCollection (this);
130
131                         border_style = BorderStyle.Fixed3D;
132
133                         // we are mostly scrollable
134                         h_scroll = new HScrollBar ();
135                         v_scroll = new VScrollBar ();
136                         h_marker = v_marker = 0;
137
138                         // scroll bars are disabled initially
139                         h_scroll.Visible = false;
140                         h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
141                         v_scroll.Visible = false;
142                         v_scroll.ValueChanged += new EventHandler(VerticalScroller);
143
144                         // event handlers
145                         base.DoubleClick += new EventHandler(ListView_DoubleClick);
146                         base.KeyDown += new KeyEventHandler(ListView_KeyDown);
147                         base.KeyUp += new KeyEventHandler(ListView_KeyUp);
148                         base.MouseDown += new MouseEventHandler(ListView_MouseDown);
149                         base.MouseHover += new EventHandler(ListView_MouseHover);
150                         base.MouseUp += new MouseEventHandler(ListView_MouseUp);
151                         base.MouseMove += new MouseEventHandler(ListView_MouseMove);
152                         base.Paint += new PaintEventHandler (ListView_Paint);
153                 }
154                 #endregion      // Public Constructors
155
156                 #region Private Internal Properties
157                 internal Size CheckBoxSize {
158                         get {
159                                 if (this.check_boxes) {
160                                         if (this.state_image_list != null)
161                                                 return this.state_image_list.ImageSize;
162                                         else
163                                                 return ThemeEngine.Current.ListViewCheckBoxSize;
164                                 }
165                                 return Size.Empty;
166                         }
167                 }
168
169                 internal bool CanMultiselect {
170                         get {
171                                 if (this.multiselect &&
172                                         (this.ctrl_pressed || this.shift_pressed))
173                                         return true;
174                                 else
175                                         return false;
176                         }
177                 }
178                 #endregion      // Private Internal Properties
179
180                 #region  Protected Properties
181                 protected override CreateParams CreateParams {
182                         get { return base.CreateParams; }
183                 }
184
185                 protected override Size DefaultSize {
186                         get { return ThemeEngine.Current.ListViewDefaultSize; }
187                 }
188                 #endregion      // Protected Properties
189
190                 #region Public Instance Properties
191                 [DefaultValue (ItemActivation.Standard)]
192                 public ItemActivation Activation {
193                         get { return activation; }
194                         set { activation = value; }
195                 }
196
197                 [DefaultValue (ListViewAlignment.Top)]
198                 [Localizable (true)]
199                 public ListViewAlignment Alignment {
200                         get { return alignment; }
201                         set {
202                                 if (this.alignment != value) {
203                                         alignment = value;
204                                         // alignment does not matter in Details/List views
205                                         if (this.view == View.LargeIcon ||
206                                             this.View == View.SmallIcon)
207                                                 this.Redraw (true);
208                                 }
209                         }
210                 }
211
212                 [DefaultValue (false)]
213                 public bool AllowColumnReorder {
214                         get { return allow_column_reorder; }
215                         set {
216                                 if (this.allow_column_reorder != value) {
217                                         allow_column_reorder = value;
218                                         // column reorder does not matter in Details view
219                                         if (this.view != View.Details)
220                                                 this.Redraw (true);
221                                 }
222                         }
223                 }
224
225                 [DefaultValue (true)]
226                 public bool AutoArrange {
227                         get { return auto_arrange; }
228                         set {
229                                 if (auto_arrange != value) {
230                                         auto_arrange = value;
231                                         // autoarrange does not matter in Details/List views
232                                         if (this.view == View.LargeIcon || this.View == View.SmallIcon)
233                                                 this.Redraw (true);
234                                 }
235                         }
236                 }
237
238                 public override Color BackColor {
239                         get {
240                                 if (background_color.IsEmpty)
241                                         return ThemeEngine.Current.ColorWindow;
242                                 else
243                                         return background_color;
244                         }
245                         set { background_color = value; }
246                 }
247
248                 [Browsable (false)]
249                 [EditorBrowsable (EditorBrowsableState.Never)]
250                 public override Image BackgroundImage {
251                         get { return background_image; }
252                         set {
253                                 if (value == background_image)
254                                         return;
255
256                                 background_image = value;
257                                 if (BackgroundImageChanged != null)
258                                         BackgroundImageChanged (this, new EventArgs ());
259                         }
260                 }
261
262                 [DefaultValue (BorderStyle.Fixed3D)]
263                 [DispId (-504)]
264                 public BorderStyle BorderStyle {
265                         get { return border_style; }
266                         set {
267                                 if (border_style != value) {
268                                         border_style = value;
269                                         this.Redraw (false);
270                                 }
271                         }
272                 }
273
274                 [DefaultValue (false)]
275                 public bool CheckBoxes {
276                         get { return check_boxes; }
277                         set {
278                                 if (check_boxes != value) {
279                                         check_boxes = value;
280                                         this.Redraw (true);
281                                 }
282                         }
283                 }
284
285                 [Browsable (false)]
286                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
287                 public CheckedIndexCollection CheckedIndices {
288                         get { return checked_indices; }
289                 }
290
291                 [Browsable (false)]
292                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
293                 public CheckedListViewItemCollection CheckedItems {
294                         get { return checked_items; }
295                 }
296
297                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
298                 [Localizable (true)]
299                 [MergableProperty (false)]
300                 public ColumnHeaderCollection Columns {
301                         get { return columns; }
302                 }
303
304                 [Browsable (false)]
305                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
306                 public ListViewItem FocusedItem {
307                         get { return focused_item; }
308                 }
309
310                 public override Color ForeColor {
311                         get {
312                                 if (foreground_color.IsEmpty)
313                                         return ThemeEngine.Current.ColorWindowText;
314                                 else
315                                         return foreground_color;
316                         }
317                         set { foreground_color = value; }
318                 }
319
320                 [DefaultValue (false)]
321                 public bool FullRowSelect {
322                         get { return full_row_select; }
323                         set { full_row_select = value; }
324                 }
325
326                 [DefaultValue (false)]
327                 public bool GridLines {
328                         get { return grid_lines; }
329                         set {
330                                 if (grid_lines != value) {
331                                         grid_lines = value;
332                                         this.Redraw (false);
333                                 }
334                         }
335                 }
336
337                 [DefaultValue (ColumnHeaderStyle.Clickable)]
338                 public ColumnHeaderStyle HeaderStyle {
339                         get { return header_style; }
340                         set {
341                                 if (header_style != value) {
342                                         header_style = value;
343                                         // header style matters only in Details view
344                                         if (this.view == View.Details)
345                                                 this.Redraw (false);
346                                 }
347                         }
348                 }
349
350                 [DefaultValue (true)]
351                 public bool HideSelection {
352                         get { return hide_selection; }
353                         set {
354                                 if (hide_selection != value) {
355                                         hide_selection = value;
356                                         this.Redraw (false);
357                                 }
358                         }
359                 }
360
361                 [DefaultValue (false)]
362                 public bool HoverSelection {
363                         get { return hover_selection; }
364                         set { hover_selection = value; }
365                 }
366
367                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
368                 [Localizable (true)]
369                 [MergableProperty (false)]              
370                 public ListViewItemCollection Items {
371                         get { return items; }
372                 }
373
374                 [DefaultValue (false)]
375                 public bool LabelEdit {
376                         get { return label_edit; }
377                         set { label_edit = value; }
378                 }
379
380                 [DefaultValue (true)]
381                 [Localizable (true)]
382                 public bool LabelWrap {
383                         get { return label_wrap; }
384                         set {
385                                 if (label_wrap != value) {
386                                         label_wrap = value;
387                                         this.Redraw (true);
388                                 }
389                         }
390                 }
391
392                 [DefaultValue (null)]
393                 public ImageList LargeImageList {
394                         get { return large_image_list; }
395                         set {
396                                 large_image_list = value;
397                                 this.Redraw (true);
398                         }
399                 }
400
401                 [Browsable (false)]
402                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
403                 public IComparer ListViewItemSorter {
404                         get { return item_sorter; }
405                         set { item_sorter = value; }
406                 }
407
408                 [DefaultValue (true)]
409                 public bool MultiSelect {
410                         get { return multiselect; }
411                         set { multiselect = value; }
412                 }
413
414                 [DefaultValue (true)]
415                 public bool Scrollable {
416                         get { return scrollable; }
417                         set {
418                                 if (scrollable != value) {
419                                         scrollable = value;
420                                         this.Redraw (true);
421                                 }
422                         }
423                 }
424
425                 [Browsable (false)]
426                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
427                 public SelectedIndexCollection SelectedIndices {
428                         get { return selected_indices; }
429                 }
430
431                 [Browsable (false)]
432                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
433                 public SelectedListViewItemCollection SelectedItems {
434                         get { return selected_items; }
435                 }
436
437                 [DefaultValue (null)]
438                 public ImageList SmallImageList {
439                         get { return small_image_list; }
440                         set {
441                                 small_image_list = value;
442                                 this.Redraw (true);
443                         }
444                 }
445
446                 [DefaultValue (SortOrder.None)]
447                 public SortOrder Sorting {
448                         get { return sort_order; }
449                         set { sort_order = value; }
450                 }
451
452                 [DefaultValue (null)]
453                 public ImageList StateImageList {
454                         get { return state_image_list; }
455                         set {
456                                 state_image_list = value;
457                                 this.Redraw (true);
458                         }
459                 }
460
461                 [Bindable (false)]
462                 [Browsable (false)]
463                 [EditorBrowsable (EditorBrowsableState.Never)]
464                 public override string Text {
465                         get { return text; } 
466                         set {
467                                 if (value == text)
468                                         return;
469
470                                 text = value;
471                                 this.Redraw (true);
472
473                                 if (TextChanged != null)
474                                         TextChanged (this, new EventArgs ());
475                         }
476                 }
477
478                 [Browsable (false)]
479                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
480                 public ListViewItem TopItem {
481                         get {
482                                 // there is no item
483                                 if (this.items.Count == 0)
484                                         return null;
485                                 // if contents are not scrolled
486                                 // it is the first item
487                                 else if (h_marker == 0 && v_marker == 0)
488                                         return this.items [0];
489                                 // do a hit test for the scrolled position
490                                 else {
491                                         foreach (ListViewItem item in this.items) {
492                                                 if (item.EntireRect.Contains (h_marker, v_marker))
493                                                         return item;
494                                         }
495                                         return null;
496                                 }
497                         }
498                 }
499
500                 [DefaultValue (View.LargeIcon)]
501                 public View View {
502                         get { return view; }
503                         set { view = value; }
504                 }
505                 #endregion      // Public Instance Properties
506
507                 #region Internal Methods Properties
508                 internal int TotalWidth {
509                         get { return Math.Max (this.Width, this.layout_wd); }
510                 }
511
512                 internal int TotalHeight {
513                         get { return Math.Max (this.Height, this.layout_ht); }
514                 }
515
516                 internal void Redraw (bool recalculate)
517                 {
518                         // Avoid calculations when control is being updated
519                         if (this.updating)
520                                 return;
521
522                         if (recalculate)
523                                 CalculateListView (this.alignment);
524
525                         redraw = true;
526                         Refresh ();
527                 }
528
529                 internal Size GetChildColumnSize (int index)
530                 {
531                         Size ret_size = Size.Empty;
532                         ColumnHeader col = this.columns [index];
533
534                         if (col.Width == -2) { // autosize = max(items, columnheader)
535                                 Size size = Size.Ceiling (this.DeviceContext.MeasureString
536                                                           (col.Text, this.Font));
537                                 ret_size = BiggestItem (index);
538                                 if (size.Width > ret_size.Width)
539                                         ret_size = size;
540                         }
541                         else { // -1 and all the values < -2 are put under one category
542                                 ret_size = BiggestItem (index);
543                                 // fall back to empty columns' width if no subitem is available for a column
544                                 if (ret_size.IsEmpty) {
545                                         ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
546                                         if (col.Text.Length > 0)
547                                                 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
548                                                                                 (col.Text, this.Font)).Height;
549                                         else
550                                                 ret_size.Height = this.Font.Height;
551                                 }
552                         }
553
554                         // adjust the size for icon and checkbox for 0th column
555                         if (index == 0) {
556                                 ret_size.Width += (this.CheckBoxSize.Width + 4);
557                                 if (this.small_image_list != null)
558                                         ret_size.Width += this.small_image_list.ImageSize.Width;
559                         }
560                         return ret_size;
561                 }
562
563                 // Returns the size of biggest item text in a column.
564                 private Size BiggestItem (int col)
565                 {
566                         Size temp = Size.Empty;
567                         Size ret_size = Size.Empty;
568
569                         // 0th column holds the item text, we check the size of
570                         // the various subitems falling in that column and get
571                         // the biggest one's size.
572                         foreach (ListViewItem item in items) {
573                                 if (col >= item.SubItems.Count)
574                                         continue;
575
576                                 temp = Size.Ceiling (this.DeviceContext.MeasureString
577                                                      (item.SubItems [col].Text, this.Font));
578                                 if (temp.Width > ret_size.Width)
579                                         ret_size = temp;
580                         }
581
582                         // adjustment for space
583                         if (!ret_size.IsEmpty)
584                                 ret_size.Width += 4;
585
586                         return ret_size;
587                 }
588
589                 // Sets the size of the biggest item text as per the view
590                 private void CalcTextSize ()
591                 {                       
592                         // clear the old value
593                         text_size = Size.Empty;
594
595                         if (items.Count == 0)
596                                 return;
597
598                         text_size = BiggestItem (0);
599
600                         if (view == View.LargeIcon && this.label_wrap) {
601                                 Size temp = Size.Empty;
602                                 if (this.check_boxes)
603                                         temp.Width += 2 * this.CheckBoxSize.Width;
604                                 if (large_image_list != null)
605                                         temp.Width += large_image_list.ImageSize.Width;
606                                 if (temp.Width == 0)
607                                         temp.Width = 43;
608                                 // wrapping is done for two lines only
609                                 if (text_size.Width > temp.Width) {
610                                         text_size.Width = temp.Width;
611                                         text_size.Height *= 2;
612                                 }
613                         }
614                         else if (view == View.List) {
615                                 // in list view max text shown in determined by the
616                                 // control width, even if scolling is enabled.
617                                 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
618                                 if (this.small_image_list != null)
619                                         max_wd -= this.small_image_list.ImageSize.Width;
620
621                                 if (text_size.Width > max_wd)
622                                         text_size.Width = max_wd;
623                         }
624
625                         // we do the default settings, if we have got 0's
626                         if (text_size.Height <= 0)
627                                 text_size.Height = this.Font.Height;
628                         if (text_size.Width <= 0)
629                                 text_size.Width = this.Width;
630
631                         // little adjustment
632                         text_size.Width += 4;
633                         text_size.Height += 2;
634                 }
635
636                 // Sets the location of every item on
637                 // the ListView as per the view
638                 private void CalculateListView (ListViewAlignment align)
639                 {
640                         int current_pos_x = 0; // our x-position marker
641                         int current_pos_y = 0; // our y-position marker
642                         int item_ht;
643                         int item_wd;
644                         int max;         // max x_pos or y_pos depending on the alignment
645                         int current = 0; // current row or column
646                         int vertical_spacing = ThemeEngine.Current.ListViewVerticalSpacing;
647                         int horizontal_spacing = ThemeEngine.Current.ListViewHorizontalSpacing;
648
649                         CalcTextSize ();
650
651                         switch (view) {
652
653                         case View.Details:
654                                 // ColumnHeaders are not drawn if headerstyle is none
655                                 int ht = (this.header_style == ColumnHeaderStyle.None) ? 
656                                         2 : this.Font.Height + 2;
657                                 if (columns.Count > 0) {
658                                         foreach (ColumnHeader col in columns) {
659                                                 col.X = current_pos_x;
660                                                 col.Y = 0;
661                                                 col.CalcColumnHeader ();
662                                                 current_pos_x += col.Wd;
663                                         }
664                                         this.layout_wd = current_pos_x;
665                                 }
666                                 // set the position marker for placing items
667                                 // vertically down
668                                 current_pos_y = ht;
669
670                                 if (items.Count > 0) {
671                                         foreach (ListViewItem item in items) {
672                                                 item.location.X = 0;
673                                                 item.location.Y = current_pos_y;
674                                                 item.CalcListViewItem ();
675                                                 current_pos_y += item.EntireRect.Height;
676                                         }
677                                         this.layout_ht = current_pos_y;
678
679                                         // some space for bottom gridline
680                                         if (this.grid_lines)
681                                                 this.layout_ht += 2;
682                                 }
683                                 break;
684
685                         case View.SmallIcon:
686                                 vertical_spacing = 0;
687                                 horizontal_spacing = 0;
688                                 goto case View.LargeIcon;
689
690                         case View.LargeIcon:
691                                 if (items.Count > 0) {
692                                         items [0].CalcListViewItem ();
693                                         item_ht = items [0].EntireRect.Height;
694                                         item_wd = items [0].EntireRect.Width;
695
696                                         // top (default) and snaptogrid alignments are handled same way
697                                         if (align == ListViewAlignment.Left) {
698                                                 max = this.Height;
699                                                 foreach (ListViewItem item in items) {
700                                                         item.location.X = current_pos_x +
701                                                                 horizontal_spacing;
702                                                         item.location.Y = current_pos_y;
703                                                         item.CalcListViewItem ();
704                                                         current_pos_y += item_ht;
705
706                                                         current ++; // just to know about the last element
707                                                         // we just did the last item
708                                                         if (current == items.Count) {
709                                                                 if (max < current_pos_y)
710                                                                         max = current_pos_y;
711                                                                 current_pos_x = item.EntireRect.Right;
712                                                                 break;
713                                                         }
714                                                         else {
715                                                                 // is there enough space for another row ?
716                                                                 if ((current_pos_y + vertical_spacing
717                                                                      + item_ht) <= this.Height)
718                                                                         current_pos_y += vertical_spacing;
719                                                                 else {
720                                                                         // start another column
721                                                                         // make current_pos_y as the
722                                                                         // max value and reset
723                                                                         // current_pos_y value.
724                                                                         max = current_pos_y;
725                                                                         current_pos_x += item_wd;
726                                                                         current_pos_y = 0;
727                                                                 }
728                                                         }
729                                                 }
730                                                 // adjust the layout dimensions
731                                                 this.layout_ht = max;
732                                                 this.layout_wd = current_pos_x;
733                                         }
734                                         else { // other default/top alignment
735                                                 max = this.Width;
736                                                 foreach (ListViewItem item in items) {
737                                                         item.location.X = current_pos_x +
738                                                                 horizontal_spacing;
739
740                                                         item.location.Y = current_pos_y;
741                                                         item.CalcListViewItem ();
742                                                         current_pos_x += item_wd;
743
744                                                         current ++; // just to know about the last element
745                                                         // we just did the last item
746                                                         if (current == items.Count) {
747                                                                 if (max < current_pos_x)
748                                                                         max = current_pos_x;
749                                                                 current_pos_y = item.EntireRect.Bottom;
750                                                                 break;
751                                                         }
752                                                         else {
753                                                                 // is there enough space for another column?
754                                                                 if ((current_pos_x + horizontal_spacing
755                                                                      + item_wd) <= this.Width)
756                                                                         continue;
757                                                                 else {
758                                                                         // start another row
759                                                                         // make current_pos_x as the
760                                                                         // max value and reset
761                                                                         // current_pos_x value.
762                                                                         max = current_pos_x;
763                                                                         current_pos_y += (item_ht +
764                                                                                           vertical_spacing);
765                                                                         current_pos_x = 0;
766                                                                 }
767                                                         }
768                                                 }
769                                                 // adjust the layout dimensions
770                                                 this.layout_wd = max;
771                                                 this.layout_ht = current_pos_y;
772                                         }
773                                 }
774                                 break;
775
776                         case View.List:
777                                 if (items.Count > 0) {
778                                         items [0].CalcListViewItem ();
779                                         item_ht = items [0].EntireRect.Height;
780                                         item_wd = items [0].EntireRect.Width;
781
782                                         max = this.Height / item_ht;
783                                         if (max == 0)
784                                                 max = 1; // we draw at least one row
785
786                                         foreach (ListViewItem item in items) {
787                                                 item.location.X = current_pos_x;
788                                                 item.location.Y = current_pos_y;
789                                                 item.CalcListViewItem ();
790                                                 current ++;
791                                                 if (current == max) {
792                                                         current_pos_x += item_wd;
793                                                         current_pos_y = 0;
794                                                         current = 0;
795                                                 }
796                                                 else
797                                                         current_pos_y += item_ht;
798                                         }
799
800                                         // adjust the layout dimensions
801                                         this.layout_ht = max * item_ht;
802                                         if (current == 0) // we have fully filled layout
803                                                 this.layout_wd = current_pos_x;
804                                         else
805                                                 this.layout_wd = current_pos_x + item_wd;
806                                 }
807                                 break;
808                         }
809
810                         if (this.scrollable && this.items.Count > 0) {
811                                 // making a scroll bar visible might make
812                                 // other scroll bar visible
813                                 if (this.layout_wd > this.Width) {
814                                         this.h_scroll.Visible = true;
815                                         if ((this.layout_ht + this.h_scroll.Height) > this.Height)
816                                                 this.v_scroll.Visible = true;
817                                 }
818                                 else if (this.layout_ht > this.Height) {
819                                         this.v_scroll.Visible = true;
820                                         if ((this.layout_wd + this.v_scroll.Width) > this.Width)
821                                                 this.h_scroll.Visible = true;
822                                 }
823
824                                 // create big enough buffers
825                                 if (this.layout_wd > this.Width ||
826                                     this.layout_ht > this.Height)
827                                         this.CreateBuffers (this.TotalWidth, this.TotalHeight);
828
829                                 if (this.h_scroll.Visible) {
830                                         this.h_scroll.Location = new Point (0, this.Height 
831                                                                             - this.h_scroll.Height);
832                                         
833                                         this.h_scroll.Minimum = 0;
834
835                                         // if v_scroll is visible, adjust the maximum of the
836                                         // h_scroll to account for the width of v_scroll
837                                         if (this.v_scroll.Visible) {
838                                                 this.h_scroll.Maximum = this.layout_wd + this.v_scroll.Width;
839                                                 this.h_scroll.Width = this.Width - this.v_scroll.Width;
840                                         }
841                                         else {
842                                                 this.h_scroll.Maximum = this.layout_wd;
843                                                 this.h_scroll.Width = this.Width;
844                                         }
845    
846                                         this.h_scroll.LargeChange = this.Width;
847                                         this.h_scroll.SmallChange = this.Font.Height;
848                                 }
849
850                                 // vertical scrollbar
851                                 if (this.v_scroll.Visible) {
852                                         this.v_scroll.Location = new Point (this.Width 
853                                                                             - this.v_scroll.Width, 0);
854
855                                         this.v_scroll.Minimum = 0;
856
857                                         // if h_scroll is visible, adjust the maximum of the
858                                         // v_scroll to account for the height of h_scroll
859                                         if (this.h_scroll.Visible) {
860                                                 this.v_scroll.Maximum = this.layout_ht + this.h_scroll.Height;
861                                                 this.v_scroll.Height = this.Height - this.h_scroll.Height;
862                                         }
863                                         else {
864                                                 this.v_scroll.Maximum = this.layout_ht;
865                                                 this.v_scroll.Height = this.Height;
866                                         }
867
868                                         this.v_scroll.LargeChange = this.Height;
869                                         this.v_scroll.SmallChange = this.Font.Height;
870                                 }
871                         }
872                         else {
873                                 this.h_scroll.Visible = false;
874                                 this.v_scroll.Visible = false;
875                         }
876                 }
877
878                 // Event Handlers
879                 private void ListView_DoubleClick (object sender, EventArgs e)
880                 {
881                         if (this.activation == ItemActivation.Standard
882                             && this.ItemActivate != null)
883                                 this.ItemActivate (this, e);
884                 }
885
886                 private void ListView_KeyDown (object sender, KeyEventArgs ke)
887                 {
888                         int index = -1;
889                         if (ke.Handled)
890                                 return;
891
892                         ke.Handled = true;
893
894                         switch (ke.KeyCode) {
895
896                         case Keys.ControlKey:
897                                 this.ctrl_pressed = true;
898                                 break;
899
900                         case Keys.Down:
901                                 // FIXME:TODO
902                                 break;
903
904                         case Keys.End:
905                                 this.v_scroll.Value = this.v_scroll.Maximum;
906                                 break;
907
908                         case Keys.Home:
909                                 this.v_scroll.Value = this.v_scroll.Minimum;
910                                 break;
911
912                         case Keys.Left:
913                                 index = -1;
914                                 if (this.last_clicked_item != null)
915                                         index = this.last_clicked_item.Index;
916                                 else
917                                         break;
918
919                                 if (index > 0)
920                                         index -= 1;
921
922                                 this.last_clicked_item = this.items [index];
923                                 this.last_clicked_item.Selected = true;
924                                 this.EnsureVisible (index);
925                                 break;
926
927                         case Keys.Right:
928                                 if (this.last_clicked_item != null)
929                                         index = this.last_clicked_item.Index + 1;
930                                 else
931                                         index = 1;
932
933                                 if (index == this.items.Count)
934                                         break;
935
936                                 this.last_clicked_item = this.items [index];
937                                 this.last_clicked_item.Selected = true;
938                                 this.EnsureVisible (index);
939                                 break;
940
941                         case Keys.ShiftKey:
942                                 this.shift_pressed = true;
943                                 break;
944
945                         case Keys.Up:
946                                 // FIXME:TODO
947                                 break;
948
949                         default:
950                                 ke.Handled = false;
951                                 break;
952                         }
953                 }
954
955                 private void ListView_KeyUp (object sender, KeyEventArgs ke)
956                 {
957                         if (!ke.Handled) {
958                                 if (ke.KeyCode == Keys.ControlKey)
959                                         this.ctrl_pressed = false;
960
961                                 if (ke.KeyCode == Keys.ShiftKey)
962                                         this.shift_pressed = false;
963                                 ke.Handled = true;
964                         }
965                 }
966
967                 private void ListView_MouseDown (object sender, MouseEventArgs me)
968                 {
969                         if (items.Count == 0)
970                                 return;
971
972                         Point hit = Point.Empty;
973                         if (this.HeaderStyle != ColumnHeaderStyle.None) {
974                                 // take horizontal scrolling into account
975                                 hit = new Point (me.X + h_marker, me.Y);
976
977                                 // hit test on columns
978                                 if (this.view == View.Details && this.columns.Count > 0) {
979                                         foreach (ColumnHeader col in this.columns) {
980                                                 if (col.Rect.Contains (hit)) {
981                                                         this.clicked_column = col;
982                                                         this.Capture = true;
983                                                         break;
984                                                 }
985                                         }
986
987                                         if (this.clicked_column != null) {
988                                                 this.clicked_column.pressed = true;
989                                                 this.draw_headers = true;
990                                                 this.Redraw (false);
991                                                 return;
992                                         }
993                                 }
994                         }
995
996                         // hit test on items
997                         // we need to take scrolling into account
998                         hit = new Point (me.X + h_marker, me.Y + v_marker);
999                         foreach (ListViewItem item in this.items) {
1000                                 if (item.CheckRect.Contains (hit)) {
1001                                         CheckState curr_state = item.Checked ?
1002                                                 CheckState.Checked : CheckState.Unchecked;
1003                                         if (item.Checked)
1004                                                 item.Checked = false;
1005                                         else
1006                                                 item.Checked = true;
1007
1008                                         CheckState new_state = item.Checked ?
1009                                                 CheckState.Checked : CheckState.Unchecked;
1010                                         this.Redraw (false);
1011
1012                                         // Raise the ItemCheck event
1013                                         ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index,
1014                                                                                          curr_state,
1015                                                                                          new_state);
1016                                         this.OnItemCheck (ice);
1017                                         break;
1018                                 }
1019
1020                                 if (this.view == View.Details &&
1021                                     this.FullRowSelect == false) {
1022                                         if (item.LabelRect.Contains (hit)) {
1023                                                 this.clicked_item = item;
1024                                                 break;
1025                                         }
1026                                 }
1027                                 else {
1028                                         if (item.EntireRect.Contains (hit)) {
1029                                                 this.clicked_item = item;
1030                                                 break;
1031                                         }
1032                                 }
1033                         }
1034
1035                         if (this.clicked_item != null) {
1036                                 this.clicked_item.Selected = true;
1037                                 // Raise the event
1038                                 this.OnSelectedIndexChanged (new EventArgs ());
1039
1040                                 this.Redraw (false);
1041                         }
1042
1043                         // set the FocusedItem to be the current clicked_item
1044                         this.focused_item = this.clicked_item;
1045                 }
1046
1047                 private void ListView_MouseHover (object sender, EventArgs e)
1048                 {
1049                         // handle the hover events only when the mouse
1050                         // is not captured.
1051                         if (this.hover_selection == false || this.Capture)
1052                                 return;
1053
1054                         // hit test for the items
1055                         Point hit = this.PointToClient (Control.MousePosition);
1056                         ListViewItem item = this.GetItemAt (hit.X, hit.Y);
1057
1058                         if (item != null) {
1059                                 item.Selected = true;
1060                                 // Raise the event
1061                                 this.OnSelectedIndexChanged (new EventArgs ());
1062
1063                                 this.Redraw (false);
1064                         }
1065                 }
1066
1067                 private void ListView_MouseMove (object sender, MouseEventArgs me)
1068                 {
1069                         // Column header is always at the top. It can
1070                         // scroll only horizontally. So, we have to take
1071                         // only horizontal scrolling into account
1072                         Point hit = new Point (me.X + h_marker, me.Y);
1073
1074                         // non-null clicked_col means mouse down has happened
1075                         // on a column
1076                         if (this.clicked_column != null) {
1077                                 if (this.clicked_column.pressed == false &&
1078                                     this.clicked_column.Rect.Contains (hit)) {
1079                                         this.clicked_column.pressed = true;
1080                                         this.draw_headers = true;
1081                                         this.Redraw (false);
1082                                 }
1083                                 else if (this.clicked_column.pressed && 
1084                                          ! this.clicked_column.Rect.Contains (hit)) {
1085                                         this.clicked_column.pressed = false;
1086                                         this.draw_headers = true;
1087                                         this.Redraw (false);
1088                                 }
1089                         }
1090                 }
1091
1092                 private void ListView_MouseUp (object sender, MouseEventArgs me)
1093                 {
1094                         this.Capture = false;
1095                         if (items.Count == 0)
1096                                 return;
1097
1098                         Point hit = new Point (me.X, me.Y);
1099
1100                         if (this.clicked_column != null) {
1101                                 if (this.clicked_column.pressed) {
1102                                         this.clicked_column.pressed = false;
1103                                         this.draw_headers = true;
1104                                         this.Redraw (false);
1105
1106                                         // Raise the ColumnClick event
1107                                         this.OnColumnClick (new ColumnClickEventArgs
1108                                                             (this.clicked_column.Index));
1109                                 }
1110                         }
1111
1112                         // Raise the ItemActivate event
1113                         Rectangle rect = Rectangle.Empty;
1114                         if (this.clicked_item != null) {
1115                                 if (this.view == View.Details && !this.full_row_select)
1116                                         rect = this.clicked_item.LabelRect;
1117                                 else
1118                                         rect = this.clicked_item.EntireRect;
1119
1120                                 // We handle double click in a separate handler
1121                                 if (this.activation != ItemActivation.Standard &&
1122                                     rect.Contains (hit)) {
1123                                         if (this.activation == ItemActivation.OneClick)
1124                                                 this.ItemActivate (this, EventArgs.Empty);
1125
1126                                         // ItemActivate is raised on the second click on the same item
1127                                         else if (this.activation == ItemActivation.TwoClick) {
1128                                                 if (this.last_clicked_item == this.clicked_item) {
1129                                                         this.ItemActivate (this, EventArgs.Empty);
1130                                                         this.last_clicked_item = null;
1131                                                 }
1132                                                 else
1133                                                         this.last_clicked_item = this.clicked_item;
1134                                         }
1135                                 }
1136                         }
1137
1138                         this.clicked_column = null;
1139                         this.clicked_item = null;
1140                 }
1141
1142                 private void ListView_Paint (object sender, PaintEventArgs pe)
1143                 {
1144                         if (this.Width <= 0 || this.Height <=  0 ||
1145                             this.Visible == false || this.updating == true)
1146                                 return;
1147
1148                         if (redraw) {
1149                                 ThemeEngine.Current.DrawListView (this.DeviceContext,
1150                                                                   pe.ClipRectangle, this);
1151                                 redraw = false;
1152                         }
1153
1154                         // We paint on the screen as per the location set
1155                         // by the two scrollbars. In case of details view
1156                         // since column headers can scroll only horizontally
1157                         // and items can scroll in both directions, paiting is
1158                         // done separtely for the column header and the items.
1159
1160                         Rectangle srcRect = this.ClientRectangle;
1161                         Rectangle dstRect = this.ClientRectangle;
1162
1163                         // set the visible starting point
1164                         if (scrollable) {
1165                                 srcRect.X += h_marker;
1166                                 srcRect.Y += v_marker;
1167
1168                                 if (h_scroll.Visible) {
1169                                         srcRect.Height -= h_scroll.Height;
1170                                         dstRect.Height -= h_scroll.Height;
1171                                 }
1172
1173                                 if (v_scroll.Visible) {
1174                                         srcRect.Width -= v_scroll.Width;
1175                                         dstRect.Width -= v_scroll.Width;
1176                                 }
1177                         }
1178
1179                         // We paint the column headers always at the top, in case
1180                         // of vertical scrolling. Therefore, we advance the painting
1181                         // by the amount equal to the column height.
1182                         if (this.view == View.Details &&
1183                             this.Columns.Count > 0 &&
1184                             this.header_style != ColumnHeaderStyle.None &&
1185                             v_marker > 0) {
1186
1187                                 int col_ht = this.Columns [0].Ht;
1188
1189                                 if (this.draw_headers) {
1190                                         this.draw_headers = false;
1191                                         // Move the source rect by the amount of horizontal
1192                                         // scrolling done so far.
1193                                         Rectangle headerSrc = new Rectangle (h_marker, 0,
1194                                                                              srcRect.Width, col_ht);
1195                                         // dest rect is always stable at 0,0
1196                                         Rectangle headerDst = new Rectangle (0, 0, srcRect.Width, col_ht);
1197                                         pe.Graphics.DrawImage (this.ImageBuffer, headerDst,
1198                                                                headerSrc, GraphicsUnit.Pixel);
1199                                 }
1200
1201                                 dstRect.Y += col_ht;
1202                                 srcRect.Y += col_ht;
1203                         }
1204
1205                         // Paint the items
1206                         pe.Graphics.DrawImage (this.ImageBuffer, dstRect,
1207                                                srcRect, GraphicsUnit.Pixel);
1208
1209                         // Draw the border of the list view
1210                         // The border is painted here separately, because
1211                         // our imagebuffer might be scrollable
1212                         ThemeEngine.Current.CPDrawBorderStyle (pe.Graphics,
1213                                                                this.ClientRectangle,
1214                                                                this.BorderStyle);
1215
1216                         // Raise the Paint event
1217                         if (Paint != null)
1218                                 Paint (this, pe);
1219                 }
1220
1221                 private void HorizontalScroller (object sender, EventArgs e)
1222                 {
1223                         // Avoid unnecessary flickering, when button is
1224                         // kept pressed at the end
1225                         if (h_marker != h_scroll.Value) {
1226                                 h_marker = h_scroll.Value;
1227                                 // draw the headers again
1228                                 this.draw_headers = true;
1229                                 this.Refresh ();
1230                         }
1231                 }
1232
1233                 private void VerticalScroller (object sender, EventArgs e)
1234                 {
1235                         // Avoid unnecessary flickering, when button is
1236                         // kept pressed at the end
1237                         if (v_marker != v_scroll.Value) {
1238                                 v_marker = v_scroll.Value;
1239                                 this.Refresh ();
1240                         }
1241                 }
1242                 #endregion      // Internal Methods Properties
1243
1244                 #region Protected Methods
1245                 protected override void CreateHandle ()
1246                 {
1247                         base.CreateHandle ();
1248                 }
1249
1250                 protected override void Dispose (bool disposing)
1251                 {
1252                         // FIXME: TODO
1253                 }
1254
1255                 protected override bool IsInputKey (Keys keyData)
1256                 {
1257                         return base.IsInputKey (keyData);
1258                 }
1259
1260                 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1261                 {
1262                         if (AfterLabelEdit != null)
1263                                 AfterLabelEdit (this, e);
1264                 }
1265
1266                 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1267                 {
1268                         if (BeforeLabelEdit != null)
1269                                 BeforeLabelEdit (this, e);
1270                 }
1271
1272                 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1273                 {
1274                         if (ColumnClick != null)
1275                                 ColumnClick (this, e);
1276                 }
1277
1278                 protected override void OnEnabledChanged (EventArgs e)
1279                 {
1280                         base.OnEnabledChanged (e);
1281                 }
1282
1283                 protected override void OnFontChanged (EventArgs e)
1284                 {
1285                         base.OnFontChanged (e);
1286                 }
1287
1288                 protected override void OnHandleCreated (EventArgs e)
1289                 {
1290                         base.OnHandleCreated (e);
1291                         this.Controls.Add (this.v_scroll);
1292                         this.Controls.Add (this.h_scroll);
1293                         this.SetStyle (ControlStyles.UserPaint |
1294                                        ControlStyles.AllPaintingInWmPaint, true);
1295                 }
1296
1297                 protected override void OnHandleDestroyed (EventArgs e)
1298                 {
1299                         base.OnHandleDestroyed (e);
1300                 }
1301
1302                 protected virtual void OnItemActivate (EventArgs e)
1303                 {
1304                         if (ItemActivate != null)
1305                                 ItemActivate (this, e);
1306                 }
1307
1308                 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1309                 {
1310                         if (ItemCheck != null)
1311                                 ItemCheck (this, ice);
1312                 }
1313
1314                 protected virtual void OnItemDrag (ItemDragEventArgs e)
1315                 {
1316                         if (ItemDrag != null)
1317                                 ItemDrag (this, e);
1318                 }
1319
1320                 protected virtual void OnSelectedIndexChanged (EventArgs e)
1321                 {
1322                         if (SelectedIndexChanged != null)
1323                                 SelectedIndexChanged (this, e);
1324                 }
1325
1326                 protected override void OnSystemColorsChanged (EventArgs e)
1327                 {
1328                         base.OnSystemColorsChanged (e);
1329                 }
1330
1331                 protected void RealizeProperties ()
1332                 {
1333                         // FIXME: TODO
1334                 }
1335
1336                 protected void UpdateExtendedStyles ()
1337                 {
1338                         // FIXME: TODO
1339                 }
1340
1341                 protected override void WndProc (ref Message m)
1342                 {
1343                         base.WndProc (ref m);
1344                 }
1345                 #endregion // Protected Methods
1346
1347                 #region Public Instance Methods
1348                 public void ArrangeIcons ()
1349                 {
1350                         ArrangeIcons (this.alignment);
1351                 }
1352
1353                 public void ArrangeIcons (ListViewAlignment alignment)
1354                 {
1355                         // Icons are arranged only if view is set to LargeIcon or SmallIcon
1356                         if (view == View.LargeIcon || view == View.SmallIcon) {
1357                                 this.CalculateListView (alignment);
1358                                 // we have done the calculations already
1359                                 this.Redraw (false);
1360                         }
1361                 }
1362
1363                 public void BeginUpdate ()
1364                 {
1365                         // flag to avoid painting
1366                         updating = true;
1367                 }
1368
1369                 public void Clear ()
1370                 {
1371                         columns.Clear ();
1372                         items.Clear ();
1373                         this.Redraw (true);
1374                 }
1375
1376                 public void EndUpdate ()
1377                 {
1378                         // flag to avoid painting
1379                         updating = false;
1380
1381                         // probably, now we need a redraw with recalculations
1382                         this.Redraw (true);
1383                 }
1384
1385                 public void EnsureVisible (int index)
1386                 {
1387                         if (index < 0 || index >= this.items.Count || this.scrollable == false)
1388                                 return;
1389
1390                         // dimensions of visible area
1391                         int view_wd = this.Width - (this.v_scroll.Visible ? this.v_scroll.Width : 0);
1392                         int view_ht = this.Height - (this.h_scroll.Visible ? this.h_scroll.Height : 0);
1393                         // visible area is decided by the h_marker and v_marker
1394                         Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1395
1396                         // an item's bounding rect
1397                         Rectangle rect = this.items [index].EntireRect;
1398
1399                         // we don't need to do anything if item is visible.
1400                         // visible area is represented by (0,0,view_wd,view_ht)
1401                         if (view_rect.Contains (rect))
1402                                 return;
1403
1404                         // Scroll Left or Up
1405                         if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1406                                 if (rect.Left < view_rect.Left)
1407                                         this.h_scroll.Value -= (view_rect.Left - rect.Left);
1408                                 if (rect.Top < view_rect.Top)
1409                                         this.v_scroll.Value -= (view_rect.Top - rect.Top);
1410                         }
1411                         // Scroll Right or Down
1412                         else {
1413                                 if (rect.Right > view_rect.Right)
1414                                         this.h_scroll.Value += (rect.Right - view_rect.Right);
1415                                 if (rect.Bottom > view_rect.Bottom)
1416                                         this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1417                         }
1418                 }
1419                 
1420                 public ListViewItem GetItemAt (int x, int y)
1421                 {
1422                         foreach (ListViewItem item in items) {
1423                                 if (item.Bounds.Contains (x, y))
1424                                         return item;
1425                         }
1426                         return null;
1427                 }
1428
1429                 public Rectangle GetItemRect (int index)
1430                 {
1431                         return GetItemRect (index, ItemBoundsPortion.Entire);
1432                 }
1433
1434                 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1435                 {
1436                         if (index < 0 || index >= items.Count)
1437                                 throw new IndexOutOfRangeException ("Invalid Index");
1438
1439                         return items [index].GetBounds (portion);
1440                 }
1441
1442                 public void Sort ()
1443                 {
1444                         if (sort_order != SortOrder.None)
1445                                 items.list.Sort (item_sorter);
1446
1447                         if (sort_order == SortOrder.Descending)
1448                                 items.list.Reverse ();
1449
1450                         this.Redraw (true);
1451                 }
1452
1453                 public override string ToString ()
1454                 {
1455                         int count = this.Items.Count;
1456
1457                         if (count == 0)
1458                                 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1459                         else
1460                                 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1461                 }
1462                 #endregion      // Public Instance Methods
1463
1464
1465                 #region Subclasses
1466                 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1467                 {
1468                         internal ArrayList list;
1469                         private ListView owner;
1470
1471                         #region Public Constructor
1472                         public CheckedIndexCollection (ListView owner)
1473                         {
1474                                 list = new ArrayList ();
1475                                 this.owner = owner;
1476                         }
1477                         #endregion      // Public Constructor
1478
1479                         #region Public Properties
1480                         [Browsable (false)]
1481                         public virtual int Count {
1482                                 get { return list.Count; }
1483                         }
1484
1485                         public virtual bool IsReadOnly {
1486                                 get { return true; }
1487                         }
1488
1489                         public int this [int index] {
1490                                 get {
1491                                         if (index < 0 || index >= list.Count)
1492                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1493                                         return (int) list [index];
1494                                 }
1495                         }
1496
1497                         bool ICollection.IsSynchronized {
1498                                 get { return list.IsSynchronized; }
1499                         }
1500
1501                         object ICollection.SyncRoot {
1502                                 get { return list.SyncRoot; }
1503                         }
1504
1505                         bool IList.IsFixedSize {
1506                                 get { return list.IsFixedSize; }
1507                         }
1508
1509                         object IList.this [int index] {
1510                                 get { return this [index]; }
1511                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1512                         }
1513                         #endregion      // Public Properties
1514
1515                         #region Public Methods
1516                         public bool Contains (int checkedIndex)
1517                         {
1518                                 return list.Contains (checkedIndex);
1519                         }
1520
1521                         public virtual IEnumerator GetEnumerator ()
1522                         {
1523                                 return list.GetEnumerator ();
1524                         }
1525
1526                         void ICollection.CopyTo (Array dest, int index)
1527                         {
1528                                 list.CopyTo (dest, index);
1529                         }
1530
1531                         int IList.Add (object value)
1532                         {
1533                                 throw new NotSupportedException ("Add operation is not supported.");
1534                         }
1535
1536                         void IList.Clear ()
1537                         {
1538                                 throw new NotSupportedException ("Clear operation is not supported.");
1539                         }
1540
1541                         bool IList.Contains (object checkedIndex)
1542                         {
1543                                 return list.Contains (checkedIndex);
1544                         }
1545
1546                         int IList.IndexOf (object checkedIndex)
1547                         {
1548                                 return list.IndexOf (checkedIndex);
1549                         }
1550
1551                         void IList.Insert (int index, object value)
1552                         {
1553                                 throw new NotSupportedException ("Insert operation is not supported.");
1554                         }
1555
1556                         void IList.Remove (object value)
1557                         {
1558                                 throw new NotSupportedException ("Remove operation is not supported.");
1559                         }
1560
1561                         void IList.RemoveAt (int index)
1562                         {
1563                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
1564                         }
1565
1566                         public int IndexOf (int checkedIndex)
1567                         {
1568                                 return list.IndexOf (checkedIndex);
1569                         }
1570                         #endregion      // Public Methods
1571
1572                 }       // CheckedIndexCollection
1573
1574                 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1575                 {
1576                         internal ArrayList list;
1577                         private ListView owner;
1578
1579                         #region Public Constructor
1580                         public CheckedListViewItemCollection (ListView owner)
1581                         {
1582                                 list = new ArrayList ();
1583                                 this.owner = owner;
1584                         }
1585                         #endregion      // Public Constructor
1586
1587                         #region Public Properties
1588                         [Browsable (false)]
1589                         public virtual int Count {
1590                                 get { return list.Count; }
1591                         }
1592
1593                         public virtual bool IsReadOnly {
1594                                 get { return true; }
1595                         }
1596
1597                         public ListViewItem this [int index] {
1598                                 get {
1599                                         if (index < 0 || index >= list.Count)
1600                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1601                                         return (ListViewItem) list [index];
1602                                 }
1603                         }
1604
1605                         bool ICollection.IsSynchronized {
1606                                 get { return list.IsSynchronized; }
1607                         }
1608
1609                         object ICollection.SyncRoot {
1610                                 get { return list.SyncRoot; }
1611                         }
1612
1613                         bool IList.IsFixedSize {
1614                                 get { return list.IsFixedSize; }
1615                         }
1616
1617                         object IList.this [int index] {
1618                                 get { return this [index]; }
1619                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1620                         }
1621                         #endregion      // Public Properties
1622
1623                         #region Public Methods
1624                         public bool Contains (ListViewItem item)
1625                         {
1626                                 return list.Contains (item);
1627                         }
1628
1629                         public virtual void CopyTo (Array dest, int index)
1630                         {
1631                                 list.CopyTo (dest, index);
1632                         }
1633
1634                         public virtual IEnumerator GetEnumerator ()
1635                         {
1636                                 return list.GetEnumerator ();
1637                         }
1638
1639                         int IList.Add (object value)
1640                         {
1641                                 throw new NotSupportedException ("Add operation is not supported.");
1642                         }
1643
1644                         void IList.Clear ()
1645                         {
1646                                 throw new NotSupportedException ("Clear operation is not supported.");
1647                         }
1648
1649                         bool IList.Contains (object item)
1650                         {
1651                                 return list.Contains (item);
1652                         }
1653
1654                         int IList.IndexOf (object item)
1655                         {
1656                                 return list.IndexOf (item);
1657                         }
1658
1659                         void IList.Insert (int index, object value)
1660                         {
1661                                 throw new NotSupportedException ("Insert operation is not supported.");
1662                         }
1663
1664                         void IList.Remove (object value)
1665                         {
1666                                 throw new NotSupportedException ("Remove operation is not supported.");
1667                         }
1668
1669                         void IList.RemoveAt (int index)
1670                         {
1671                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
1672                         }
1673
1674                         public int IndexOf (ListViewItem item)
1675                         {
1676                                 return list.IndexOf (item);
1677                         }
1678                         #endregion      // Public Methods
1679
1680                 }       // CheckedListViewItemCollection
1681
1682                 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1683                 {
1684                         internal ArrayList list;
1685                         private ListView owner;
1686
1687                         #region Public Constructor
1688                         public ColumnHeaderCollection (ListView owner)
1689                         {
1690                                 list = new ArrayList ();
1691                                 this.owner = owner;
1692                         }
1693                         #endregion      // Public Constructor
1694
1695                         #region Public Properties
1696                         [Browsable (false)]
1697                         public virtual int Count {
1698                                 get { return list.Count; }
1699                         }
1700
1701                         public virtual bool IsReadOnly {
1702                                 get { return false; }
1703                         }
1704
1705                         public virtual ColumnHeader this [int index] {
1706                                 get {
1707                                         if (index < 0 || index >= list.Count)
1708                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1709                                         return (ColumnHeader) list [index];
1710                                 }
1711                         }
1712
1713                         bool ICollection.IsSynchronized {
1714                                 get { return list.IsSynchronized; }
1715                         }
1716
1717                         object ICollection.SyncRoot {
1718                                 get { return list.SyncRoot; }
1719                         }
1720
1721                         bool IList.IsFixedSize {
1722                                 get { return list.IsFixedSize; }
1723                         }
1724
1725                         object IList.this [int index] {
1726                                 get { return this [index]; }
1727                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1728                         }
1729                         #endregion      // Public Properties
1730
1731                         #region Public Methods
1732                         public virtual int Add (ColumnHeader value)
1733                         {
1734                                 value.owner = this.owner;
1735                                 return list.Add (value);
1736                         }
1737
1738                         public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1739                         {
1740                                 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1741                                 this.Add (colHeader);
1742
1743                                 return colHeader;
1744                         }
1745
1746                         public virtual void AddRange (ColumnHeader [] values)
1747                         {
1748                                 foreach (ColumnHeader colHeader in values)
1749                                         this.Add (colHeader);
1750                         }
1751
1752                         public virtual void Clear ()
1753                         {
1754                                 list.Clear ();
1755                         }
1756
1757                         public bool Contains (ColumnHeader value)
1758                         {
1759                                 return list.Contains (value);
1760                         }
1761
1762                         public virtual IEnumerator GetEnumerator ()
1763                         {
1764                                 return list.GetEnumerator ();
1765                         }
1766
1767                         void ICollection.CopyTo (Array dest, int index)
1768                         {
1769                                 list.CopyTo (dest, index);
1770                         }
1771
1772                         int IList.Add (object value)
1773                         {
1774                                 if (! (value is ColumnHeader)) {
1775                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1776                                 }
1777
1778                                 return this.Add ((ColumnHeader) value);
1779                         }
1780
1781                         bool IList.Contains (object value)
1782                         {
1783                                 if (! (value is ColumnHeader)) {
1784                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1785                                 }
1786
1787                                 return this.Contains ((ColumnHeader) value);
1788                         }
1789
1790                         int IList.IndexOf (object value)
1791                         {
1792                                 if (! (value is ColumnHeader)) {
1793                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1794                                 }
1795
1796                                 return this.IndexOf ((ColumnHeader) value);
1797                         }
1798
1799                         void IList.Insert (int index, object value)
1800                         {
1801                                 if (! (value is ColumnHeader)) {
1802                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1803                                 }
1804
1805                                 this.Insert (index, (ColumnHeader) value);
1806                         }
1807
1808                         void IList.Remove (object value)
1809                         {
1810                                 if (! (value is ColumnHeader)) {
1811                                         throw new ArgumentException ("Not of type ColumnHeader", "value");
1812                                 }
1813
1814                                 this.Remove ((ColumnHeader) value);
1815                         }
1816
1817                         public int IndexOf (ColumnHeader value)
1818                         {
1819                                 return list.IndexOf (value);
1820                         }
1821
1822                         public void Insert (int index, ColumnHeader value)
1823                         {
1824                                 if (index < 0 || index >= list.Count)
1825                                         throw new ArgumentOutOfRangeException ("Index out of range.");
1826
1827                                 value.owner = this.owner;
1828                                 list.Insert (index, value);
1829                         }
1830
1831                         public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1832                         {
1833                                 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1834                                 this.Insert (index, colHeader);
1835                         }
1836
1837                         public virtual void Remove (ColumnHeader column)
1838                         {
1839                                 list.Remove (column);
1840                         }
1841
1842                         public virtual void RemoveAt (int index)
1843                         {
1844                                 if (index < 0 || index >= list.Count)
1845                                         throw new ArgumentOutOfRangeException ("Index out of range.");
1846
1847                                 list.RemoveAt (index);
1848                         }
1849                         #endregion      // Public Methods
1850
1851                 }       // ColumnHeaderCollection
1852
1853                 public class ListViewItemCollection : IList, ICollection, IEnumerable
1854                 {
1855                         internal ArrayList list;
1856                         private ListView owner;
1857
1858                         #region Public Constructor
1859                         public ListViewItemCollection (ListView owner)
1860                         {
1861                                 list = new ArrayList ();
1862                                 this.owner = owner;
1863                         }
1864                         #endregion      // Public Constructor
1865
1866                         #region Public Properties
1867                         [Browsable (false)]
1868                         public virtual int Count {
1869                                 get { return list.Count; }
1870                         }
1871
1872                         public virtual bool IsReadOnly {
1873                                 get { return false; }
1874                         }
1875
1876                         public virtual ListViewItem this [int displayIndex] {
1877                                 get {
1878                                         if (displayIndex < 0 || displayIndex >= list.Count)
1879                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1880                                         return (ListViewItem) list [displayIndex];
1881                                 }
1882
1883                                 set {
1884                                         if (displayIndex < 0 || displayIndex >= list.Count)
1885                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
1886
1887                                         if (list.Contains (value))
1888                                                 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1889
1890                                         value.owner = this.owner;
1891                                         list [displayIndex] = value;
1892
1893                                         owner.Redraw (true);
1894                                 }
1895                         }
1896
1897                         bool ICollection.IsSynchronized {
1898                                 get { return list.IsSynchronized; }
1899                         }
1900
1901                         object ICollection.SyncRoot {
1902                                 get { return list.SyncRoot; }
1903                         }
1904
1905                         bool IList.IsFixedSize {
1906                                 get { return list.IsFixedSize; }
1907                         }
1908
1909                         object IList.this [int index] {
1910                                 get { return this [index]; }
1911                                 set {
1912                                         if (value is ListViewItem)
1913                                                 this [index] = (ListViewItem) value;
1914                                         else
1915                                                 this [index] = new ListViewItem (value.ToString ());
1916                                 }
1917                         }
1918                         #endregion      // Public Properties
1919
1920                         #region Public Methods
1921                         public virtual ListViewItem Add (ListViewItem value)
1922                         {
1923                                 if (list.Contains (value))
1924                                         throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1925
1926                                 value.owner = this.owner;
1927                                 list.Add (value);
1928
1929                                 if (owner.Sorting != SortOrder.None)
1930                                         owner.Sort ();
1931
1932                                 owner.Redraw (true);
1933
1934                                 return value;
1935                         }
1936
1937                         public virtual ListViewItem Add (string text)
1938                         {
1939                                 ListViewItem item = new ListViewItem (text);
1940                                 return this.Add (item);
1941                         }
1942
1943                         public virtual ListViewItem Add (string text, int imageIndex)
1944                         {
1945                                 ListViewItem item = new ListViewItem (text, imageIndex);
1946                                 return this.Add (item);
1947                         }
1948
1949                         public void AddRange (ListViewItem [] values)
1950                         {
1951                                 list.Clear ();
1952
1953                                 foreach (ListViewItem item in values) {
1954                                         item.owner = this.owner;
1955                                         list.Add (item);
1956                                 }
1957
1958                                 if (owner.Sorting != SortOrder.None)
1959                                         owner.Sort ();
1960
1961                                 owner.Redraw (true);
1962                         }
1963
1964                         public virtual void Clear ()
1965                         {
1966                                 list.Clear ();
1967                         }
1968
1969                         public bool Contains (ListViewItem item)
1970                         {
1971                                 return list.Contains (item);
1972                         }
1973
1974                         public virtual void CopyTo (Array dest, int index)
1975                         {
1976                                 list.CopyTo (dest, index);
1977                         }
1978
1979                         public virtual IEnumerator GetEnumerator ()
1980                         {
1981                                 return list.GetEnumerator ();
1982                         }
1983
1984                         int IList.Add (object item)
1985                         {
1986                                 int result;
1987                                 ListViewItem li;
1988
1989                                 if (item is ListViewItem) {
1990                                         li = (ListViewItem) item;
1991                                         if (list.Contains (li))
1992                                                 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
1993                                 }
1994                                 else
1995                                         li = new ListViewItem (item.ToString ());
1996
1997                                 li.owner = this.owner;
1998                                 result = list.Add (li);
1999                                 owner.Redraw (true);
2000
2001                                 return result;
2002                         }
2003
2004                         bool IList.Contains (object item)
2005                         {
2006                                 return list.Contains (item);
2007                         }
2008
2009                         int IList.IndexOf (object item)
2010                         {
2011                                 return list.IndexOf (item);
2012                         }
2013
2014                         void IList.Insert (int index, object item)
2015                         {
2016                                 if (item is ListViewItem)
2017                                         this.Insert (index, (ListViewItem) item);
2018                                 else
2019                                         this.Insert (index, item.ToString ());
2020                         }
2021
2022                         void IList.Remove (object item)
2023                         {
2024                                 if (list.Contains (item)) {
2025                                         list.Remove (item);
2026                                         owner.Redraw (true);
2027                                 }
2028                         }
2029
2030                         public int IndexOf (ListViewItem item)
2031                         {
2032                                 return list.IndexOf (item);
2033                         }
2034
2035                         public ListViewItem Insert (int index, ListViewItem item)
2036                         {
2037                                 if (index < 0 || index >= list.Count)
2038                                         throw new ArgumentOutOfRangeException ("Index out of range.");
2039
2040                                 if (list.Contains (item))
2041                                         throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2042
2043                                 item.owner = this.owner;
2044                                 list.Insert (index, item);
2045                                 owner.Redraw (true);
2046                                 return item;
2047                         }
2048
2049                         public ListViewItem Insert (int index, string text)
2050                         {
2051                                 return this.Insert (index, new ListViewItem (text));
2052                         }
2053
2054                         public ListViewItem Insert (int index, string text, int imageIndex)
2055                         {
2056                                 return this.Insert (index, new ListViewItem (text, imageIndex));
2057                         }
2058
2059                         public virtual void Remove (ListViewItem item)
2060                         {
2061                                 if (list.Contains (item)) {
2062                                         list.Remove (item);
2063                                         owner.Redraw (true);
2064                                 }
2065                         }
2066
2067                         public virtual void RemoveAt (int index)
2068                         {
2069                                 if (index < 0 || index >= list.Count)
2070                                         throw new ArgumentOutOfRangeException ("Index out of range.");
2071
2072                                 list.RemoveAt (index);
2073                                 owner.Redraw (false);
2074                         }
2075                         #endregion      // Public Methods
2076
2077                 }       // ListViewItemCollection
2078
2079                 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2080                 {
2081                         internal ArrayList list;
2082                         private ListView owner;
2083
2084                         #region Public Constructor
2085                         public SelectedIndexCollection (ListView owner)
2086                         {
2087                                 list = new ArrayList ();
2088                                 this.owner = owner;
2089                         }
2090                         #endregion      // Public Constructor
2091
2092                         #region Public Properties
2093                         [Browsable (false)]
2094                         public virtual int Count {
2095                                 get { return list.Count; }
2096                         }
2097
2098                         public virtual bool IsReadOnly {
2099                                 get { return true; }
2100                         }
2101
2102                         public int this [int index] {
2103                                 get {
2104                                         if (index < 0 || index >= list.Count)
2105                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
2106                                         return (int) list [index];
2107                                 }
2108                         }
2109
2110                         bool ICollection.IsSynchronized {
2111                                 get { return list.IsSynchronized; }
2112                         }
2113
2114                         object ICollection.SyncRoot {
2115                                 get { return list.SyncRoot; }
2116                         }
2117
2118                         bool IList.IsFixedSize {
2119                                 get { return list.IsFixedSize; }
2120                         }
2121
2122                         object IList.this [int index] {
2123                                 get { return this [index]; }
2124                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2125                         }
2126                         #endregion      // Public Properties
2127
2128                         #region Public Methods
2129                         public bool Contains (int selectedIndex)
2130                         {
2131                                 return list.Contains (selectedIndex);
2132                         }
2133
2134                         public virtual void CopyTo (Array dest, int index)
2135                         {
2136                                 list.CopyTo (dest, index);
2137                         }
2138
2139                         public virtual IEnumerator GetEnumerator ()
2140                         {
2141                                 return list.GetEnumerator ();
2142                         }
2143
2144                         int IList.Add (object value)
2145                         {
2146                                 throw new NotSupportedException ("Add operation is not supported.");
2147                         }
2148
2149                         void IList.Clear ()
2150                         {
2151                                 throw new NotSupportedException ("Clear operation is not supported.");
2152                         }
2153
2154                         bool IList.Contains (object selectedIndex)
2155                         {
2156                                 return list.Contains (selectedIndex);
2157                         }
2158
2159                         int IList.IndexOf (object selectedIndex)
2160                         {
2161                                 return list.IndexOf (selectedIndex);
2162                         }
2163
2164                         void IList.Insert (int index, object value)
2165                         {
2166                                 throw new NotSupportedException ("Insert operation is not supported.");
2167                         }
2168
2169                         void IList.Remove (object value)
2170                         {
2171                                 throw new NotSupportedException ("Remove operation is not supported.");
2172                         }
2173
2174                         void IList.RemoveAt (int index)
2175                         {
2176                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
2177                         }
2178
2179                         public int IndexOf (int selectedIndex)
2180                         {
2181                                 return list.IndexOf (selectedIndex);
2182                         }
2183                         #endregion      // Public Methods
2184
2185                 }       // SelectedIndexCollection
2186
2187                 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2188                 {
2189                         internal ArrayList list;
2190                         private ListView owner;
2191
2192                         #region Public Constructor
2193                         public SelectedListViewItemCollection (ListView owner)
2194                         {
2195                                 list = new ArrayList ();
2196                                 this.owner = owner;
2197                         }
2198                         #endregion      // Public Constructor
2199
2200                         #region Public Properties
2201                         [Browsable (false)]
2202                         public virtual int Count {
2203                                 get { return list.Count; }
2204                         }
2205
2206                         public virtual bool IsReadOnly {
2207                                 get { return true; }
2208                         }
2209
2210                         public ListViewItem this [int index] {
2211                                 get {
2212                                         if (index < 0 || index >= list.Count)
2213                                                 throw new ArgumentOutOfRangeException ("Index out of range.");
2214                                         return (ListViewItem) list [index];
2215                                 }
2216                         }
2217
2218                         bool ICollection.IsSynchronized {
2219                                 get { return list.IsSynchronized; }
2220                         }
2221
2222                         object ICollection.SyncRoot {
2223                                 get { return list.SyncRoot; }
2224                         }
2225
2226                         bool IList.IsFixedSize {
2227                                 get { return list.IsFixedSize; }
2228                         }
2229
2230                         object IList.this [int index] {
2231                                 get { return this [index]; }
2232                                 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2233                         }
2234                         #endregion      // Public Properties
2235
2236                         #region Public Methods
2237                         public virtual void Clear ()
2238                         {
2239                                 // mark the items as unselected before clearing the list
2240                                 for (int i = 0; i < list.Count; i++)
2241                                         ((ListViewItem) list [i]).selected = false;
2242
2243                                 list.Clear ();
2244                         }
2245
2246                         public bool Contains (ListViewItem item)
2247                         {
2248                                 return list.Contains (item);
2249                         }
2250
2251                         public virtual void CopyTo (Array dest, int index)
2252                         {
2253                                 list.CopyTo (dest, index);
2254                         }
2255
2256                         public virtual IEnumerator GetEnumerator ()
2257                         {
2258                                 return list.GetEnumerator ();
2259                         }
2260
2261                         int IList.Add (object value)
2262                         {
2263                                 throw new NotSupportedException ("Add operation is not supported.");
2264                         }
2265
2266                         bool IList.Contains (object item)
2267                         {
2268                                 return list.Contains (item);
2269                         }
2270
2271                         int IList.IndexOf (object item)
2272                         {
2273                                 return list.IndexOf (item);
2274                         }
2275
2276                         void IList.Insert (int index, object value)
2277                         {
2278                                 throw new NotSupportedException ("Insert operation is not supported.");
2279                         }
2280
2281                         void IList.Remove (object value)
2282                         {
2283                                 throw new NotSupportedException ("Remove operation is not supported.");
2284                         }
2285
2286                         void IList.RemoveAt (int index)
2287                         {
2288                                 throw new NotSupportedException ("RemoveAt operation is not supported.");
2289                         }
2290
2291                         public int IndexOf (ListViewItem item)
2292                         {
2293                                 return list.IndexOf (item);
2294                         }
2295                         #endregion      // Public Methods
2296
2297                 }       // SelectedListViewItemCollection
2298
2299                 #endregion // Subclasses
2300         }
2301 }