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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2004 Novell, Inc. (http://www.novell.com)
23 // Ravindra (rkumar@novell.com)
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.
34 // $Log: ListView.cs,v $
35 // Revision 1.9 2004/11/05 14:00:50 ravindra
36 // Implemented some methods and fixed scrolling.
38 // Revision 1.8 2004/11/04 11:29:38 ravindra
39 // - Changed default value signatures (prefixed all with ListView).
40 // - Fixed/implemented layout LargeIcon, SmallIcon and List views for ListView.
41 // - Fixed calculations for ListViewItem and implemented Clone() method.
43 // Revision 1.7 2004/10/30 10:21:14 ravindra
44 // Added support for scrolling and fixed calculations.
46 // Revision 1.6 2004/10/26 19:51:20 jordi
49 // Revision 1.5 2004/10/26 09:55:48 ravindra
50 // Some formatting for my last checkins.
52 // Revision 1.4 2004/10/26 09:31:35 ravindra
53 // Added some internal members and calculations for ListView.
55 // Revision 1.3 2004/10/15 15:03:39 ravindra
56 // Implemented Paint method and fixed coding style.
58 // Revision 1.2 2004/10/02 11:32:01 ravindra
61 // Revision 1.1 2004/09/30 13:24:25 ravindra
62 // Initial implementation.
68 using System.Collections;
69 using System.ComponentModel;
70 using System.ComponentModel.Design;
72 using System.Runtime.InteropServices;
74 namespace System.Windows.Forms
76 [DefaultEvent ("SelectedIndexChanged")]
77 [DefaultProperty ("Items")]
78 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design,
80 public class ListView : Control
82 private ItemActivation activation = ItemActivation.Standard;
83 private ListViewAlignment alignment = ListViewAlignment.Top;
84 private bool allow_column_reorder = false;
85 private bool auto_arrange = true;
86 private BorderStyle border_style = BorderStyle.Fixed3D;
87 private bool check_boxes = false;
88 private CheckedIndexCollection checked_indices;
89 private CheckedListViewItemCollection checked_items;
90 private ColumnHeader clicked_column;
91 private ListViewItem clicked_item;
92 private ListViewItem last_clicked_item;
93 private ColumnHeaderCollection columns;
94 private bool ctrl_pressed;
95 private bool shift_pressed;
96 private bool draw_headers = true; // Used for painting. Do we need to draw column headers ?
97 private ListViewItem focused_item;
98 private bool full_row_select = false;
99 private bool grid_lines = false;
100 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
101 private bool hide_selection = true;
102 private bool hover_selection = false;
103 private IComparer item_sorter;
104 private ListViewItemCollection items;
105 private bool label_edit = false;
106 private bool label_wrap = true;
107 private bool multiselect = true;
108 private bool redraw = true;
109 private bool scrollable = true;
110 private SelectedIndexCollection selected_indices;
111 private SelectedListViewItemCollection selected_items;
112 private SortOrder sort_order = SortOrder.None;
113 private ImageList state_image_list;
114 private bool updating = false;
115 private View view = View.LargeIcon;
116 private int layout_wd; // We might draw more than our client area
117 private int layout_ht; // therefore we need to have these two.
118 //private TextBox editor; // Used for editing an item text
119 private ScrollBar h_scroll; // used for scrolling horizontally
120 private ScrollBar v_scroll; // used for scrolling vertically
121 private int h_marker; // Position markers for scrolling
122 private int v_marker;
124 // internal variables
125 internal ImageList large_image_list;
126 internal ImageList small_image_list;
127 internal Size text_size = Size.Empty;
130 public event LabelEditEventHandler AfterLabelEdit;
133 [EditorBrowsable (EditorBrowsableState.Never)]
134 public new event EventHandler BackgroundImageChanged;
136 public event LabelEditEventHandler BeforeLabelEdit;
137 public event ColumnClickEventHandler ColumnClick;
138 public event EventHandler ItemActivate;
139 public event ItemCheckEventHandler ItemCheck;
140 public event ItemDragEventHandler ItemDrag;
143 [EditorBrowsable (EditorBrowsableState.Never)]
144 public new event PaintEventHandler Paint;
146 public event EventHandler SelectedIndexChanged;
149 [EditorBrowsable (EditorBrowsableState.Never)]
150 public new event EventHandler TextChanged;
153 #region Public Constructors
156 background_color = ThemeEngine.Current.ColorWindow;
157 checked_indices = new CheckedIndexCollection (this);
158 checked_items = new CheckedListViewItemCollection (this);
159 columns = new ColumnHeaderCollection (this);
160 foreground_color = SystemColors.WindowText;
161 items = new ListViewItemCollection (this);
162 selected_indices = new SelectedIndexCollection (this);
163 selected_items = new SelectedListViewItemCollection (this);
165 // we are mostly scrollable
166 h_scroll = new HScrollBar ();
167 v_scroll = new VScrollBar ();
168 h_marker = v_marker = 0;
170 // scroll bars are disabled initially
171 h_scroll.Visible = false;
172 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
173 v_scroll.Visible = false;
174 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
177 base.DoubleClick += new EventHandler(ListView_DoubleClick);
178 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
179 base.KeyUp += new KeyEventHandler(ListView_KeyUp);
180 base.MouseDown += new MouseEventHandler(ListView_MouseDown);
181 base.MouseHover += new EventHandler(ListView_MouseHover);
182 base.MouseUp += new MouseEventHandler(ListView_MouseUp);
183 base.MouseMove += new MouseEventHandler(ListView_MouseMove);
184 base.Paint += new PaintEventHandler (ListView_Paint);
186 #endregion // Public Constructors
188 #region Private Internal Properties
189 internal Size CheckBoxSize {
191 if (this.check_boxes) {
192 if (this.state_image_list != null)
193 return this.state_image_list.ImageSize;
195 return ThemeEngine.Current.ListViewCheckBoxSize;
201 internal bool CanMultiselect {
203 if (this.multiselect &&
204 (this.ctrl_pressed || this.shift_pressed))
210 #endregion // Private Internal Properties
212 #region Protected Properties
213 protected override CreateParams CreateParams {
214 get { return base.CreateParams; }
217 protected override Size DefaultSize {
218 get { return ThemeEngine.Current.ListViewDefaultSize; }
220 #endregion // Protected Properties
222 #region Public Instance Properties
223 [DefaultValue (ItemActivation.Standard)]
224 public ItemActivation Activation {
225 get { return activation; }
226 set { activation = value; }
229 [DefaultValue (ListViewAlignment.Top)]
231 public ListViewAlignment Alignment {
232 get { return alignment; }
234 if (this.alignment != value) {
236 // alignment does not matter in Details/List views
237 if (this.view == View.LargeIcon ||
238 this.View == View.SmallIcon)
244 [DefaultValue (false)]
245 public bool AllowColumnReorder {
246 get { return allow_column_reorder; }
248 if (this.allow_column_reorder != value) {
249 allow_column_reorder = value;
250 // column reorder does not matter in Details view
251 if (this.view != View.Details)
257 [DefaultValue (true)]
258 public bool AutoArrange {
259 get { return auto_arrange; }
261 if (auto_arrange != value) {
262 auto_arrange = value;
263 // autoarrange does not matter in Details/List views
264 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
270 public override Color BackColor {
272 if (background_color.IsEmpty)
273 return ThemeEngine.Current.ColorWindow;
275 return background_color;
277 set { background_color = value; }
281 [EditorBrowsable (EditorBrowsableState.Never)]
282 public override Image BackgroundImage {
283 get { return background_image; }
285 if (value == background_image)
288 background_image = value;
289 if (BackgroundImageChanged != null)
290 BackgroundImageChanged (this, new EventArgs ());
294 [DefaultValue (BorderStyle.Fixed3D)]
296 public BorderStyle BorderStyle {
297 get { return border_style; }
299 if (border_style != value) {
300 border_style = value;
306 [DefaultValue (false)]
307 public bool CheckBoxes {
308 get { return check_boxes; }
310 if (check_boxes != value) {
318 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
319 public CheckedIndexCollection CheckedIndices {
320 get { return checked_indices; }
324 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
325 public CheckedListViewItemCollection CheckedItems {
326 get { return checked_items; }
329 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
331 [MergableProperty (false)]
332 public ColumnHeaderCollection Columns {
333 get { return columns; }
337 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
338 public ListViewItem FocusedItem {
339 get { return focused_item; }
342 public override Color ForeColor {
344 if (foreground_color.IsEmpty)
345 return ThemeEngine.Current.ColorWindowText;
347 return foreground_color;
349 set { foreground_color = value; }
352 [DefaultValue (false)]
353 public bool FullRowSelect {
354 get { return full_row_select; }
355 set { full_row_select = value; }
358 [DefaultValue (false)]
359 public bool GridLines {
360 get { return grid_lines; }
362 if (grid_lines != value) {
369 [DefaultValue (ColumnHeaderStyle.Clickable)]
370 public ColumnHeaderStyle HeaderStyle {
371 get { return header_style; }
373 if (header_style != value) {
374 header_style = value;
375 // header style matters only in Details view
376 if (this.view == View.Details)
382 [DefaultValue (true)]
383 public bool HideSelection {
384 get { return hide_selection; }
386 if (hide_selection != value) {
387 hide_selection = value;
393 [DefaultValue (false)]
394 public bool HoverSelection {
395 get { return hover_selection; }
396 set { hover_selection = value; }
399 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
401 [MergableProperty (false)]
402 public ListViewItemCollection Items {
403 get { return items; }
406 [DefaultValue (false)]
407 public bool LabelEdit {
408 get { return label_edit; }
409 set { label_edit = value; }
412 [DefaultValue (false)]
414 public bool LabelWrap {
415 get { return label_wrap; }
417 if (label_wrap != value) {
424 [DefaultValue (null)]
425 public ImageList LargeImageList {
426 get { return large_image_list; }
428 large_image_list = value;
434 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
435 public IComparer ListViewItemSorter {
436 get { return item_sorter; }
437 set { item_sorter = value; }
440 [DefaultValue (true)]
441 public bool MultiSelect {
442 get { return multiselect; }
443 set { multiselect = value; }
446 [DefaultValue (true)]
447 public bool Scrollable {
448 get { return scrollable; }
450 if (scrollable != value) {
458 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
459 public SelectedIndexCollection SelectedIndices {
460 get { return selected_indices; }
464 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
465 public SelectedListViewItemCollection SelectedItems {
466 get { return selected_items; }
469 [DefaultValue (null)]
470 public ImageList SmallImageList {
471 get { return small_image_list; }
473 small_image_list = value;
478 [DefaultValue (SortOrder.None)]
479 public SortOrder Sorting {
480 get { return sort_order; }
481 set { sort_order = value; }
484 [DefaultValue (null)]
485 public ImageList StateImageList {
486 get { return state_image_list; }
488 state_image_list = value;
495 [EditorBrowsable (EditorBrowsableState.Never)]
496 public override string Text {
505 if (TextChanged != null)
506 TextChanged (this, new EventArgs ());
511 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
512 public ListViewItem TopItem {
515 if (this.items.Count == 0)
517 // if contents are not scrolled
518 // it is the first item
519 else if (h_marker == 0 && v_marker == 0)
520 return this.items [0];
521 // do a hit test for the scrolled position
523 foreach (ListViewItem item in this.items) {
524 if (item.EntireRect.Contains (h_marker, v_marker))
532 [DefaultValue (View.LargeIcon)]
535 set { view = value; }
537 #endregion // Public Instance Properties
539 #region Internal Methods Properties
540 internal int TotalWidth {
541 get { return Math.Max (this.Width, this.layout_wd); }
544 internal int TotalHeight {
545 get { return Math.Max (this.Height, this.layout_ht); }
548 internal void Redraw (bool recalculate)
550 // Avoid calculations when control is being updated
555 CalculateListView (this.alignment);
561 internal Size GetChildColumnSize (int index)
563 Size ret_size = Size.Empty;
564 ColumnHeader col = this.columns [index];
566 if (col.Width == -2) { // autosize = max(items, columnheader)
567 Size size = Size.Ceiling (this.DeviceContext.MeasureString
568 (col.Text, this.Font));
569 ret_size = BiggestItem (index);
570 if (size.Width > ret_size.Width)
573 else { // -1 and all the values < -2 are put under one category
574 ret_size = BiggestItem (index);
575 // fall back to empty columns' width if no subitem is available for a column
576 if (ret_size.IsEmpty) {
577 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
578 if (col.Text.Length > 0)
579 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
580 (col.Text, this.Font)).Height;
582 ret_size.Height = this.Font.Height;
586 // adjust the size for icon and checkbox for 0th column
588 ret_size.Width += (this.CheckBoxSize.Width + 4);
589 if (this.small_image_list != null)
590 ret_size.Width += this.small_image_list.ImageSize.Width;
595 // Returns the size of biggest item text in a column.
596 private Size BiggestItem (int col)
598 Size temp = Size.Empty;
599 Size ret_size = Size.Empty;
601 // 0th column holds the item text, we check the size of
602 // the various subitems falling in that column and get
603 // the biggest one's size.
604 foreach (ListViewItem item in items) {
605 if (col >= item.SubItems.Count)
608 temp = Size.Ceiling (this.DeviceContext.MeasureString
609 (item.SubItems [col].Text, this.Font));
610 if (temp.Width > ret_size.Width)
614 // adjustment for space
615 if (!ret_size.IsEmpty)
621 // Sets the size of the biggest item text as per the view
622 private void CalcTextSize ()
624 // clear the old value
625 text_size = Size.Empty;
627 if (items.Count == 0)
630 text_size = BiggestItem (0);
632 if (view == View.LargeIcon && this.label_wrap) {
633 Size temp = Size.Empty;
634 if (this.check_boxes)
635 temp.Width += 2 * this.CheckBoxSize.Width;
636 if (large_image_list != null)
637 temp.Width += large_image_list.ImageSize.Width;
640 // wrapping is done for two lines only
641 if (text_size.Width > temp.Width) {
642 text_size.Width = temp.Width;
643 text_size.Height *= 2;
646 else if (view == View.List) {
647 // in list view max text shown in determined by the
648 // control width, even if scolling is enabled.
649 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
650 if (this.small_image_list != null)
651 max_wd -= this.small_image_list.ImageSize.Width;
653 if (text_size.Width > max_wd)
654 text_size.Width = max_wd;
657 // we do the default settings, if we have got 0's
658 if (text_size.Height <= 0)
659 text_size.Height = this.Font.Height;
660 if (text_size.Width <= 0)
661 text_size.Width = this.Width;
664 text_size.Width += 4;
665 text_size.Height += 2;
668 // Sets the location of every item on
669 // the ListView as per the view
670 private void CalculateListView (ListViewAlignment align)
672 int current_pos_x = 0; // our x-position marker
673 int current_pos_y = 0; // our y-position marker
676 int max; // max x_pos or y_pos depending on the alignment
677 int current = 0; // current row or column
678 int vertical_spacing = ThemeEngine.Current.ListViewVerticalSpacing;
679 int horizontal_spacing = ThemeEngine.Current.ListViewHorizontalSpacing;
686 // ColumnHeaders are not drawn if headerstyle is none
687 int ht = (this.header_style == ColumnHeaderStyle.None) ?
688 2 : this.Font.Height + 2;
689 if (columns.Count > 0) {
690 foreach (ColumnHeader col in columns) {
691 col.X = current_pos_x;
693 col.CalcColumnHeader ();
694 current_pos_x += col.Wd;
696 this.layout_wd = current_pos_x;
698 // set the position marker for placing items
702 if (items.Count > 0) {
703 foreach (ListViewItem item in items) {
705 item.location.Y = current_pos_y;
706 item.CalcListViewItem ();
707 current_pos_y += item.EntireRect.Height;
709 this.layout_ht = current_pos_y;
711 // some space for bottom gridline
718 vertical_spacing = 0;
719 horizontal_spacing = 0;
720 goto case View.LargeIcon;
723 if (items.Count > 0) {
724 items [0].CalcListViewItem ();
725 item_ht = items [0].EntireRect.Height;
726 item_wd = items [0].EntireRect.Width;
728 // top (default) and snaptogrid alignments are handled same way
729 if (align == ListViewAlignment.Left) {
731 foreach (ListViewItem item in items) {
732 item.location.X = current_pos_x +
734 item.location.Y = current_pos_y;
735 item.CalcListViewItem ();
736 current_pos_y += item_ht;
738 current ++; // just to know about the last element
739 // we just did the last item
740 if (current == items.Count) {
741 if (max < current_pos_y)
743 current_pos_x = item.EntireRect.Right;
747 // is there enough space for another row ?
748 if ((current_pos_y + vertical_spacing
749 + item_ht) <= this.Height)
750 current_pos_y += vertical_spacing;
752 // start another column
753 // make current_pos_y as the
754 // max value and reset
755 // current_pos_y value.
757 current_pos_x += item_wd;
762 // adjust the layout dimensions
763 this.layout_ht = max;
764 this.layout_wd = current_pos_x;
766 else { // other default/top alignment
768 foreach (ListViewItem item in items) {
769 item.location.X = current_pos_x +
772 item.location.Y = current_pos_y;
773 item.CalcListViewItem ();
774 current_pos_x += item_wd;
776 current ++; // just to know about the last element
777 // we just did the last item
778 if (current == items.Count) {
779 if (max < current_pos_x)
781 current_pos_y = item.EntireRect.Bottom;
785 // is there enough space for another column?
786 if ((current_pos_x + horizontal_spacing
787 + item_wd) <= this.Width)
791 // make current_pos_x as the
792 // max value and reset
793 // current_pos_x value.
795 current_pos_y += (item_ht +
801 // adjust the layout dimensions
802 this.layout_wd = max;
803 this.layout_ht = current_pos_y;
809 if (items.Count > 0) {
810 items [0].CalcListViewItem ();
811 item_ht = items [0].EntireRect.Height;
812 item_wd = items [0].EntireRect.Width;
814 max = this.Height / item_ht;
816 max = 1; // we draw at least one row
818 foreach (ListViewItem item in items) {
819 item.location.X = current_pos_x;
820 item.location.Y = current_pos_y;
821 item.CalcListViewItem ();
823 if (current == max) {
824 current_pos_x += item_wd;
829 current_pos_y += item_ht;
832 // adjust the layout dimensions
833 this.layout_ht = max * item_ht;
834 if (current == 0) // we have fully filled layout
835 this.layout_wd = current_pos_x;
837 this.layout_wd = current_pos_x + item_wd;
842 if (this.scrollable && this.items.Count > 0) {
843 // making a scroll bar visible might make
844 // other scroll bar visible
845 if (this.layout_wd > this.Width) {
846 this.h_scroll.Visible = true;
847 if ((this.layout_ht + this.h_scroll.Height) > this.Height)
848 this.v_scroll.Visible = true;
850 else if (this.layout_ht > this.Height) {
851 this.v_scroll.Visible = true;
852 if ((this.layout_wd + this.v_scroll.Width) > this.Width)
853 this.h_scroll.Visible = true;
856 // create big enough buffers
857 if (this.layout_wd > this.Width ||
858 this.layout_ht > this.Height)
859 this.CreateBuffers (this.TotalWidth, this.TotalHeight);
861 if (this.h_scroll.Visible) {
862 this.h_scroll.Location = new Point (0, this.Height
863 - this.h_scroll.Height);
865 this.h_scroll.Minimum = 0;
867 // if v_scroll is visible, adjust the maximum of the
868 // h_scroll to account for the width of v_scroll
869 if (this.v_scroll.Visible) {
870 this.h_scroll.Maximum = this.layout_wd + this.v_scroll.Width;
871 this.h_scroll.Width = this.Width - this.v_scroll.Width;
874 this.h_scroll.Maximum = this.layout_wd;
875 this.h_scroll.Width = this.Width;
878 this.h_scroll.LargeChange = this.Width;
879 this.h_scroll.SmallChange = this.Font.Height;
882 // vertical scrollbar
883 if (this.v_scroll.Visible) {
884 this.v_scroll.Location = new Point (this.Width
885 - this.v_scroll.Width, 0);
887 this.v_scroll.Minimum = 0;
889 // if h_scroll is visible, adjust the maximum of the
890 // v_scroll to account for the height of h_scroll
891 if (this.h_scroll.Visible) {
892 this.v_scroll.Maximum = this.layout_ht + this.h_scroll.Height;
893 this.v_scroll.Height = this.Height - this.h_scroll.Height;
896 this.v_scroll.Maximum = this.layout_ht;
897 this.v_scroll.Height = this.Height;
900 this.v_scroll.LargeChange = this.Height;
901 this.v_scroll.SmallChange = this.Font.Height;
905 this.h_scroll.Visible = false;
906 this.v_scroll.Visible = false;
911 private void ListView_DoubleClick (object sender, EventArgs e)
913 if (this.activation == ItemActivation.Standard
914 && this.ItemActivate != null)
915 this.ItemActivate (this, e);
918 private void ListView_KeyDown (object sender, KeyEventArgs ke)
926 switch (ke.KeyCode) {
928 case Keys.ControlKey:
929 this.ctrl_pressed = true;
937 this.v_scroll.Value = this.v_scroll.Maximum;
941 this.v_scroll.Value = this.v_scroll.Minimum;
946 if (this.last_clicked_item != null)
947 index = this.last_clicked_item.Index;
954 this.last_clicked_item = this.items [index];
955 this.last_clicked_item.Selected = true;
956 this.EnsureVisible (index);
960 if (this.last_clicked_item != null)
961 index = this.last_clicked_item.Index + 1;
965 if (index == this.items.Count)
968 this.last_clicked_item = this.items [index];
969 this.last_clicked_item.Selected = true;
970 this.EnsureVisible (index);
974 this.shift_pressed = true;
987 private void ListView_KeyUp (object sender, KeyEventArgs ke)
990 if (ke.KeyCode == Keys.ControlKey)
991 this.ctrl_pressed = false;
993 if (ke.KeyCode == Keys.ShiftKey)
994 this.shift_pressed = false;
999 private void ListView_MouseDown (object sender, MouseEventArgs me)
1001 if (items.Count == 0)
1004 Point hit = Point.Empty;
1005 if (this.HeaderStyle != ColumnHeaderStyle.None) {
1006 // take horizontal scrolling into account
1007 hit = new Point (me.X + h_marker, me.Y);
1009 // hit test on columns
1010 if (this.view == View.Details && this.columns.Count > 0) {
1011 foreach (ColumnHeader col in this.columns) {
1012 if (col.Rect.Contains (hit)) {
1013 this.clicked_column = col;
1014 this.Capture = true;
1019 if (this.clicked_column != null) {
1020 this.clicked_column.pressed = true;
1021 this.draw_headers = true;
1022 this.Redraw (false);
1028 // hit test on items
1029 // we need to take scrolling into account
1030 hit = new Point (me.X + h_marker, me.Y + v_marker);
1031 foreach (ListViewItem item in this.items) {
1032 if (item.CheckRect.Contains (hit)) {
1033 CheckState curr_state = item.Checked ?
1034 CheckState.Checked : CheckState.Unchecked;
1036 item.Checked = false;
1038 item.Checked = true;
1040 CheckState new_state = item.Checked ?
1041 CheckState.Checked : CheckState.Unchecked;
1042 this.Redraw (false);
1044 // Raise the ItemCheck event
1045 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index,
1048 this.OnItemCheck (ice);
1052 if (this.view == View.Details &&
1053 this.FullRowSelect == false) {
1054 if (item.LabelRect.Contains (hit)) {
1055 this.clicked_item = item;
1060 if (item.EntireRect.Contains (hit)) {
1061 this.clicked_item = item;
1067 if (this.clicked_item != null) {
1068 this.clicked_item.Selected = true;
1070 this.OnSelectedIndexChanged (new EventArgs ());
1072 this.Redraw (false);
1075 // set the FocusedItem to be the current clicked_item
1076 this.focused_item = this.clicked_item;
1079 private void ListView_MouseHover (object sender, EventArgs e)
1081 // handle the hover events only when the mouse
1083 if (this.hover_selection == false || this.Capture)
1086 // hit test for the items
1087 Point hit = this.PointToClient (Control.MousePosition);
1088 ListViewItem item = this.GetItemAt (hit.X, hit.Y);
1091 item.Selected = true;
1093 this.OnSelectedIndexChanged (new EventArgs ());
1095 this.Redraw (false);
1099 private void ListView_MouseMove (object sender, MouseEventArgs me)
1101 // Column header is always at the top. It can
1102 // scroll only horizontally. So, we have to take
1103 // only horizontal scrolling into account
1104 Point hit = new Point (me.X + h_marker, me.Y);
1106 // non-null clicked_col means mouse down has happened
1108 if (this.clicked_column != null) {
1109 if (this.clicked_column.pressed == false &&
1110 this.clicked_column.Rect.Contains (hit)) {
1111 this.clicked_column.pressed = true;
1112 this.draw_headers = true;
1113 this.Redraw (false);
1115 else if (this.clicked_column.pressed &&
1116 ! this.clicked_column.Rect.Contains (hit)) {
1117 this.clicked_column.pressed = false;
1118 this.draw_headers = true;
1119 this.Redraw (false);
1124 private void ListView_MouseUp (object sender, MouseEventArgs me)
1126 this.Capture = false;
1127 if (items.Count == 0)
1130 Point hit = new Point (me.X, me.Y);
1132 if (this.clicked_column != null) {
1133 if (this.clicked_column.pressed) {
1134 this.clicked_column.pressed = false;
1135 this.draw_headers = true;
1136 this.Redraw (false);
1138 // Raise the ColumnClick event
1139 this.OnColumnClick (new ColumnClickEventArgs
1140 (this.clicked_column.Index));
1144 // Raise the ItemActivate event
1145 Rectangle rect = Rectangle.Empty;
1146 if (this.clicked_item != null) {
1147 if (this.view == View.Details && !this.full_row_select)
1148 rect = this.clicked_item.LabelRect;
1150 rect = this.clicked_item.EntireRect;
1152 // We handle double click in a separate handler
1153 if (this.activation != ItemActivation.Standard &&
1154 rect.Contains (hit)) {
1155 if (this.activation == ItemActivation.OneClick)
1156 this.ItemActivate (this, EventArgs.Empty);
1158 // ItemActivate is raised on the second click on the same item
1159 else if (this.activation == ItemActivation.TwoClick) {
1160 if (this.last_clicked_item == this.clicked_item) {
1161 this.ItemActivate (this, EventArgs.Empty);
1162 this.last_clicked_item = null;
1165 this.last_clicked_item = this.clicked_item;
1170 this.clicked_column = null;
1171 this.clicked_item = null;
1174 private void ListView_Paint (object sender, PaintEventArgs pe)
1176 if (this.Width <= 0 || this.Height <= 0 ||
1177 this.Visible == false || this.updating == true)
1181 ThemeEngine.Current.DrawListView (this.DeviceContext,
1182 pe.ClipRectangle, this);
1186 // We paint on the screen as per the location set
1187 // by the two scrollbars. In case of details view
1188 // since column headers can scroll only horizontally
1189 // and items can scroll in both directions, paiting is
1190 // done separtely for the column header and the items.
1192 Rectangle srcRect = this.ClientRectangle;
1193 Rectangle dstRect = this.ClientRectangle;
1195 // set the visible starting point
1197 srcRect.X += h_marker;
1198 srcRect.Y += v_marker;
1200 if (h_scroll.Visible) {
1201 srcRect.Height -= h_scroll.Height;
1202 dstRect.Height -= h_scroll.Height;
1205 if (v_scroll.Visible) {
1206 srcRect.Width -= v_scroll.Width;
1207 dstRect.Width -= v_scroll.Width;
1211 // We paint the column headers always at the top, in case
1212 // of vertical scrolling. Therefore, we advance the painting
1213 // by the amount equal to the column height.
1214 if (this.view == View.Details &&
1215 this.Columns.Count > 0 &&
1216 this.header_style != ColumnHeaderStyle.None &&
1219 int col_ht = this.Columns [0].Ht;
1221 if (this.draw_headers) {
1222 this.draw_headers = false;
1223 // Move the source rect by the amount of horizontal
1224 // scrolling done so far.
1225 Rectangle headerSrc = new Rectangle (h_marker, 0,
1226 srcRect.Width, col_ht);
1227 // dest rect is always stable at 0,0
1228 Rectangle headerDst = new Rectangle (0, 0, srcRect.Width, col_ht);
1229 pe.Graphics.DrawImage (this.ImageBuffer, headerDst,
1230 headerSrc, GraphicsUnit.Pixel);
1233 dstRect.Y += col_ht;
1234 srcRect.Y += col_ht;
1238 pe.Graphics.DrawImage (this.ImageBuffer, dstRect,
1239 srcRect, GraphicsUnit.Pixel);
1241 // Draw the border of the list view
1242 // The border is painted here separately, because
1243 // our imagebuffer might be scrollable
1244 ThemeEngine.Current.CPDrawBorderStyle (pe.Graphics,
1245 this.ClientRectangle,
1248 // Raise the Paint event
1253 private void HorizontalScroller (object sender, EventArgs e)
1255 // Avoid unnecessary flickering, when button is
1256 // kept pressed at the end
1257 if (h_marker != h_scroll.Value) {
1258 h_marker = h_scroll.Value;
1259 // draw the headers again
1260 this.draw_headers = true;
1265 private void VerticalScroller (object sender, EventArgs e)
1267 // Avoid unnecessary flickering, when button is
1268 // kept pressed at the end
1269 if (v_marker != v_scroll.Value) {
1270 v_marker = v_scroll.Value;
1274 #endregion // Internal Methods Properties
1276 #region Protected Methods
1277 protected override void CreateHandle ()
1279 base.CreateHandle ();
1282 protected override void Dispose (bool disposing)
1287 protected override bool IsInputKey (Keys keyData)
1289 return base.IsInputKey (keyData);
1292 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1294 if (AfterLabelEdit != null)
1295 AfterLabelEdit (this, e);
1298 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1300 if (BeforeLabelEdit != null)
1301 BeforeLabelEdit (this, e);
1304 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1306 if (ColumnClick != null)
1307 ColumnClick (this, e);
1310 protected override void OnEnabledChanged (EventArgs e)
1312 base.OnEnabledChanged (e);
1315 protected override void OnFontChanged (EventArgs e)
1317 base.OnFontChanged (e);
1320 protected override void OnHandleCreated (EventArgs e)
1322 base.OnHandleCreated (e);
1323 this.Controls.Add (this.v_scroll);
1324 this.Controls.Add (this.h_scroll);
1325 this.SetStyle (ControlStyles.UserPaint |
1326 ControlStyles.AllPaintingInWmPaint, true);
1329 protected override void OnHandleDestroyed (EventArgs e)
1331 base.OnHandleDestroyed (e);
1334 protected virtual void OnItemActivate (EventArgs e)
1336 if (ItemActivate != null)
1337 ItemActivate (this, e);
1340 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1342 if (ItemCheck != null)
1343 ItemCheck (this, ice);
1346 protected virtual void OnItemDrag (ItemDragEventArgs e)
1348 if (ItemDrag != null)
1352 protected virtual void OnSelectedIndexChanged (EventArgs e)
1354 if (SelectedIndexChanged != null)
1355 SelectedIndexChanged (this, e);
1358 protected override void OnSystemColorsChanged (EventArgs e)
1360 base.OnSystemColorsChanged (e);
1363 protected void RealizeProperties ()
1368 protected void UpdateExtendedStyles ()
1373 protected override void WndProc (ref Message m)
1375 base.WndProc (ref m);
1377 #endregion // Protected Methods
1379 #region Public Instance Methods
1380 public void ArrangeIcons ()
1382 ArrangeIcons (this.alignment);
1385 public void ArrangeIcons (ListViewAlignment alignment)
1387 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1388 if (view == View.LargeIcon || view == View.SmallIcon) {
1389 this.CalculateListView (alignment);
1390 // we have done the calculations already
1391 this.Redraw (false);
1395 public void BeginUpdate ()
1397 // flag to avoid painting
1401 public void Clear ()
1408 public void EndUpdate ()
1410 // flag to avoid painting
1413 // probably, now we need a redraw with recalculations
1417 public void EnsureVisible (int index)
1419 if (index < 0 || index >= this.items.Count || this.scrollable == false)
1422 // dimensions of visible area
1423 int view_wd = this.Width - (this.v_scroll.Visible ? this.v_scroll.Width : 0);
1424 int view_ht = this.Height - (this.h_scroll.Visible ? this.h_scroll.Height : 0);
1425 // visible area is decided by the h_marker and v_marker
1426 Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1428 // an item's bounding rect
1429 Rectangle rect = this.items [index].EntireRect;
1431 // we don't need to do anything if item is visible.
1432 // visible area is represented by (0,0,view_wd,view_ht)
1433 if (view_rect.Contains (rect))
1436 // Scroll Left or Up
1437 if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1438 if (rect.Left < view_rect.Left)
1439 this.h_scroll.Value -= (view_rect.Left - rect.Left);
1440 if (rect.Top < view_rect.Top)
1441 this.v_scroll.Value -= (view_rect.Top - rect.Top);
1443 // Scroll Right or Down
1445 if (rect.Right > view_rect.Right)
1446 this.h_scroll.Value += (rect.Right - view_rect.Right);
1447 if (rect.Bottom > view_rect.Bottom)
1448 this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1452 public ListViewItem GetItemAt (int x, int y)
1454 foreach (ListViewItem item in items) {
1455 if (item.Bounds.Contains (x, y))
1461 public Rectangle GetItemRect (int index)
1463 return GetItemRect (index, ItemBoundsPortion.Entire);
1466 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1468 if (index < 0 || index >= items.Count)
1469 throw new IndexOutOfRangeException ("Invalid Index");
1471 return items [index].GetBounds (portion);
1476 if (sort_order != SortOrder.None)
1477 items.list.Sort (item_sorter);
1479 if (sort_order == SortOrder.Descending)
1480 items.list.Reverse ();
1485 public override string ToString ()
1487 int count = this.Items.Count;
1490 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1492 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1494 #endregion // Public Instance Methods
1498 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1500 internal ArrayList list;
1501 private ListView owner;
1503 #region Public Constructor
1504 public CheckedIndexCollection (ListView owner)
1506 list = new ArrayList ();
1509 #endregion // Public Constructor
1511 #region Public Properties
1513 public virtual int Count {
1514 get { return list.Count; }
1517 public virtual bool IsReadOnly {
1518 get { return true; }
1521 public int this [int index] {
1523 if (index < 0 || index >= list.Count)
1524 throw new ArgumentOutOfRangeException ("Index out of range.");
1525 return (int) list [index];
1529 bool ICollection.IsSynchronized {
1530 get { return list.IsSynchronized; }
1533 object ICollection.SyncRoot {
1534 get { return list.SyncRoot; }
1537 bool IList.IsFixedSize {
1538 get { return list.IsFixedSize; }
1541 object IList.this [int index] {
1542 get { return this [index]; }
1543 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1545 #endregion // Public Properties
1547 #region Public Methods
1548 public bool Contains (int checkedIndex)
1550 return list.Contains (checkedIndex);
1553 public virtual IEnumerator GetEnumerator ()
1555 return list.GetEnumerator ();
1558 void ICollection.CopyTo (Array dest, int index)
1560 list.CopyTo (dest, index);
1563 int IList.Add (object value)
1565 throw new NotSupportedException ("Add operation is not supported.");
1570 throw new NotSupportedException ("Clear operation is not supported.");
1573 bool IList.Contains (object checkedIndex)
1575 return list.Contains (checkedIndex);
1578 int IList.IndexOf (object checkedIndex)
1580 return list.IndexOf (checkedIndex);
1583 void IList.Insert (int index, object value)
1585 throw new NotSupportedException ("Insert operation is not supported.");
1588 void IList.Remove (object value)
1590 throw new NotSupportedException ("Remove operation is not supported.");
1593 void IList.RemoveAt (int index)
1595 throw new NotSupportedException ("RemoveAt operation is not supported.");
1598 public int IndexOf (int checkedIndex)
1600 return list.IndexOf (checkedIndex);
1602 #endregion // Public Methods
1604 } // CheckedIndexCollection
1606 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1608 internal ArrayList list;
1609 private ListView owner;
1611 #region Public Constructor
1612 public CheckedListViewItemCollection (ListView owner)
1614 list = new ArrayList ();
1617 #endregion // Public Constructor
1619 #region Public Properties
1621 public virtual int Count {
1622 get { return list.Count; }
1625 public virtual bool IsReadOnly {
1626 get { return true; }
1629 public ListViewItem this [int index] {
1631 if (index < 0 || index >= list.Count)
1632 throw new ArgumentOutOfRangeException ("Index out of range.");
1633 return (ListViewItem) list [index];
1637 bool ICollection.IsSynchronized {
1638 get { return list.IsSynchronized; }
1641 object ICollection.SyncRoot {
1642 get { return list.SyncRoot; }
1645 bool IList.IsFixedSize {
1646 get { return list.IsFixedSize; }
1649 object IList.this [int index] {
1650 get { return this [index]; }
1651 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1653 #endregion // Public Properties
1655 #region Public Methods
1656 public bool Contains (ListViewItem item)
1658 return list.Contains (item);
1661 public virtual void CopyTo (Array dest, int index)
1663 list.CopyTo (dest, index);
1666 public virtual IEnumerator GetEnumerator ()
1668 return list.GetEnumerator ();
1671 int IList.Add (object value)
1673 throw new NotSupportedException ("Add operation is not supported.");
1678 throw new NotSupportedException ("Clear operation is not supported.");
1681 bool IList.Contains (object item)
1683 return list.Contains (item);
1686 int IList.IndexOf (object item)
1688 return list.IndexOf (item);
1691 void IList.Insert (int index, object value)
1693 throw new NotSupportedException ("Insert operation is not supported.");
1696 void IList.Remove (object value)
1698 throw new NotSupportedException ("Remove operation is not supported.");
1701 void IList.RemoveAt (int index)
1703 throw new NotSupportedException ("RemoveAt operation is not supported.");
1706 public int IndexOf (ListViewItem item)
1708 return list.IndexOf (item);
1710 #endregion // Public Methods
1712 } // CheckedListViewItemCollection
1714 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1716 internal ArrayList list;
1717 private ListView owner;
1719 #region Public Constructor
1720 public ColumnHeaderCollection (ListView owner)
1722 list = new ArrayList ();
1725 #endregion // Public Constructor
1727 #region Public Properties
1729 public virtual int Count {
1730 get { return list.Count; }
1733 public virtual bool IsReadOnly {
1734 get { return false; }
1737 public virtual ColumnHeader this [int index] {
1739 if (index < 0 || index >= list.Count)
1740 throw new ArgumentOutOfRangeException ("Index out of range.");
1741 return (ColumnHeader) list [index];
1745 bool ICollection.IsSynchronized {
1746 get { return list.IsSynchronized; }
1749 object ICollection.SyncRoot {
1750 get { return list.SyncRoot; }
1753 bool IList.IsFixedSize {
1754 get { return list.IsFixedSize; }
1757 object IList.this [int index] {
1758 get { return this [index]; }
1759 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1761 #endregion // Public Properties
1763 #region Public Methods
1764 public virtual int Add (ColumnHeader value)
1766 return list.Add (value);
1769 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1771 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1772 this.Add (colHeader);
1777 public virtual void AddRange (ColumnHeader [] values)
1779 foreach (ColumnHeader colHeader in values)
1780 this.Add (colHeader);
1783 public virtual void Clear ()
1788 public bool Contains (ColumnHeader value)
1790 return list.Contains (value);
1793 public virtual IEnumerator GetEnumerator ()
1795 return list.GetEnumerator ();
1798 void ICollection.CopyTo (Array dest, int index)
1800 list.CopyTo (dest, index);
1803 int IList.Add (object value)
1805 if (! (value is ColumnHeader)) {
1806 throw new ArgumentException ("Not of type ColumnHeader", "value");
1809 return this.Add ((ColumnHeader) value);
1812 bool IList.Contains (object value)
1814 if (! (value is ColumnHeader)) {
1815 throw new ArgumentException ("Not of type ColumnHeader", "value");
1818 return this.Contains ((ColumnHeader) value);
1821 int IList.IndexOf (object value)
1823 if (! (value is ColumnHeader)) {
1824 throw new ArgumentException ("Not of type ColumnHeader", "value");
1827 return this.IndexOf ((ColumnHeader) value);
1830 void IList.Insert (int index, object value)
1832 if (! (value is ColumnHeader)) {
1833 throw new ArgumentException ("Not of type ColumnHeader", "value");
1836 this.Insert (index, (ColumnHeader) value);
1839 void IList.Remove (object value)
1841 if (! (value is ColumnHeader)) {
1842 throw new ArgumentException ("Not of type ColumnHeader", "value");
1845 this.Remove ((ColumnHeader) value);
1848 public int IndexOf (ColumnHeader value)
1850 return list.IndexOf (value);
1853 public void Insert (int index, ColumnHeader value)
1855 if (index < 0 || index >= list.Count)
1856 throw new ArgumentOutOfRangeException ("Index out of range.");
1858 list.Insert (index, value);
1861 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1863 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1864 this.Insert (index, colHeader);
1867 public virtual void Remove (ColumnHeader column)
1869 list.Remove (column);
1872 public virtual void RemoveAt (int index)
1874 if (index < 0 || index >= list.Count)
1875 throw new ArgumentOutOfRangeException ("Index out of range.");
1877 list.RemoveAt (index);
1879 #endregion // Public Methods
1881 } // ColumnHeaderCollection
1883 public class ListViewItemCollection : IList, ICollection, IEnumerable
1885 internal ArrayList list;
1886 private ListView owner;
1888 #region Public Constructor
1889 public ListViewItemCollection (ListView owner)
1891 list = new ArrayList ();
1894 #endregion // Public Constructor
1896 #region Public Properties
1898 public virtual int Count {
1899 get { return list.Count; }
1902 public virtual bool IsReadOnly {
1903 get { return false; }
1906 public virtual ListViewItem this [int displayIndex] {
1908 if (displayIndex < 0 || displayIndex >= list.Count)
1909 throw new ArgumentOutOfRangeException ("Index out of range.");
1910 return (ListViewItem) list [displayIndex];
1914 if (displayIndex < 0 || displayIndex >= list.Count)
1915 throw new ArgumentOutOfRangeException ("Index out of range.");
1917 if (list.Contains (value))
1918 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1920 value.owner = this.owner;
1921 list [displayIndex] = value;
1923 owner.Redraw (true);
1927 bool ICollection.IsSynchronized {
1928 get { return list.IsSynchronized; }
1931 object ICollection.SyncRoot {
1932 get { return list.SyncRoot; }
1935 bool IList.IsFixedSize {
1936 get { return list.IsFixedSize; }
1939 object IList.this [int index] {
1940 get { return this [index]; }
1942 if (value is ListViewItem)
1943 this [index] = (ListViewItem) value;
1945 this [index] = new ListViewItem (value.ToString ());
1948 #endregion // Public Properties
1950 #region Public Methods
1951 public virtual ListViewItem Add (ListViewItem value)
1953 if (list.Contains (value))
1954 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1956 value.owner = this.owner;
1959 if (owner.Sorting != SortOrder.None)
1962 owner.Redraw (true);
1967 public virtual ListViewItem Add (string text)
1969 ListViewItem item = new ListViewItem (text);
1970 return this.Add (item);
1973 public virtual ListViewItem Add (string text, int imageIndex)
1975 ListViewItem item = new ListViewItem (text, imageIndex);
1976 return this.Add (item);
1979 public void AddRange (ListViewItem [] values)
1983 foreach (ListViewItem item in values) {
1984 item.owner = this.owner;
1988 if (owner.Sorting != SortOrder.None)
1991 owner.Redraw (true);
1994 public virtual void Clear ()
1999 public bool Contains (ListViewItem item)
2001 return list.Contains (item);
2004 public virtual void CopyTo (Array dest, int index)
2006 list.CopyTo (dest, index);
2009 public virtual IEnumerator GetEnumerator ()
2011 return list.GetEnumerator ();
2014 int IList.Add (object item)
2019 if (item is ListViewItem) {
2020 li = (ListViewItem) item;
2021 if (list.Contains (li))
2022 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2025 li = new ListViewItem (item.ToString ());
2027 li.owner = this.owner;
2028 result = list.Add (li);
2029 owner.Redraw (true);
2034 bool IList.Contains (object item)
2036 return list.Contains (item);
2039 int IList.IndexOf (object item)
2041 return list.IndexOf (item);
2044 void IList.Insert (int index, object item)
2046 if (item is ListViewItem)
2047 this.Insert (index, (ListViewItem) item);
2049 this.Insert (index, item.ToString ());
2052 void IList.Remove (object item)
2054 if (list.Contains (item)) {
2056 owner.Redraw (true);
2060 public int IndexOf (ListViewItem item)
2062 return list.IndexOf (item);
2065 public ListViewItem Insert (int index, ListViewItem item)
2067 if (index < 0 || index >= list.Count)
2068 throw new ArgumentOutOfRangeException ("Index out of range.");
2070 if (list.Contains (item))
2071 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2073 item.owner = this.owner;
2074 list.Insert (index, item);
2075 owner.Redraw (true);
2079 public ListViewItem Insert (int index, string text)
2081 return this.Insert (index, new ListViewItem (text));
2084 public ListViewItem Insert (int index, string text, int imageIndex)
2086 return this.Insert (index, new ListViewItem (text, imageIndex));
2089 public virtual void Remove (ListViewItem item)
2091 if (list.Contains (item)) {
2093 owner.Redraw (true);
2097 public virtual void RemoveAt (int index)
2099 if (index < 0 || index >= list.Count)
2100 throw new ArgumentOutOfRangeException ("Index out of range.");
2102 list.RemoveAt (index);
2103 owner.Redraw (false);
2105 #endregion // Public Methods
2107 } // ListViewItemCollection
2109 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2111 internal ArrayList list;
2112 private ListView owner;
2114 #region Public Constructor
2115 public SelectedIndexCollection (ListView owner)
2117 list = new ArrayList ();
2120 #endregion // Public Constructor
2122 #region Public Properties
2124 public virtual int Count {
2125 get { return list.Count; }
2128 public virtual bool IsReadOnly {
2129 get { return true; }
2132 public int this [int index] {
2134 if (index < 0 || index >= list.Count)
2135 throw new ArgumentOutOfRangeException ("Index out of range.");
2136 return (int) list [index];
2140 bool ICollection.IsSynchronized {
2141 get { return list.IsSynchronized; }
2144 object ICollection.SyncRoot {
2145 get { return list.SyncRoot; }
2148 bool IList.IsFixedSize {
2149 get { return list.IsFixedSize; }
2152 object IList.this [int index] {
2153 get { return this [index]; }
2154 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2156 #endregion // Public Properties
2158 #region Public Methods
2159 public bool Contains (int selectedIndex)
2161 return list.Contains (selectedIndex);
2164 public virtual void CopyTo (Array dest, int index)
2166 list.CopyTo (dest, index);
2169 public virtual IEnumerator GetEnumerator ()
2171 return list.GetEnumerator ();
2174 int IList.Add (object value)
2176 throw new NotSupportedException ("Add operation is not supported.");
2181 throw new NotSupportedException ("Clear operation is not supported.");
2184 bool IList.Contains (object selectedIndex)
2186 return list.Contains (selectedIndex);
2189 int IList.IndexOf (object selectedIndex)
2191 return list.IndexOf (selectedIndex);
2194 void IList.Insert (int index, object value)
2196 throw new NotSupportedException ("Insert operation is not supported.");
2199 void IList.Remove (object value)
2201 throw new NotSupportedException ("Remove operation is not supported.");
2204 void IList.RemoveAt (int index)
2206 throw new NotSupportedException ("RemoveAt operation is not supported.");
2209 public int IndexOf (int selectedIndex)
2211 return list.IndexOf (selectedIndex);
2213 #endregion // Public Methods
2215 } // SelectedIndexCollection
2217 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2219 internal ArrayList list;
2220 private ListView owner;
2222 #region Public Constructor
2223 public SelectedListViewItemCollection (ListView owner)
2225 list = new ArrayList ();
2228 #endregion // Public Constructor
2230 #region Public Properties
2232 public virtual int Count {
2233 get { return list.Count; }
2236 public virtual bool IsReadOnly {
2237 get { return true; }
2240 public ListViewItem this [int index] {
2242 if (index < 0 || index >= list.Count)
2243 throw new ArgumentOutOfRangeException ("Index out of range.");
2244 return (ListViewItem) list [index];
2248 bool ICollection.IsSynchronized {
2249 get { return list.IsSynchronized; }
2252 object ICollection.SyncRoot {
2253 get { return list.SyncRoot; }
2256 bool IList.IsFixedSize {
2257 get { return list.IsFixedSize; }
2260 object IList.this [int index] {
2261 get { return this [index]; }
2262 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2264 #endregion // Public Properties
2266 #region Public Methods
2267 public virtual void Clear ()
2269 // mark the items as unselected before clearing the list
2270 for (int i = 0; i < list.Count; i++)
2271 ((ListViewItem) list [i]).selected = false;
2276 public bool Contains (ListViewItem item)
2278 return list.Contains (item);
2281 public virtual void CopyTo (Array dest, int index)
2283 list.CopyTo (dest, index);
2286 public virtual IEnumerator GetEnumerator ()
2288 return list.GetEnumerator ();
2291 int IList.Add (object value)
2293 throw new NotSupportedException ("Add operation is not supported.");
2296 bool IList.Contains (object item)
2298 return list.Contains (item);
2301 int IList.IndexOf (object item)
2303 return list.IndexOf (item);
2306 void IList.Insert (int index, object value)
2308 throw new NotSupportedException ("Insert operation is not supported.");
2311 void IList.Remove (object value)
2313 throw new NotSupportedException ("Remove operation is not supported.");
2316 void IList.RemoveAt (int index)
2318 throw new NotSupportedException ("RemoveAt operation is not supported.");
2321 public int IndexOf (ListViewItem item)
2323 return list.IndexOf (item);
2325 #endregion // Public Methods
2327 } // SelectedListViewItemCollection
2329 #endregion // Subclasses