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-2005 Novell, Inc. (http://www.novell.com)
23 // Ravindra Kumar (rkumar@novell.com)
24 // Jordi Mas i Hernandez, jordi@ximian.com
27 // - Keys to be handled ENTER/PAGE UP/PAGE DOWN/HOME/END/ARROWS/CTRL/SHIFT
28 // - Item text editing
29 // - Column resizing/reodering
30 // - Feedback for item activation, change in cursor types as mouse moves.
32 // - Focused item (broken and not drawn)
34 // - Manual column resizing
42 using System.Collections;
43 using System.ComponentModel;
44 using System.ComponentModel.Design;
46 using System.Runtime.InteropServices;
48 namespace System.Windows.Forms
50 [DefaultEvent ("SelectedIndexChanged")]
51 [DefaultProperty ("Items")]
52 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, (string)null)]
53 public class ListView : Control
55 private ItemActivation activation = ItemActivation.Standard;
56 private ListViewAlignment alignment = ListViewAlignment.Top;
57 private bool allow_column_reorder = false;
58 private bool auto_arrange = true;
59 private bool check_boxes = false;
60 private CheckedIndexCollection checked_indices;
61 private CheckedListViewItemCollection checked_items;
62 private ColumnHeader clicked_column;
63 private ListViewItem clicked_item;
64 private ListViewItem last_clicked_item;
65 private ColumnHeaderCollection columns;
66 private bool ctrl_pressed;
67 private bool shift_pressed;
68 private bool draw_headers = true; // Used for painting. Do we need to draw column headers ?
69 private ListViewItem focused_item;
70 private bool full_row_select = false;
71 private bool grid_lines = false;
72 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
73 private bool hide_selection = true;
74 private bool hover_selection = false;
75 private IComparer item_sorter;
76 private ListViewItemCollection items;
77 private bool label_edit = false;
78 private bool label_wrap = true;
79 private bool multiselect = true;
80 private bool redraw = true;
81 private bool scrollable = true;
82 private SelectedIndexCollection selected_indices;
83 private SelectedListViewItemCollection selected_items;
84 private SortOrder sort_order = SortOrder.None;
85 private ImageList state_image_list;
86 private bool updating = false;
87 private View view = View.LargeIcon;
88 private int layout_wd; // We might draw more than our client area
89 private int layout_ht; // therefore we need to have these two.
90 //private TextBox editor; // Used for editing an item text
91 private ScrollBar h_scroll; // used for scrolling horizontally
92 private ScrollBar v_scroll; // used for scrolling vertically
93 private int h_marker; // Position markers for scrolling
97 internal ImageList large_image_list;
98 internal ImageList small_image_list;
99 internal Size text_size = Size.Empty;
102 public event LabelEditEventHandler AfterLabelEdit;
105 [EditorBrowsable (EditorBrowsableState.Never)]
106 public new event EventHandler BackgroundImageChanged;
108 public event LabelEditEventHandler BeforeLabelEdit;
109 public event ColumnClickEventHandler ColumnClick;
110 public event EventHandler ItemActivate;
111 public event ItemCheckEventHandler ItemCheck;
112 public event ItemDragEventHandler ItemDrag;
115 [EditorBrowsable (EditorBrowsableState.Never)]
116 public new event PaintEventHandler Paint;
118 public event EventHandler SelectedIndexChanged;
121 [EditorBrowsable (EditorBrowsableState.Never)]
122 public new event EventHandler TextChanged;
125 #region Public Constructors
128 background_color = ThemeEngine.Current.ColorWindow;
129 checked_indices = new CheckedIndexCollection (this);
130 checked_items = new CheckedListViewItemCollection (this);
131 columns = new ColumnHeaderCollection (this);
132 foreground_color = SystemColors.WindowText;
133 items = new ListViewItemCollection (this);
134 selected_indices = new SelectedIndexCollection (this);
135 selected_items = new SelectedListViewItemCollection (this);
137 border_style = BorderStyle.Fixed3D;
139 // we are mostly scrollable
140 h_scroll = new HScrollBar ();
141 v_scroll = new VScrollBar ();
142 h_marker = v_marker = 0;
144 // scroll bars are disabled initially
145 h_scroll.Visible = false;
146 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
147 v_scroll.Visible = false;
148 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
151 base.DoubleClick += new EventHandler(ListView_DoubleClick);
152 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
153 base.KeyUp += new KeyEventHandler(ListView_KeyUp);
154 base.MouseDown += new MouseEventHandler(ListView_MouseDown);
155 base.MouseHover += new EventHandler(ListView_MouseHover);
156 base.MouseUp += new MouseEventHandler(ListView_MouseUp);
157 base.MouseMove += new MouseEventHandler(ListView_MouseMove);
158 base.Paint += new PaintEventHandler (ListView_Paint);
160 this.SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
162 #endregion // Public Constructors
164 #region Private Internal Properties
165 internal Size CheckBoxSize {
167 if (this.check_boxes) {
168 if (this.state_image_list != null)
169 return this.state_image_list.ImageSize;
171 return ThemeEngine.Current.ListViewCheckBoxSize;
177 internal bool CanMultiselect {
179 if (this.multiselect &&
180 (this.ctrl_pressed || this.shift_pressed))
186 #endregion // Private Internal Properties
188 #region Protected Properties
189 protected override CreateParams CreateParams {
190 get { return base.CreateParams; }
193 protected override Size DefaultSize {
194 get { return ThemeEngine.Current.ListViewDefaultSize; }
196 #endregion // Protected Properties
198 #region Public Instance Properties
199 [DefaultValue (ItemActivation.Standard)]
200 public ItemActivation Activation {
201 get { return activation; }
203 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
204 value != ItemActivation.TwoClick) {
205 throw new InvalidEnumArgumentException (string.Format
206 ("Enum argument value '{0}' is not valid for Activation", value));
213 [DefaultValue (ListViewAlignment.Top)]
215 public ListViewAlignment Alignment {
216 get { return alignment; }
218 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
219 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
220 throw new InvalidEnumArgumentException (string.Format
221 ("Enum argument value '{0}' is not valid for Alignment", value));
224 if (this.alignment != value) {
226 // alignment does not matter in Details/List views
227 if (this.view == View.LargeIcon ||
228 this.View == View.SmallIcon)
234 [DefaultValue (false)]
235 public bool AllowColumnReorder {
236 get { return allow_column_reorder; }
238 if (this.allow_column_reorder != value) {
239 allow_column_reorder = value;
240 // column reorder does not matter in Details view
241 if (this.view != View.Details)
247 [DefaultValue (true)]
248 public bool AutoArrange {
249 get { return auto_arrange; }
251 if (auto_arrange != value) {
252 auto_arrange = value;
253 // autoarrange does not matter in Details/List views
254 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
260 public override Color BackColor {
262 if (background_color.IsEmpty)
263 return ThemeEngine.Current.ColorWindow;
265 return background_color;
267 set { background_color = value; }
271 [EditorBrowsable (EditorBrowsableState.Never)]
272 public override Image BackgroundImage {
273 get { return background_image; }
275 if (value == background_image)
278 background_image = value;
279 if (BackgroundImageChanged != null)
280 BackgroundImageChanged (this, new EventArgs ());
284 [DefaultValue (BorderStyle.Fixed3D)]
286 public BorderStyle BorderStyle {
287 get { return border_style; }
289 if (value != BorderStyle.Fixed3D && value != BorderStyle.FixedSingle &&
290 value != BorderStyle.None) {
291 throw new InvalidEnumArgumentException (string.Format
292 ("Enum argument value '{0}' is not valid for BorderStyle", value));
295 if (border_style != value) {
296 border_style = value;
302 [DefaultValue (false)]
303 public bool CheckBoxes {
304 get { return check_boxes; }
306 if (check_boxes != value) {
314 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
315 public CheckedIndexCollection CheckedIndices {
316 get { return checked_indices; }
320 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
321 public CheckedListViewItemCollection CheckedItems {
322 get { return checked_items; }
325 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
327 [MergableProperty (false)]
328 public ColumnHeaderCollection Columns {
329 get { return columns; }
333 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
334 public ListViewItem FocusedItem {
335 get { return focused_item; }
338 public override Color ForeColor {
340 if (foreground_color.IsEmpty)
341 return ThemeEngine.Current.ColorWindowText;
343 return foreground_color;
345 set { foreground_color = value; }
348 [DefaultValue (false)]
349 public bool FullRowSelect {
350 get { return full_row_select; }
351 set { full_row_select = value; }
354 [DefaultValue (false)]
355 public bool GridLines {
356 get { return grid_lines; }
358 if (grid_lines != value) {
365 [DefaultValue (ColumnHeaderStyle.Clickable)]
366 public ColumnHeaderStyle HeaderStyle {
367 get { return header_style; }
369 if (value != ColumnHeaderStyle.Clickable && value != ColumnHeaderStyle.Nonclickable &&
370 value != ColumnHeaderStyle.None) {
371 throw new InvalidEnumArgumentException (string.Format
372 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
375 if (header_style != value) {
376 header_style = value;
377 // header style matters only in Details view
378 if (this.view == View.Details)
384 [DefaultValue (true)]
385 public bool HideSelection {
386 get { return hide_selection; }
388 if (hide_selection != value) {
389 hide_selection = value;
395 [DefaultValue (false)]
396 public bool HoverSelection {
397 get { return hover_selection; }
398 set { hover_selection = value; }
401 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
403 [MergableProperty (false)]
404 public ListViewItemCollection Items {
405 get { return items; }
408 [DefaultValue (false)]
409 public bool LabelEdit {
410 get { return label_edit; }
411 set { label_edit = value; }
414 [DefaultValue (true)]
416 public bool LabelWrap {
417 get { return label_wrap; }
419 if (label_wrap != value) {
426 [DefaultValue (null)]
427 public ImageList LargeImageList {
428 get { return large_image_list; }
430 large_image_list = value;
436 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
437 public IComparer ListViewItemSorter {
438 get { return item_sorter; }
439 set { item_sorter = value; }
442 [DefaultValue (true)]
443 public bool MultiSelect {
444 get { return multiselect; }
445 set { multiselect = value; }
448 [DefaultValue (true)]
449 public bool Scrollable {
450 get { return scrollable; }
452 if (scrollable != value) {
460 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
461 public SelectedIndexCollection SelectedIndices {
462 get { return selected_indices; }
466 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
467 public SelectedListViewItemCollection SelectedItems {
468 get { return selected_items; }
471 [DefaultValue (null)]
472 public ImageList SmallImageList {
473 get { return small_image_list; }
475 small_image_list = value;
480 [DefaultValue (SortOrder.None)]
481 public SortOrder Sorting {
482 get { return sort_order; }
484 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
485 value != SortOrder.None) {
486 throw new InvalidEnumArgumentException (string.Format
487 ("Enum argument value '{0}' is not valid for Sorting", value));
490 if (sort_order != value) {
497 [DefaultValue (null)]
498 public ImageList StateImageList {
499 get { return state_image_list; }
501 state_image_list = value;
508 [EditorBrowsable (EditorBrowsableState.Never)]
509 public override string Text {
518 if (TextChanged != null)
519 TextChanged (this, new EventArgs ());
524 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
525 public ListViewItem TopItem {
528 if (this.items.Count == 0)
530 // if contents are not scrolled
531 // it is the first item
532 else if (h_marker == 0 && v_marker == 0)
533 return this.items [0];
534 // do a hit test for the scrolled position
536 foreach (ListViewItem item in this.items) {
537 if (item.EntireRect.Contains (h_marker, v_marker))
545 [DefaultValue (View.LargeIcon)]
549 if (value != View.Details && value != View.LargeIcon &&
550 value != View.List && value != View.SmallIcon ) {
551 throw new InvalidEnumArgumentException (string.Format
552 ("Enum argument value '{0}' is not valid for View", value));
561 #endregion // Public Instance Properties
563 #region Internal Methods Properties
564 internal int TotalWidth {
565 get { return Math.Max (this.Width, this.layout_wd); }
568 internal int TotalHeight {
569 get { return Math.Max (this.Height, this.layout_ht); }
572 internal void Redraw (bool recalculate)
574 // Avoid calculations when control is being updated
579 CalculateListView (this.alignment);
585 internal Size GetChildColumnSize (int index)
587 Size ret_size = Size.Empty;
588 ColumnHeader col = this.columns [index];
590 if (col.Width == -2) { // autosize = max(items, columnheader)
591 Size size = Size.Ceiling (this.DeviceContext.MeasureString
592 (col.Text, this.Font));
593 ret_size = BiggestItem (index);
594 if (size.Width > ret_size.Width)
597 else { // -1 and all the values < -2 are put under one category
598 ret_size = BiggestItem (index);
599 // fall back to empty columns' width if no subitem is available for a column
600 if (ret_size.IsEmpty) {
601 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
602 if (col.Text.Length > 0)
603 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
604 (col.Text, this.Font)).Height;
606 ret_size.Height = this.Font.Height;
610 // adjust the size for icon and checkbox for 0th column
612 ret_size.Width += (this.CheckBoxSize.Width + 4);
613 if (this.small_image_list != null)
614 ret_size.Width += this.small_image_list.ImageSize.Width;
619 // Returns the size of biggest item text in a column.
620 private Size BiggestItem (int col)
622 Size temp = Size.Empty;
623 Size ret_size = Size.Empty;
625 // 0th column holds the item text, we check the size of
626 // the various subitems falling in that column and get
627 // the biggest one's size.
628 foreach (ListViewItem item in items) {
629 if (col >= item.SubItems.Count)
632 temp = Size.Ceiling (this.DeviceContext.MeasureString
633 (item.SubItems [col].Text, this.Font));
634 if (temp.Width > ret_size.Width)
638 // adjustment for space
639 if (!ret_size.IsEmpty)
645 // Sets the size of the biggest item text as per the view
646 private void CalcTextSize ()
648 // clear the old value
649 text_size = Size.Empty;
651 if (items.Count == 0)
654 text_size = BiggestItem (0);
656 if (view == View.LargeIcon && this.label_wrap) {
657 Size temp = Size.Empty;
658 if (this.check_boxes)
659 temp.Width += 2 * this.CheckBoxSize.Width;
660 if (large_image_list != null)
661 temp.Width += large_image_list.ImageSize.Width;
664 // wrapping is done for two lines only
665 if (text_size.Width > temp.Width) {
666 text_size.Width = temp.Width;
667 text_size.Height *= 2;
670 else if (view == View.List) {
671 // in list view max text shown in determined by the
672 // control width, even if scolling is enabled.
673 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
674 if (this.small_image_list != null)
675 max_wd -= this.small_image_list.ImageSize.Width;
677 if (text_size.Width > max_wd)
678 text_size.Width = max_wd;
681 // we do the default settings, if we have got 0's
682 if (text_size.Height <= 0)
683 text_size.Height = this.Font.Height;
684 if (text_size.Width <= 0)
685 text_size.Width = this.Width;
688 text_size.Width += 4;
689 text_size.Height += 2;
692 // Sets the location of every item on
693 // the ListView as per the view
694 private void CalculateListView (ListViewAlignment align)
696 int current_pos_x = 0; // our x-position marker
697 int current_pos_y = 0; // our y-position marker
700 int max; // max x_pos or y_pos depending on the alignment
701 int current = 0; // current row or column
702 int vertical_spacing = ThemeEngine.Current.ListViewVerticalSpacing;
703 int horizontal_spacing = ThemeEngine.Current.ListViewHorizontalSpacing;
710 // ColumnHeaders are not drawn if headerstyle is none
711 int ht = (this.header_style == ColumnHeaderStyle.None) ?
712 2 : this.Font.Height + 5;
713 if (columns.Count > 0) {
714 foreach (ColumnHeader col in columns) {
715 col.X = current_pos_x;
717 col.CalcColumnHeader ();
718 current_pos_x += col.Wd;
720 this.layout_wd = current_pos_x;
722 // set the position marker for placing items
726 if (items.Count > 0) {
727 foreach (ListViewItem item in items) {
729 item.location.Y = current_pos_y;
730 item.CalcListViewItem ();
731 current_pos_y += item.EntireRect.Height;
733 this.layout_ht = current_pos_y;
735 // some space for bottom gridline
742 vertical_spacing = 0;
743 horizontal_spacing = 0;
744 goto case View.LargeIcon;
747 if (items.Count > 0) {
748 items [0].CalcListViewItem ();
749 item_ht = items [0].EntireRect.Height;
750 item_wd = items [0].EntireRect.Width;
752 // top (default) and snaptogrid alignments are handled same way
753 if (align == ListViewAlignment.Left) {
755 foreach (ListViewItem item in items) {
756 item.location.X = current_pos_x +
758 item.location.Y = current_pos_y;
759 item.CalcListViewItem ();
760 current_pos_y += item_ht;
762 current ++; // just to know about the last element
763 // we just did the last item
764 if (current == items.Count) {
765 if (max < current_pos_y)
767 current_pos_x = item.EntireRect.Right;
771 // is there enough space for another row ?
772 if ((current_pos_y + vertical_spacing
773 + item_ht) <= this.Height)
774 current_pos_y += vertical_spacing;
776 // start another column
777 // make current_pos_y as the
778 // max value and reset
779 // current_pos_y value.
781 current_pos_x += item_wd;
786 // adjust the layout dimensions
787 this.layout_ht = max;
788 this.layout_wd = current_pos_x;
790 else { // other default/top alignment
792 foreach (ListViewItem item in items) {
793 item.location.X = current_pos_x +
796 item.location.Y = current_pos_y;
797 item.CalcListViewItem ();
798 current_pos_x += item_wd;
800 current ++; // just to know about the last element
801 // we just did the last item
802 if (current == items.Count) {
803 if (max < current_pos_x)
805 current_pos_y = item.EntireRect.Bottom;
809 // is there enough space for another column?
810 if ((current_pos_x + horizontal_spacing
811 + item_wd) <= this.Width)
815 // make current_pos_x as the
816 // max value and reset
817 // current_pos_x value.
819 current_pos_y += (item_ht +
825 // adjust the layout dimensions
826 this.layout_wd = max;
827 this.layout_ht = current_pos_y;
833 if (items.Count > 0) {
834 items [0].CalcListViewItem ();
835 item_ht = items [0].EntireRect.Height;
836 item_wd = items [0].EntireRect.Width;
838 max = this.Height / item_ht;
840 max = 1; // we draw at least one row
842 foreach (ListViewItem item in items) {
843 item.location.X = current_pos_x;
844 item.location.Y = current_pos_y;
845 item.CalcListViewItem ();
847 if (current == max) {
848 current_pos_x += item_wd;
853 current_pos_y += item_ht;
856 // adjust the layout dimensions
857 this.layout_ht = max * item_ht;
858 if (current == 0) // we have fully filled layout
859 this.layout_wd = current_pos_x;
861 this.layout_wd = current_pos_x + item_wd;
866 if (this.scrollable && this.items.Count > 0) {
867 // making a scroll bar visible might make
868 // other scroll bar visible
869 if (this.layout_wd > this.Width) {
870 this.h_scroll.Visible = true;
871 if ((this.layout_ht + this.h_scroll.Height) > this.Height)
872 this.v_scroll.Visible = true;
874 else if (this.layout_ht > this.Height) {
875 this.v_scroll.Visible = true;
876 if ((this.layout_wd + this.v_scroll.Width) > this.Width)
877 this.h_scroll.Visible = true;
880 // create big enough buffers
881 if (this.layout_wd > this.Width ||
882 this.layout_ht > this.Height)
883 this.CreateBuffers (this.TotalWidth, this.TotalHeight);
885 if (this.h_scroll.Visible) {
886 this.h_scroll.Location = new Point (0, this.Height
887 - this.h_scroll.Height);
889 this.h_scroll.Minimum = 0;
891 // if v_scroll is visible, adjust the maximum of the
892 // h_scroll to account for the width of v_scroll
893 if (this.v_scroll.Visible) {
894 this.h_scroll.Maximum = this.layout_wd + this.v_scroll.Width;
895 this.h_scroll.Width = this.Width - this.v_scroll.Width;
898 this.h_scroll.Maximum = this.layout_wd;
899 this.h_scroll.Width = this.Width;
902 this.h_scroll.LargeChange = this.Width;
903 this.h_scroll.SmallChange = this.Font.Height;
906 // vertical scrollbar
907 if (this.v_scroll.Visible) {
908 this.v_scroll.Location = new Point (this.Width
909 - this.v_scroll.Width, 0);
911 this.v_scroll.Minimum = 0;
913 // if h_scroll is visible, adjust the maximum of the
914 // v_scroll to account for the height of h_scroll
915 if (this.h_scroll.Visible) {
916 this.v_scroll.Maximum = this.layout_ht + this.h_scroll.Height;
917 this.v_scroll.Height = this.Height - this.h_scroll.Height;
920 this.v_scroll.Maximum = this.layout_ht;
921 this.v_scroll.Height = this.Height;
924 this.v_scroll.LargeChange = this.Height;
925 this.v_scroll.SmallChange = this.Font.Height;
929 this.h_scroll.Visible = false;
930 this.v_scroll.Visible = false;
936 private void ListView_DoubleClick (object sender, EventArgs e)
938 if (this.activation == ItemActivation.Standard
939 && this.ItemActivate != null)
940 this.ItemActivate (this, e);
943 private void ListView_KeyDown (object sender, KeyEventArgs ke)
951 switch (ke.KeyCode) {
953 case Keys.ControlKey:
954 this.ctrl_pressed = true;
962 this.v_scroll.Value = this.v_scroll.Maximum;
966 this.v_scroll.Value = this.v_scroll.Minimum;
971 if (this.last_clicked_item != null)
972 index = this.last_clicked_item.Index;
979 this.last_clicked_item = this.items [index];
980 this.last_clicked_item.Selected = true;
981 this.EnsureVisible (index);
985 if (this.last_clicked_item != null)
986 index = this.last_clicked_item.Index + 1;
990 if (index == this.items.Count)
993 this.last_clicked_item = this.items [index];
994 this.last_clicked_item.Selected = true;
995 this.EnsureVisible (index);
999 this.shift_pressed = true;
1012 private void ListView_KeyUp (object sender, KeyEventArgs ke)
1015 if (ke.KeyCode == Keys.ControlKey)
1016 this.ctrl_pressed = false;
1018 if (ke.KeyCode == Keys.ShiftKey)
1019 this.shift_pressed = false;
1024 private void ListView_MouseDown (object sender, MouseEventArgs me)
1026 if (items.Count == 0)
1029 Point hit = Point.Empty;
1030 if (this.HeaderStyle != ColumnHeaderStyle.None) {
1031 // take horizontal scrolling into account
1032 hit = new Point (me.X + h_marker, me.Y);
1034 // hit test on columns
1035 if (this.view == View.Details && this.columns.Count > 0) {
1036 foreach (ColumnHeader col in this.columns) {
1037 if (col.Rect.Contains (hit)) {
1038 this.clicked_column = col;
1039 this.Capture = true;
1044 if (this.clicked_column != null) {
1045 this.clicked_column.pressed = true;
1046 this.draw_headers = true;
1047 this.Redraw (false);
1053 // hit test on items
1054 // we need to take scrolling into account
1055 hit = new Point (me.X + h_marker, me.Y + v_marker);
1056 foreach (ListViewItem item in this.items) {
1057 if (item.CheckRect.Contains (hit)) {
1058 CheckState curr_state = item.Checked ?
1059 CheckState.Checked : CheckState.Unchecked;
1061 item.Checked = false;
1063 item.Checked = true;
1065 CheckState new_state = item.Checked ?
1066 CheckState.Checked : CheckState.Unchecked;
1067 this.Redraw (false);
1069 // Raise the ItemCheck event
1070 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index,
1073 this.OnItemCheck (ice);
1077 if (this.view == View.Details &&
1078 this.FullRowSelect == false) {
1079 if (item.LabelRect.Contains (hit)) {
1080 this.clicked_item = item;
1085 if (item.EntireRect.Contains (hit)) {
1086 this.clicked_item = item;
1092 // set the FocusedItem to be the current clicked_item
1093 this.focused_item = this.clicked_item;
1095 if (this.clicked_item != null) {
1096 this.clicked_item.Selected = true;
1098 this.OnSelectedIndexChanged (new EventArgs ());
1100 this.Redraw (false);
1104 private void ListView_MouseHover (object sender, EventArgs e)
1106 // handle the hover events only when the mouse
1108 if (this.hover_selection == false || this.Capture)
1111 // hit test for the items
1112 Point hit = this.PointToClient (Control.MousePosition);
1113 ListViewItem item = this.GetItemAt (hit.X, hit.Y);
1116 item.Selected = true;
1118 this.OnSelectedIndexChanged (new EventArgs ());
1120 this.Redraw (false);
1124 private void ListView_MouseMove (object sender, MouseEventArgs me)
1126 // Column header is always at the top. It can
1127 // scroll only horizontally. So, we have to take
1128 // only horizontal scrolling into account
1129 Point hit = new Point (me.X + h_marker, me.Y);
1131 // non-null clicked_col means mouse down has happened
1133 if (this.clicked_column != null) {
1134 if (this.clicked_column.pressed == false &&
1135 this.clicked_column.Rect.Contains (hit)) {
1136 this.clicked_column.pressed = true;
1137 this.draw_headers = true;
1138 this.Redraw (false);
1140 else if (this.clicked_column.pressed &&
1141 ! this.clicked_column.Rect.Contains (hit)) {
1142 this.clicked_column.pressed = false;
1143 this.draw_headers = true;
1144 this.Redraw (false);
1149 private void ListView_MouseUp (object sender, MouseEventArgs me)
1151 this.Capture = false;
1152 if (items.Count == 0)
1155 Point hit = new Point (me.X, me.Y);
1157 if (this.clicked_column != null) {
1158 if (this.clicked_column.pressed) {
1159 this.clicked_column.pressed = false;
1160 this.draw_headers = true;
1161 this.Redraw (false);
1163 // Raise the ColumnClick event
1164 this.OnColumnClick (new ColumnClickEventArgs
1165 (this.clicked_column.Index));
1169 // Raise the ItemActivate event
1170 Rectangle rect = Rectangle.Empty;
1171 if (this.clicked_item != null) {
1172 if (this.view == View.Details && !this.full_row_select)
1173 rect = this.clicked_item.LabelRect;
1175 rect = this.clicked_item.EntireRect;
1177 // We handle double click in a separate handler
1178 if (this.activation != ItemActivation.Standard &&
1179 rect.Contains (hit)) {
1180 if (this.activation == ItemActivation.OneClick)
1181 this.ItemActivate (this, EventArgs.Empty);
1183 // ItemActivate is raised on the second click on the same item
1184 else if (this.activation == ItemActivation.TwoClick) {
1185 if (this.last_clicked_item == this.clicked_item) {
1186 this.ItemActivate (this, EventArgs.Empty);
1187 this.last_clicked_item = null;
1190 this.last_clicked_item = this.clicked_item;
1195 this.clicked_column = null;
1196 this.clicked_item = null;
1199 private void ListView_Paint (object sender, PaintEventArgs pe)
1201 if (this.Width <= 0 || this.Height <= 0 ||
1202 this.Visible == false || this.updating == true)
1206 ThemeEngine.Current.DrawListView (pe.Graphics,
1207 pe.ClipRectangle, this);
1211 // We paint on the screen as per the location set
1212 // by the two scrollbars. In case of details view
1213 // since column headers can scroll only horizontally
1214 // and items can scroll in both directions, paiting is
1215 // done separtely for the column header and the items.
1217 Rectangle srcRect = this.ClientRectangle;
1218 Rectangle dstRect = this.ClientRectangle;
1220 // set the visible starting point
1222 srcRect.X += h_marker;
1223 srcRect.Y += v_marker;
1225 if (h_scroll.Visible) {
1226 srcRect.Height -= h_scroll.Height;
1227 dstRect.Height -= h_scroll.Height;
1230 if (v_scroll.Visible) {
1231 srcRect.Width -= v_scroll.Width;
1232 dstRect.Width -= v_scroll.Width;
1236 // We paint the column headers always at the top, in case
1237 // of vertical scrolling. Therefore, we advance the painting
1238 // by the amount equal to the column height.
1240 if (this.view == View.Details &&
1241 this.Columns.Count > 0 &&
1242 this.header_style != ColumnHeaderStyle.None &&
1245 int col_ht = this.Columns [0].Ht;
1247 if (this.draw_headers) {
1248 this.draw_headers = false;
1249 // Move the source rect by the amount of horizontal
1250 // scrolling done so far.
1251 Rectangle headerSrc = new Rectangle (h_marker, 0,
1252 srcRect.Width, col_ht);
1253 // dest rect is always stable at 0,0
1254 Rectangle headerDst = new Rectangle (0, 0, srcRect.Width, col_ht);
1255 pe.Graphics.DrawImage (this.ImageBuffer, headerDst,
1256 headerSrc, GraphicsUnit.Pixel);
1259 dstRect.Y += col_ht;
1260 srcRect.Y += col_ht;
1264 // Draw the border of the list view
1265 // The border is painted here separately, because
1266 // our imagebuffer might be scrollable
1267 ThemeEngine.Current.CPDrawBorderStyle (pe.Graphics,
1268 this.ClientRectangle,
1271 // Raise the Paint event
1276 private void HorizontalScroller (object sender, EventArgs e)
1278 // Avoid unnecessary flickering, when button is
1279 // kept pressed at the end
1280 if (h_marker != h_scroll.Value) {
1281 h_marker = h_scroll.Value;
1282 // draw the headers again
1283 this.draw_headers = true;
1288 private void VerticalScroller (object sender, EventArgs e)
1290 // Avoid unnecessary flickering, when button is
1291 // kept pressed at the end
1292 if (v_marker != v_scroll.Value) {
1293 v_marker = v_scroll.Value;
1297 #endregion // Internal Methods Properties
1299 #region Protected Methods
1300 protected override void CreateHandle ()
1302 base.CreateHandle ();
1305 protected override void Dispose (bool disposing)
1307 base.Dispose (disposing);
1310 protected override bool IsInputKey (Keys keyData)
1312 return base.IsInputKey (keyData);
1315 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1317 if (AfterLabelEdit != null)
1318 AfterLabelEdit (this, e);
1321 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1323 if (BeforeLabelEdit != null)
1324 BeforeLabelEdit (this, e);
1327 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1329 if (ColumnClick != null)
1330 ColumnClick (this, e);
1333 protected override void OnEnabledChanged (EventArgs e)
1335 base.OnEnabledChanged (e);
1338 protected override void OnFontChanged (EventArgs e)
1340 base.OnFontChanged (e);
1344 protected override void OnHandleCreated (EventArgs e)
1346 base.OnHandleCreated (e);
1347 this.Controls.Add (this.v_scroll);
1348 this.Controls.Add (this.h_scroll);
1351 protected override void OnHandleDestroyed (EventArgs e)
1353 base.OnHandleDestroyed (e);
1356 protected virtual void OnItemActivate (EventArgs e)
1358 if (ItemActivate != null)
1359 ItemActivate (this, e);
1362 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1364 if (ItemCheck != null)
1365 ItemCheck (this, ice);
1368 protected virtual void OnItemDrag (ItemDragEventArgs e)
1370 if (ItemDrag != null)
1374 protected virtual void OnSelectedIndexChanged (EventArgs e)
1376 if (SelectedIndexChanged != null)
1377 SelectedIndexChanged (this, e);
1380 protected override void OnSystemColorsChanged (EventArgs e)
1382 base.OnSystemColorsChanged (e);
1385 protected void RealizeProperties ()
1390 protected void UpdateExtendedStyles ()
1395 protected override void WndProc (ref Message m)
1397 base.WndProc (ref m);
1399 #endregion // Protected Methods
1401 #region Public Instance Methods
1402 public void ArrangeIcons ()
1404 ArrangeIcons (this.alignment);
1407 public void ArrangeIcons (ListViewAlignment alignment)
1409 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1410 if (view == View.LargeIcon || view == View.SmallIcon) {
1411 this.CalculateListView (alignment);
1412 // we have done the calculations already
1413 this.Redraw (false);
1417 public void BeginUpdate ()
1419 // flag to avoid painting
1423 public void Clear ()
1430 public void EndUpdate ()
1432 // flag to avoid painting
1435 // probably, now we need a redraw with recalculations
1439 public void EnsureVisible (int index)
1441 if (index < 0 || index >= this.items.Count || this.scrollable == false)
1444 // dimensions of visible area
1445 int view_wd = this.Width - (this.v_scroll.Visible ? this.v_scroll.Width : 0);
1446 int view_ht = this.Height - (this.h_scroll.Visible ? this.h_scroll.Height : 0);
1447 // visible area is decided by the h_marker and v_marker
1448 Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1450 // an item's bounding rect
1451 Rectangle rect = this.items [index].EntireRect;
1453 // we don't need to do anything if item is visible.
1454 // visible area is represented by (0,0,view_wd,view_ht)
1455 if (view_rect.Contains (rect))
1458 // Scroll Left or Up
1459 if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1460 if (rect.Left < view_rect.Left)
1461 this.h_scroll.Value -= (view_rect.Left - rect.Left);
1462 if (rect.Top < view_rect.Top)
1463 this.v_scroll.Value -= (view_rect.Top - rect.Top);
1465 // Scroll Right or Down
1467 if (rect.Right > view_rect.Right)
1468 this.h_scroll.Value += (rect.Right - view_rect.Right);
1469 if (rect.Bottom > view_rect.Bottom)
1470 this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1474 public ListViewItem GetItemAt (int x, int y)
1476 foreach (ListViewItem item in items) {
1477 if (item.Bounds.Contains (x, y))
1483 public Rectangle GetItemRect (int index)
1485 return GetItemRect (index, ItemBoundsPortion.Entire);
1488 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1490 if (index < 0 || index >= items.Count)
1491 throw new IndexOutOfRangeException ("Invalid Index");
1493 return items [index].GetBounds (portion);
1498 if (sort_order != SortOrder.None)
1499 items.list.Sort (item_sorter);
1501 if (sort_order == SortOrder.Descending)
1502 items.list.Reverse ();
1507 public override string ToString ()
1509 int count = this.Items.Count;
1512 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1514 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1516 #endregion // Public Instance Methods
1520 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1522 internal ArrayList list;
1523 private ListView owner;
1525 #region Public Constructor
1526 public CheckedIndexCollection (ListView owner)
1528 list = new ArrayList ();
1531 #endregion // Public Constructor
1533 #region Public Properties
1535 public virtual int Count {
1536 get { return list.Count; }
1539 public virtual bool IsReadOnly {
1540 get { return true; }
1543 public int this [int index] {
1545 if (index < 0 || index >= list.Count)
1546 throw new ArgumentOutOfRangeException ("Index out of range.");
1547 return (int) list [index];
1551 bool ICollection.IsSynchronized {
1552 get { return list.IsSynchronized; }
1555 object ICollection.SyncRoot {
1556 get { return list.SyncRoot; }
1559 bool IList.IsFixedSize {
1560 get { return list.IsFixedSize; }
1563 object IList.this [int index] {
1564 get { return this [index]; }
1565 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1567 #endregion // Public Properties
1569 #region Public Methods
1570 public bool Contains (int checkedIndex)
1572 return list.Contains (checkedIndex);
1575 public virtual IEnumerator GetEnumerator ()
1577 return list.GetEnumerator ();
1580 void ICollection.CopyTo (Array dest, int index)
1582 list.CopyTo (dest, index);
1585 int IList.Add (object value)
1587 throw new NotSupportedException ("Add operation is not supported.");
1592 throw new NotSupportedException ("Clear operation is not supported.");
1595 bool IList.Contains (object checkedIndex)
1597 return list.Contains (checkedIndex);
1600 int IList.IndexOf (object checkedIndex)
1602 return list.IndexOf (checkedIndex);
1605 void IList.Insert (int index, object value)
1607 throw new NotSupportedException ("Insert operation is not supported.");
1610 void IList.Remove (object value)
1612 throw new NotSupportedException ("Remove operation is not supported.");
1615 void IList.RemoveAt (int index)
1617 throw new NotSupportedException ("RemoveAt operation is not supported.");
1620 public int IndexOf (int checkedIndex)
1622 return list.IndexOf (checkedIndex);
1624 #endregion // Public Methods
1626 } // CheckedIndexCollection
1628 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1630 internal ArrayList list;
1631 private ListView owner;
1633 #region Public Constructor
1634 public CheckedListViewItemCollection (ListView owner)
1636 list = new ArrayList ();
1639 #endregion // Public Constructor
1641 #region Public Properties
1643 public virtual int Count {
1644 get { return list.Count; }
1647 public virtual bool IsReadOnly {
1648 get { return true; }
1651 public ListViewItem this [int index] {
1653 if (index < 0 || index >= list.Count)
1654 throw new ArgumentOutOfRangeException ("Index out of range.");
1655 return (ListViewItem) list [index];
1659 bool ICollection.IsSynchronized {
1660 get { return list.IsSynchronized; }
1663 object ICollection.SyncRoot {
1664 get { return list.SyncRoot; }
1667 bool IList.IsFixedSize {
1668 get { return list.IsFixedSize; }
1671 object IList.this [int index] {
1672 get { return this [index]; }
1673 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1675 #endregion // Public Properties
1677 #region Public Methods
1678 public bool Contains (ListViewItem item)
1680 return list.Contains (item);
1683 public virtual void CopyTo (Array dest, int index)
1685 list.CopyTo (dest, index);
1688 public virtual IEnumerator GetEnumerator ()
1690 return list.GetEnumerator ();
1693 int IList.Add (object value)
1695 throw new NotSupportedException ("Add operation is not supported.");
1700 throw new NotSupportedException ("Clear operation is not supported.");
1703 bool IList.Contains (object item)
1705 return list.Contains (item);
1708 int IList.IndexOf (object item)
1710 return list.IndexOf (item);
1713 void IList.Insert (int index, object value)
1715 throw new NotSupportedException ("Insert operation is not supported.");
1718 void IList.Remove (object value)
1720 throw new NotSupportedException ("Remove operation is not supported.");
1723 void IList.RemoveAt (int index)
1725 throw new NotSupportedException ("RemoveAt operation is not supported.");
1728 public int IndexOf (ListViewItem item)
1730 return list.IndexOf (item);
1732 #endregion // Public Methods
1734 } // CheckedListViewItemCollection
1736 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1738 internal ArrayList list;
1739 private ListView owner;
1741 #region Public Constructor
1742 public ColumnHeaderCollection (ListView owner)
1744 list = new ArrayList ();
1747 #endregion // Public Constructor
1749 #region Public Properties
1751 public virtual int Count {
1752 get { return list.Count; }
1755 public virtual bool IsReadOnly {
1756 get { return false; }
1759 public virtual ColumnHeader this [int index] {
1761 if (index < 0 || index >= list.Count)
1762 throw new ArgumentOutOfRangeException ("Index out of range.");
1763 return (ColumnHeader) list [index];
1767 bool ICollection.IsSynchronized {
1768 get { return list.IsSynchronized; }
1771 object ICollection.SyncRoot {
1772 get { return list.SyncRoot; }
1775 bool IList.IsFixedSize {
1776 get { return list.IsFixedSize; }
1779 object IList.this [int index] {
1780 get { return this [index]; }
1781 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1783 #endregion // Public Properties
1785 #region Public Methods
1786 public virtual int Add (ColumnHeader value)
1789 value.owner = this.owner;
1790 idx = list.Add (value);
1791 owner.Redraw (true);
1795 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1797 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1798 this.Add (colHeader);
1802 public virtual void AddRange (ColumnHeader [] values)
1804 foreach (ColumnHeader colHeader in values) {
1805 colHeader.owner = this.owner;
1809 owner.Redraw (true);
1812 public virtual void Clear ()
1815 owner.Redraw (true);
1818 public bool Contains (ColumnHeader value)
1820 return list.Contains (value);
1823 public virtual IEnumerator GetEnumerator ()
1825 return list.GetEnumerator ();
1828 void ICollection.CopyTo (Array dest, int index)
1830 list.CopyTo (dest, index);
1833 int IList.Add (object value)
1835 if (! (value is ColumnHeader)) {
1836 throw new ArgumentException ("Not of type ColumnHeader", "value");
1839 return this.Add ((ColumnHeader) value);
1842 bool IList.Contains (object value)
1844 if (! (value is ColumnHeader)) {
1845 throw new ArgumentException ("Not of type ColumnHeader", "value");
1848 return this.Contains ((ColumnHeader) value);
1851 int IList.IndexOf (object value)
1853 if (! (value is ColumnHeader)) {
1854 throw new ArgumentException ("Not of type ColumnHeader", "value");
1857 return this.IndexOf ((ColumnHeader) value);
1860 void IList.Insert (int index, object value)
1862 if (! (value is ColumnHeader)) {
1863 throw new ArgumentException ("Not of type ColumnHeader", "value");
1866 this.Insert (index, (ColumnHeader) value);
1869 void IList.Remove (object value)
1871 if (! (value is ColumnHeader)) {
1872 throw new ArgumentException ("Not of type ColumnHeader", "value");
1875 this.Remove ((ColumnHeader) value);
1878 public int IndexOf (ColumnHeader value)
1880 return list.IndexOf (value);
1883 public void Insert (int index, ColumnHeader value)
1885 if (index < 0 || index >= list.Count)
1886 throw new ArgumentOutOfRangeException ("Index out of range.");
1888 value.owner = this.owner;
1889 list.Insert (index, value);
1890 owner.Redraw (true);
1893 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1895 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1896 this.Insert (index, colHeader);
1899 public virtual void Remove (ColumnHeader column)
1901 // TODO: Update Column internal index ?
1902 list.Remove (column);
1903 owner.Redraw (true);
1906 public virtual void RemoveAt (int index)
1908 if (index < 0 || index >= list.Count)
1909 throw new ArgumentOutOfRangeException ("Index out of range.");
1911 // TODO: Update Column internal index ?
1912 list.RemoveAt (index);
1913 owner.Redraw (true);
1915 #endregion // Public Methods
1918 } // ColumnHeaderCollection
1920 public class ListViewItemCollection : IList, ICollection, IEnumerable
1922 internal ArrayList list;
1923 private ListView owner;
1925 #region Public Constructor
1926 public ListViewItemCollection (ListView owner)
1928 list = new ArrayList ();
1931 #endregion // Public Constructor
1933 #region Public Properties
1935 public virtual int Count {
1936 get { return list.Count; }
1939 public virtual bool IsReadOnly {
1940 get { return false; }
1943 public virtual ListViewItem this [int displayIndex] {
1945 if (displayIndex < 0 || displayIndex >= list.Count)
1946 throw new ArgumentOutOfRangeException ("Index out of range.");
1947 return (ListViewItem) list [displayIndex];
1951 if (displayIndex < 0 || displayIndex >= list.Count)
1952 throw new ArgumentOutOfRangeException ("Index out of range.");
1954 if (list.Contains (value))
1955 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1957 value.owner = this.owner;
1958 list [displayIndex] = value;
1960 owner.Redraw (true);
1964 bool ICollection.IsSynchronized {
1965 get { return list.IsSynchronized; }
1968 object ICollection.SyncRoot {
1969 get { return list.SyncRoot; }
1972 bool IList.IsFixedSize {
1973 get { return list.IsFixedSize; }
1976 object IList.this [int index] {
1977 get { return this [index]; }
1979 if (value is ListViewItem)
1980 this [index] = (ListViewItem) value;
1982 this [index] = new ListViewItem (value.ToString ());
1985 #endregion // Public Properties
1987 #region Public Methods
1988 public virtual ListViewItem Add (ListViewItem value)
1990 if (list.Contains (value))
1991 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1993 value.owner = this.owner;
1996 if (owner.Sorting != SortOrder.None)
1999 owner.Redraw (true);
2004 public virtual ListViewItem Add (string text)
2006 ListViewItem item = new ListViewItem (text);
2007 return this.Add (item);
2010 public virtual ListViewItem Add (string text, int imageIndex)
2012 ListViewItem item = new ListViewItem (text, imageIndex);
2013 return this.Add (item);
2016 public void AddRange (ListViewItem [] values)
2020 foreach (ListViewItem item in values) {
2021 item.owner = this.owner;
2025 if (owner.Sorting != SortOrder.None)
2028 owner.Redraw (true);
2031 public virtual void Clear ()
2036 public bool Contains (ListViewItem item)
2038 return list.Contains (item);
2041 public virtual void CopyTo (Array dest, int index)
2043 list.CopyTo (dest, index);
2046 public virtual IEnumerator GetEnumerator ()
2048 return list.GetEnumerator ();
2051 int IList.Add (object item)
2056 if (item is ListViewItem) {
2057 li = (ListViewItem) item;
2058 if (list.Contains (li))
2059 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2062 li = new ListViewItem (item.ToString ());
2064 li.owner = this.owner;
2065 result = list.Add (li);
2066 owner.Redraw (true);
2071 bool IList.Contains (object item)
2073 return list.Contains (item);
2076 int IList.IndexOf (object item)
2078 return list.IndexOf (item);
2081 void IList.Insert (int index, object item)
2083 if (item is ListViewItem)
2084 this.Insert (index, (ListViewItem) item);
2086 this.Insert (index, item.ToString ());
2089 void IList.Remove (object item)
2091 if (list.Contains (item)) {
2093 owner.Redraw (true);
2097 public int IndexOf (ListViewItem item)
2099 return list.IndexOf (item);
2102 public ListViewItem Insert (int index, ListViewItem item)
2104 if (index < 0 || index >= list.Count)
2105 throw new ArgumentOutOfRangeException ("Index out of range.");
2107 if (list.Contains (item))
2108 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2110 item.owner = this.owner;
2111 list.Insert (index, item);
2112 owner.Redraw (true);
2116 public ListViewItem Insert (int index, string text)
2118 return this.Insert (index, new ListViewItem (text));
2121 public ListViewItem Insert (int index, string text, int imageIndex)
2123 return this.Insert (index, new ListViewItem (text, imageIndex));
2126 public virtual void Remove (ListViewItem item)
2128 if (list.Contains (item)) {
2130 owner.Redraw (true);
2134 public virtual void RemoveAt (int index)
2136 if (index < 0 || index >= list.Count)
2137 throw new ArgumentOutOfRangeException ("Index out of range.");
2139 list.RemoveAt (index);
2140 owner.Redraw (false);
2142 #endregion // Public Methods
2144 } // ListViewItemCollection
2146 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2148 internal ArrayList list;
2149 private ListView owner;
2151 #region Public Constructor
2152 public SelectedIndexCollection (ListView owner)
2154 list = new ArrayList ();
2157 #endregion // Public Constructor
2159 #region Public Properties
2161 public virtual int Count {
2162 get { return list.Count; }
2165 public virtual bool IsReadOnly {
2166 get { return true; }
2169 public int this [int index] {
2171 if (index < 0 || index >= list.Count)
2172 throw new ArgumentOutOfRangeException ("Index out of range.");
2173 return (int) list [index];
2177 bool ICollection.IsSynchronized {
2178 get { return list.IsSynchronized; }
2181 object ICollection.SyncRoot {
2182 get { return list.SyncRoot; }
2185 bool IList.IsFixedSize {
2186 get { return list.IsFixedSize; }
2189 object IList.this [int index] {
2190 get { return this [index]; }
2191 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2193 #endregion // Public Properties
2195 #region Public Methods
2196 public bool Contains (int selectedIndex)
2198 return list.Contains (selectedIndex);
2201 public virtual void CopyTo (Array dest, int index)
2203 list.CopyTo (dest, index);
2206 public virtual IEnumerator GetEnumerator ()
2208 return list.GetEnumerator ();
2211 int IList.Add (object value)
2213 throw new NotSupportedException ("Add operation is not supported.");
2218 throw new NotSupportedException ("Clear operation is not supported.");
2221 bool IList.Contains (object selectedIndex)
2223 return list.Contains (selectedIndex);
2226 int IList.IndexOf (object selectedIndex)
2228 return list.IndexOf (selectedIndex);
2231 void IList.Insert (int index, object value)
2233 throw new NotSupportedException ("Insert operation is not supported.");
2236 void IList.Remove (object value)
2238 throw new NotSupportedException ("Remove operation is not supported.");
2241 void IList.RemoveAt (int index)
2243 throw new NotSupportedException ("RemoveAt operation is not supported.");
2246 public int IndexOf (int selectedIndex)
2248 return list.IndexOf (selectedIndex);
2250 #endregion // Public Methods
2252 } // SelectedIndexCollection
2254 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2256 internal ArrayList list;
2257 private ListView owner;
2259 #region Public Constructor
2260 public SelectedListViewItemCollection (ListView owner)
2262 list = new ArrayList ();
2265 #endregion // Public Constructor
2267 #region Public Properties
2269 public virtual int Count {
2270 get { return list.Count; }
2273 public virtual bool IsReadOnly {
2274 get { return true; }
2277 public ListViewItem this [int index] {
2279 if (index < 0 || index >= list.Count)
2280 throw new ArgumentOutOfRangeException ("Index out of range.");
2281 return (ListViewItem) list [index];
2285 bool ICollection.IsSynchronized {
2286 get { return list.IsSynchronized; }
2289 object ICollection.SyncRoot {
2290 get { return list.SyncRoot; }
2293 bool IList.IsFixedSize {
2294 get { return list.IsFixedSize; }
2297 object IList.this [int index] {
2298 get { return this [index]; }
2299 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2301 #endregion // Public Properties
2303 #region Public Methods
2304 public virtual void Clear ()
2306 // mark the items as unselected before clearing the list
2307 for (int i = 0; i < list.Count; i++)
2308 ((ListViewItem) list [i]).selected = false;
2313 public bool Contains (ListViewItem item)
2315 return list.Contains (item);
2318 public virtual void CopyTo (Array dest, int index)
2320 list.CopyTo (dest, index);
2323 public virtual IEnumerator GetEnumerator ()
2325 return list.GetEnumerator ();
2328 int IList.Add (object value)
2330 throw new NotSupportedException ("Add operation is not supported.");
2333 bool IList.Contains (object item)
2335 return list.Contains (item);
2338 int IList.IndexOf (object item)
2340 return list.IndexOf (item);
2343 void IList.Insert (int index, object value)
2345 throw new NotSupportedException ("Insert operation is not supported.");
2348 void IList.Remove (object value)
2350 throw new NotSupportedException ("Remove operation is not supported.");
2353 void IList.RemoveAt (int index)
2355 throw new NotSupportedException ("RemoveAt operation is not supported.");
2358 public int IndexOf (ListViewItem item)
2360 return list.IndexOf (item);
2362 #endregion // Public Methods
2364 } // SelectedListViewItemCollection
2366 #endregion // Subclasses