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 // - Item text editing
28 // - Column resizing/reodering
29 // - Feedback for item activation, change in cursor types as mouse moves.
32 // - Manual column resizing
39 using System.Collections;
40 using System.ComponentModel;
41 using System.ComponentModel.Design;
43 using System.Runtime.InteropServices;
45 namespace System.Windows.Forms
47 [DefaultEvent ("SelectedIndexChanged")]
48 [DefaultProperty ("Items")]
49 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
50 public class ListView : Control
52 private ItemActivation activation = ItemActivation.Standard;
53 private ListViewAlignment alignment = ListViewAlignment.Top;
54 private bool allow_column_reorder = false;
55 private bool auto_arrange = true;
56 private bool check_boxes = false;
57 private CheckedIndexCollection checked_indices;
58 private CheckedListViewItemCollection checked_items;
59 private ColumnHeader clicked_column;
60 private ListViewItem clicked_item;
61 private ListViewItem last_clicked_item;
62 private ColumnHeaderCollection columns;
63 private bool ctrl_pressed;
64 private bool shift_pressed;
65 internal ListViewItem focused_item;
66 private bool full_row_select = false;
67 private bool grid_lines = false;
68 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
69 private bool hide_selection = true;
70 private bool hover_selection = false;
71 private IComparer item_sorter;
72 private ListViewItemCollection items;
73 private bool label_edit = false;
74 private bool label_wrap = true;
75 private bool multiselect = true;
76 private bool scrollable = true;
77 private SelectedIndexCollection selected_indices;
78 private SelectedListViewItemCollection selected_items;
79 private SortOrder sort_order = SortOrder.None;
80 private ImageList state_image_list;
81 private bool updating = false;
82 private View view = View.LargeIcon;
83 private int layout_wd; // We might draw more than our client area
84 private int layout_ht; // therefore we need to have these two.
85 //private TextBox editor; // Used for editing an item text
86 internal ScrollBar h_scroll; // used for scrolling horizontally
87 internal ScrollBar v_scroll; // used for scrolling vertically
88 internal int h_marker; // Position markers for scrolling
89 internal int v_marker;
90 internal Rectangle client_area; // ClientRectangle - scrollbars
93 internal ImageList large_image_list;
94 internal ImageList small_image_list;
95 internal Size text_size = Size.Empty;
98 public event LabelEditEventHandler AfterLabelEdit;
101 [EditorBrowsable (EditorBrowsableState.Never)]
102 public new event EventHandler BackgroundImageChanged;
104 public event LabelEditEventHandler BeforeLabelEdit;
105 public event ColumnClickEventHandler ColumnClick;
106 public event EventHandler ItemActivate;
107 public event ItemCheckEventHandler ItemCheck;
108 public event ItemDragEventHandler ItemDrag;
111 [EditorBrowsable (EditorBrowsableState.Never)]
112 public new event PaintEventHandler Paint;
114 public event EventHandler SelectedIndexChanged;
117 [EditorBrowsable (EditorBrowsableState.Never)]
118 public new event EventHandler TextChanged;
121 #region Public Constructors
124 background_color = ThemeEngine.Current.ColorWindow;
125 checked_indices = new CheckedIndexCollection (this);
126 checked_items = new CheckedListViewItemCollection (this);
127 columns = new ColumnHeaderCollection (this);
128 foreground_color = SystemColors.WindowText;
129 items = new ListViewItemCollection (this);
130 selected_indices = new SelectedIndexCollection (this);
131 selected_items = new SelectedListViewItemCollection (this);
133 border_style = BorderStyle.Fixed3D;
135 // we are mostly scrollable
136 h_scroll = new HScrollBar ();
137 v_scroll = new VScrollBar ();
138 h_marker = v_marker = 0;
140 // scroll bars are disabled initially
141 h_scroll.Visible = false;
142 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
143 v_scroll.Visible = false;
144 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
147 base.DoubleClick += new EventHandler(ListView_DoubleClick);
148 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
149 base.KeyUp += new KeyEventHandler(ListView_KeyUp);
150 base.MouseDown += new MouseEventHandler(ListView_MouseDown);
151 base.MouseHover += new EventHandler(ListView_MouseHover);
152 base.MouseUp += new MouseEventHandler(ListView_MouseUp);
153 base.MouseMove += new MouseEventHandler(ListView_MouseMove);
154 base.Paint += new PaintEventHandler (ListView_Paint);
155 SizeChanged += new EventHandler (ListView_SizeChanged);
157 this.SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
159 #endregion // Public Constructors
161 #region Private Internal Properties
162 internal Size CheckBoxSize {
164 if (this.check_boxes) {
165 if (this.state_image_list != null)
166 return this.state_image_list.ImageSize;
168 return ThemeEngine.Current.ListViewCheckBoxSize;
174 internal bool CanMultiselect {
176 if (this.multiselect &&
177 (this.ctrl_pressed || this.shift_pressed))
183 #endregion // Private Internal Properties
185 #region Protected Properties
186 protected override CreateParams CreateParams {
187 get { return base.CreateParams; }
190 protected override Size DefaultSize {
191 get { return ThemeEngine.Current.ListViewDefaultSize; }
193 #endregion // Protected Properties
195 #region Public Instance Properties
196 [DefaultValue (ItemActivation.Standard)]
197 public ItemActivation Activation {
198 get { return activation; }
200 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
201 value != ItemActivation.TwoClick) {
202 throw new InvalidEnumArgumentException (string.Format
203 ("Enum argument value '{0}' is not valid for Activation", value));
210 [DefaultValue (ListViewAlignment.Top)]
212 public ListViewAlignment Alignment {
213 get { return alignment; }
215 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
216 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
217 throw new InvalidEnumArgumentException (string.Format
218 ("Enum argument value '{0}' is not valid for Alignment", value));
221 if (this.alignment != value) {
223 // alignment does not matter in Details/List views
224 if (this.view == View.LargeIcon ||
225 this.View == View.SmallIcon)
231 [DefaultValue (false)]
232 public bool AllowColumnReorder {
233 get { return allow_column_reorder; }
235 if (this.allow_column_reorder != value) {
236 allow_column_reorder = value;
237 // column reorder does not matter in Details view
238 if (this.view != View.Details)
244 [DefaultValue (true)]
245 public bool AutoArrange {
246 get { return auto_arrange; }
248 if (auto_arrange != value) {
249 auto_arrange = value;
250 // autoarrange does not matter in Details/List views
251 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
257 public override Color BackColor {
259 if (background_color.IsEmpty)
260 return ThemeEngine.Current.ColorWindow;
262 return background_color;
264 set { background_color = value; }
268 [EditorBrowsable (EditorBrowsableState.Never)]
269 public override Image BackgroundImage {
270 get { return background_image; }
272 if (value == background_image)
275 background_image = value;
276 if (BackgroundImageChanged != null)
277 BackgroundImageChanged (this, new EventArgs ());
281 [DefaultValue (BorderStyle.Fixed3D)]
283 public BorderStyle BorderStyle {
284 get { return InternalBorderStyle; }
285 set { InternalBorderStyle = value; }
288 [DefaultValue (false)]
289 public bool CheckBoxes {
290 get { return check_boxes; }
292 if (check_boxes != value) {
300 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
301 public CheckedIndexCollection CheckedIndices {
302 get { return checked_indices; }
306 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
307 public CheckedListViewItemCollection CheckedItems {
308 get { return checked_items; }
311 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
313 [MergableProperty (false)]
314 public ColumnHeaderCollection Columns {
315 get { return columns; }
319 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
320 public ListViewItem FocusedItem {
321 get { return focused_item; }
324 public override Color ForeColor {
326 if (foreground_color.IsEmpty)
327 return ThemeEngine.Current.ColorWindowText;
329 return foreground_color;
331 set { foreground_color = value; }
334 [DefaultValue (false)]
335 public bool FullRowSelect {
336 get { return full_row_select; }
337 set { full_row_select = value; }
340 [DefaultValue (false)]
341 public bool GridLines {
342 get { return grid_lines; }
344 if (grid_lines != value) {
351 [DefaultValue (ColumnHeaderStyle.Clickable)]
352 public ColumnHeaderStyle HeaderStyle {
353 get { return header_style; }
355 if (value != ColumnHeaderStyle.Clickable && value != ColumnHeaderStyle.Nonclickable &&
356 value != ColumnHeaderStyle.None) {
357 throw new InvalidEnumArgumentException (string.Format
358 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
361 if (header_style != value) {
362 header_style = value;
363 // header style matters only in Details view
364 if (this.view == View.Details)
370 [DefaultValue (true)]
371 public bool HideSelection {
372 get { return hide_selection; }
374 if (hide_selection != value) {
375 hide_selection = value;
381 [DefaultValue (false)]
382 public bool HoverSelection {
383 get { return hover_selection; }
384 set { hover_selection = value; }
387 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
389 [MergableProperty (false)]
390 public ListViewItemCollection Items {
391 get { return items; }
394 [DefaultValue (false)]
395 public bool LabelEdit {
396 get { return label_edit; }
397 set { label_edit = value; }
400 [DefaultValue (true)]
402 public bool LabelWrap {
403 get { return label_wrap; }
405 if (label_wrap != value) {
412 [DefaultValue (null)]
413 public ImageList LargeImageList {
414 get { return large_image_list; }
416 large_image_list = value;
422 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
423 public IComparer ListViewItemSorter {
424 get { return item_sorter; }
425 set { item_sorter = value; }
428 [DefaultValue (true)]
429 public bool MultiSelect {
430 get { return multiselect; }
431 set { multiselect = value; }
434 [DefaultValue (true)]
435 public bool Scrollable {
436 get { return scrollable; }
438 if (scrollable != value) {
446 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
447 public SelectedIndexCollection SelectedIndices {
448 get { return selected_indices; }
452 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
453 public SelectedListViewItemCollection SelectedItems {
454 get { return selected_items; }
457 [DefaultValue (null)]
458 public ImageList SmallImageList {
459 get { return small_image_list; }
461 small_image_list = value;
466 [DefaultValue (SortOrder.None)]
467 public SortOrder Sorting {
468 get { return sort_order; }
470 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
471 value != SortOrder.None) {
472 throw new InvalidEnumArgumentException (string.Format
473 ("Enum argument value '{0}' is not valid for Sorting", value));
476 if (sort_order != value) {
483 [DefaultValue (null)]
484 public ImageList StateImageList {
485 get { return state_image_list; }
487 state_image_list = value;
494 [EditorBrowsable (EditorBrowsableState.Never)]
495 public override string Text {
504 if (TextChanged != null)
505 TextChanged (this, new EventArgs ());
510 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
511 public ListViewItem TopItem {
514 if (this.items.Count == 0)
516 // if contents are not scrolled
517 // it is the first item
518 else if (h_marker == 0 && v_marker == 0)
519 return this.items [0];
520 // do a hit test for the scrolled position
522 foreach (ListViewItem item in this.items) {
523 if (item.EntireRect.X >= h_marker && item.EntireRect.Y >= v_marker)
531 [DefaultValue (View.LargeIcon)]
535 if (value != View.Details && value != View.LargeIcon &&
536 value != View.List && value != View.SmallIcon ) {
537 throw new InvalidEnumArgumentException (string.Format
538 ("Enum argument value '{0}' is not valid for View", value));
547 #endregion // Public Instance Properties
549 #region Internal Methods Properties
551 public int FirstVisibleIndex {
554 if (this.items.Count == 0)
557 if (h_marker == 0 && v_marker == 0)
560 foreach (ListViewItem item in this.items) {
561 if (item.EntireRect.X + item.EntireRect.Width >= h_marker
562 && item.EntireRect.Y + item.EntireRect.Height >= v_marker)
571 internal int LastItemIndex {
573 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
574 if (Items[i].EntireRect.Y > v_marker + ClientRectangle.Bottom)
578 return Items.Count - 1;
582 internal int TotalWidth {
583 get { return Math.Max (this.Width, this.layout_wd); }
586 internal int TotalHeight {
587 get { return Math.Max (this.Height, this.layout_ht); }
590 internal void Redraw (bool recalculate)
592 // Avoid calculations when control is being updated
597 CalculateListView (this.alignment);
602 internal Size GetChildColumnSize (int index)
604 Size ret_size = Size.Empty;
605 ColumnHeader col = this.columns [index];
607 if (col.Width == -2) { // autosize = max(items, columnheader)
608 Size size = Size.Ceiling (this.DeviceContext.MeasureString
609 (col.Text, this.Font));
610 ret_size = BiggestItem (index);
611 if (size.Width > ret_size.Width)
614 else { // -1 and all the values < -2 are put under one category
615 ret_size = BiggestItem (index);
616 // fall back to empty columns' width if no subitem is available for a column
617 if (ret_size.IsEmpty) {
618 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
619 if (col.Text.Length > 0)
620 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
621 (col.Text, this.Font)).Height;
623 ret_size.Height = this.Font.Height;
627 // adjust the size for icon and checkbox for 0th column
629 ret_size.Width += (this.CheckBoxSize.Width + 4);
630 if (this.small_image_list != null)
631 ret_size.Width += this.small_image_list.ImageSize.Width;
636 // Returns the size of biggest item text in a column.
637 private Size BiggestItem (int col)
639 Size temp = Size.Empty;
640 Size ret_size = Size.Empty;
642 // 0th column holds the item text, we check the size of
643 // the various subitems falling in that column and get
644 // the biggest one's size.
645 foreach (ListViewItem item in items) {
646 if (col >= item.SubItems.Count)
649 temp = Size.Ceiling (this.DeviceContext.MeasureString
650 (item.SubItems [col].Text, this.Font));
651 if (temp.Width > ret_size.Width)
655 // adjustment for space
656 if (!ret_size.IsEmpty)
662 // Sets the size of the biggest item text as per the view
663 private void CalcTextSize ()
665 // clear the old value
666 text_size = Size.Empty;
668 if (items.Count == 0)
671 text_size = BiggestItem (0);
673 if (view == View.LargeIcon && this.label_wrap) {
674 Size temp = Size.Empty;
675 if (this.check_boxes)
676 temp.Width += 2 * this.CheckBoxSize.Width;
677 if (large_image_list != null)
678 temp.Width += large_image_list.ImageSize.Width;
681 // wrapping is done for two lines only
682 if (text_size.Width > temp.Width) {
683 text_size.Width = temp.Width;
684 text_size.Height *= 2;
687 else if (view == View.List) {
688 // in list view max text shown in determined by the
689 // control width, even if scolling is enabled.
690 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
691 if (this.small_image_list != null)
692 max_wd -= this.small_image_list.ImageSize.Width;
694 if (text_size.Width > max_wd)
695 text_size.Width = max_wd;
698 // we do the default settings, if we have got 0's
699 if (text_size.Height <= 0)
700 text_size.Height = this.Font.Height;
701 if (text_size.Width <= 0)
702 text_size.Width = this.Width;
705 text_size.Width += 4;
706 text_size.Height += 2;
709 private void CalculateScrollBars ()
711 client_area = ClientRectangle;
713 if (!this.scrollable || this.items.Count <= 0) {
714 h_scroll.Visible = false;
715 v_scroll.Visible = false;
719 // making a scroll bar visible might make
720 // other scroll bar visible
721 if (layout_wd > client_area.Right) {
722 h_scroll.Visible = true;
723 if ((layout_ht + h_scroll.Height) > client_area.Bottom) {
724 v_scroll.Visible = true;
726 } else if (layout_ht > client_area.Bottom) {
727 v_scroll.Visible = true;
728 if ((layout_wd + v_scroll.Width) > client_area.Right)
729 h_scroll.Visible = true;
732 if (h_scroll.Visible) {
733 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
734 h_scroll.Minimum = 0;
736 // if v_scroll is visible, adjust the maximum of the
737 // h_scroll to account for the width of v_scroll
738 if (v_scroll.Visible) {
739 h_scroll.Maximum = layout_wd + v_scroll.Width;
740 h_scroll.Width = client_area.Width - v_scroll.Width;
743 h_scroll.Maximum = layout_wd;
744 h_scroll.Width = client_area.Width;
747 h_scroll.LargeChange = client_area.Width;
748 h_scroll.SmallChange = Font.Height;
749 client_area.Height -= h_scroll.Height;
752 // vertical scrollbar
753 if (v_scroll.Visible) {
754 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
755 v_scroll.Minimum = 0;
757 // if h_scroll is visible, adjust the maximum of the
758 // v_scroll to account for the height of h_scroll
759 if (h_scroll.Visible) {
760 v_scroll.Maximum = layout_ht + h_scroll.Height;
761 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
763 v_scroll.Maximum = layout_ht;
764 v_scroll.Height = client_area.Height;
767 v_scroll.LargeChange = client_area.Height;
768 v_scroll.SmallChange = Font.Height;
769 client_area.Width -= v_scroll.Width;
774 // Sets the location of every item on
775 // the ListView as per the view
776 private void CalculateListView (ListViewAlignment align)
778 int current_pos_x = 0; // our x-position marker
779 int current_pos_y = 0; // our y-position marker
782 int max; // max x_pos or y_pos depending on the alignment
783 int current = 0; // current row or column
784 int vertical_spacing = ThemeEngine.Current.ListViewVerticalSpacing;
785 int horizontal_spacing = ThemeEngine.Current.ListViewHorizontalSpacing;
792 // ColumnHeaders are not drawn if headerstyle is none
793 int ht = (this.header_style == ColumnHeaderStyle.None) ?
794 0 : this.Font.Height + 3;
796 if (columns.Count > 0) {
797 foreach (ColumnHeader col in columns) {
798 col.X = current_pos_x;
799 col.Y = current_pos_y;
800 col.CalcColumnHeader ();
801 current_pos_x += col.Wd;
803 this.layout_wd = current_pos_x;
805 // set the position marker for placing items
809 if (items.Count > 0) {
810 foreach (ListViewItem item in items) {
812 item.location.Y = current_pos_y;
813 item.CalcListViewItem ();
814 current_pos_y += item.EntireRect.Height;
816 this.layout_ht = current_pos_y;
818 // some space for bottom gridline
825 vertical_spacing = 0;
826 horizontal_spacing = 0;
827 goto case View.LargeIcon;
830 if (items.Count > 0) {
831 items [0].CalcListViewItem ();
832 item_ht = items [0].EntireRect.Height;
833 item_wd = items [0].EntireRect.Width;
835 // top (default) and snaptogrid alignments are handled same way
836 if (align == ListViewAlignment.Left) {
837 max = client_area.Height;
838 foreach (ListViewItem item in items) {
839 item.location.X = current_pos_x +
842 item.CalcListViewItem ();
843 current_pos_y += item_ht;
845 current ++; // just to know about the last element
846 // we just did the last item
847 if (current == items.Count) {
848 if (max < current_pos_y)
850 current_pos_x = item.EntireRect.Right;
854 // is there enough space for another row ?
855 if ((current_pos_y + vertical_spacing
856 + item_ht) <= client_area.Height)
857 current_pos_y += vertical_spacing;
859 // start another column
860 // make current_pos_y as the
861 // max value and reset
862 // current_pos_y value.
864 current_pos_x += item_wd;
869 // adjust the layout dimensions
870 this.layout_ht = max;
871 this.layout_wd = current_pos_x;
873 else { // other default/top alignment
874 max = client_area.Width;
875 foreach (ListViewItem item in items) {
876 item.location.X = current_pos_x +
879 item.location.Y = current_pos_y;
880 item.CalcListViewItem ();
881 current_pos_x += item_wd;
883 current ++; // just to know about the last element
884 // we just did the last item
885 if (current == items.Count) {
886 if (max < current_pos_x)
888 current_pos_y = item.EntireRect.Bottom;
892 // is there enough space for another column?
893 if ((current_pos_x + horizontal_spacing
894 + item_wd) <= client_area.Width)
898 // make current_pos_x as the
899 // max value and reset
900 // current_pos_x value.
902 current_pos_y += (item_ht +
908 // adjust the layout dimensions
909 this.layout_wd = max;
910 this.layout_ht = current_pos_y;
916 if (items.Count > 0) {
917 items [0].CalcListViewItem ();
918 item_ht = items [0].EntireRect.Height;
919 item_wd = items [0].EntireRect.Width;
921 max = client_area.Height / item_ht;
923 max = 1; // we draw at least one row
925 foreach (ListViewItem item in items) {
926 item.location.X = current_pos_x;
927 item.location.Y = current_pos_y;
928 item.CalcListViewItem ();
930 if (current == max) {
931 current_pos_x += item_wd;
936 current_pos_y += item_ht;
939 // adjust the layout dimensions
940 this.layout_ht = max * item_ht;
941 if (current == 0) // we have fully filled layout
942 this.layout_wd = current_pos_x;
944 this.layout_wd = current_pos_x + item_wd;
949 CalculateScrollBars ();
954 private void ListView_DoubleClick (object sender, EventArgs e)
956 if (this.activation == ItemActivation.Standard
957 && this.ItemActivate != null)
958 this.ItemActivate (this, e);
961 private void ListView_KeyDown (object sender, KeyEventArgs ke)
964 if (ke.Handled || Items.Count == 0)
969 switch (ke.KeyCode) {
971 case Keys.ControlKey:
976 if (focused_item != null && focused_item.Index + 1 < Items.Count) {
977 index = focused_item.Index + 1;
982 index = Items.Count - 1;
991 if (focused_item != null)
992 index = focused_item.Index;
1002 if (focused_item != null)
1003 index = focused_item.Index + 1;
1007 if (index == items.Count)
1013 shift_pressed = true;
1017 if (focused_item != null)
1018 index = focused_item.Index;
1036 items [index].Selected = true;
1037 SetFocusedItem (items [index]);
1038 EnsureVisible (index);
1042 private void ListView_KeyUp (object sender, KeyEventArgs ke)
1045 if (ke.KeyCode == Keys.ControlKey)
1046 this.ctrl_pressed = false;
1048 if (ke.KeyCode == Keys.ShiftKey)
1049 this.shift_pressed = false;
1054 private void ListView_MouseDown (object sender, MouseEventArgs me)
1056 if (items.Count == 0)
1059 Point hit = Point.Empty;
1060 if (this.HeaderStyle != ColumnHeaderStyle.None) {
1061 // take horizontal scrolling into account
1062 hit = new Point (me.X + h_marker, me.Y);
1064 // hit test on columns
1065 if (this.view == View.Details && this.columns.Count > 0) {
1066 foreach (ColumnHeader col in this.columns) {
1067 if (col.Rect.Contains (hit)) {
1068 this.clicked_column = col;
1069 this.Capture = true;
1074 if (this.clicked_column != null) {
1075 this.clicked_column.pressed = true;
1076 this.Redraw (false);
1082 // hit test on items
1083 // we need to take scrolling into account
1084 hit = new Point (me.X + h_marker, me.Y + v_marker);
1085 foreach (ListViewItem item in this.items) {
1086 if (item.CheckRect.Contains (hit)) {
1087 CheckState curr_state = item.Checked ?
1088 CheckState.Checked : CheckState.Unchecked;
1090 item.Checked = false;
1092 item.Checked = true;
1094 CheckState new_state = item.Checked ?
1095 CheckState.Checked : CheckState.Unchecked;
1096 this.Redraw (false);
1098 // Raise the ItemCheck event
1099 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index,
1102 this.OnItemCheck (ice);
1106 if (this.view == View.Details &&
1107 this.FullRowSelect == false) {
1108 if (item.LabelRect.Contains (hit)) {
1109 this.clicked_item = item;
1114 if (item.EntireRect.Contains (hit)) {
1115 this.clicked_item = item;
1121 // set the FocusedItem to be the current clicked_item
1122 SetFocusedItem (clicked_item);
1124 if (this.clicked_item != null) {
1125 this.clicked_item.Selected = true;
1127 this.OnSelectedIndexChanged (new EventArgs ());
1129 this.Redraw (false);
1133 private void ListView_MouseHover (object sender, EventArgs e)
1135 // handle the hover events only when the mouse
1137 if (this.hover_selection == false || this.Capture)
1140 // hit test for the items
1141 Point hit = this.PointToClient (Control.MousePosition);
1142 ListViewItem item = this.GetItemAt (hit.X, hit.Y);
1145 item.Selected = true;
1147 this.OnSelectedIndexChanged (new EventArgs ());
1149 this.Redraw (false);
1153 private void ListView_MouseMove (object sender, MouseEventArgs me)
1155 // Column header is always at the top. It can
1156 // scroll only horizontally. So, we have to take
1157 // only horizontal scrolling into account
1158 Point hit = new Point (me.X + h_marker, me.Y);
1160 // non-null clicked_col means mouse down has happened
1162 if (this.clicked_column != null) {
1163 if (this.clicked_column.pressed == false &&
1164 this.clicked_column.Rect.Contains (hit)) {
1165 this.clicked_column.pressed = true;
1166 this.Redraw (false);
1168 else if (this.clicked_column.pressed &&
1169 ! this.clicked_column.Rect.Contains (hit)) {
1170 this.clicked_column.pressed = false;
1171 this.Redraw (false);
1176 private void ListView_MouseUp (object sender, MouseEventArgs me)
1178 this.Capture = false;
1179 if (items.Count == 0)
1182 Point hit = new Point (me.X, me.Y);
1184 if (this.clicked_column != null) {
1185 if (this.clicked_column.pressed) {
1186 this.clicked_column.pressed = false;
1187 this.Redraw (false);
1189 // Raise the ColumnClick event
1190 this.OnColumnClick (new ColumnClickEventArgs
1191 (this.clicked_column.Index));
1195 // Raise the ItemActivate event
1196 Rectangle rect = Rectangle.Empty;
1197 if (this.clicked_item != null) {
1198 if (this.view == View.Details && !this.full_row_select)
1199 rect = this.clicked_item.LabelRect;
1201 rect = this.clicked_item.EntireRect;
1203 // We handle double click in a separate handler
1204 if (this.activation != ItemActivation.Standard &&
1205 rect.Contains (hit)) {
1206 if (this.activation == ItemActivation.OneClick)
1207 this.ItemActivate (this, EventArgs.Empty);
1209 // ItemActivate is raised on the second click on the same item
1210 else if (this.activation == ItemActivation.TwoClick) {
1211 if (this.last_clicked_item == this.clicked_item) {
1212 this.ItemActivate (this, EventArgs.Empty);
1213 this.last_clicked_item = null;
1216 this.last_clicked_item = this.clicked_item;
1221 this.clicked_column = null;
1222 this.clicked_item = null;
1225 private void ListView_Paint (object sender, PaintEventArgs pe)
1227 if (this.Width <= 0 || this.Height <= 0 ||
1228 this.Visible == false || this.updating == true)
1231 CalculateScrollBars ();
1233 ThemeEngine.Current.DrawListView (pe.Graphics,
1234 pe.ClipRectangle, this);
1236 // Raise the Paint event
1241 private void ListView_SizeChanged (object sender, EventArgs e)
1243 CalculateListView (alignment);
1246 public void SetFocusedItem (ListViewItem item)
1248 if (focused_item != null)
1249 focused_item.Focused = false;
1252 item.Focused = true;
1254 focused_item = item;
1257 private void HorizontalScroller (object sender, EventArgs e)
1259 // Avoid unnecessary flickering, when button is
1260 // kept pressed at the end
1261 if (h_marker != h_scroll.Value) {
1263 int pixels = h_marker - h_scroll.Value;
1264 Rectangle area = client_area;
1266 if (View == View.Details && Columns.Count > 0) {
1267 area.Y += Columns[0].Ht;
1268 area.Height -= Columns[0].Ht;
1271 h_marker = h_scroll.Value;
1272 XplatUI.ScrollWindow (Handle, area, pixels, 0, false);
1276 private void VerticalScroller (object sender, EventArgs e)
1278 // Avoid unnecessary flickering, when button is
1279 // kept pressed at the end
1280 if (v_marker != v_scroll.Value) {
1281 int pixels = v_marker - v_scroll.Value;
1282 Rectangle area = client_area;
1284 if (View == View.Details && Columns.Count > 0) {
1285 area.Y += Columns[0].Ht;
1286 area.Height -= Columns[0].Ht;
1289 v_marker = v_scroll.Value;
1290 XplatUI.ScrollWindow (Handle, area, 0, pixels, false);
1293 #endregion // Internal Methods Properties
1295 #region Protected Methods
1296 protected override void CreateHandle ()
1298 base.CreateHandle ();
1301 protected override void Dispose (bool disposing)
1304 h_scroll.Dispose ();
1305 v_scroll.Dispose ();
1307 if (large_image_list != null)
1308 large_image_list.Dispose ();
1310 if (small_image_list != null)
1311 small_image_list.Dispose ();
1313 if (state_image_list != null)
1314 state_image_list.Dispose ();
1317 base.Dispose (disposing);
1320 protected override bool IsInputKey (Keys keyData)
1337 return base.IsInputKey (keyData);
1340 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1342 if (AfterLabelEdit != null)
1343 AfterLabelEdit (this, e);
1346 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1348 if (BeforeLabelEdit != null)
1349 BeforeLabelEdit (this, e);
1352 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1354 if (ColumnClick != null)
1355 ColumnClick (this, e);
1358 protected override void OnEnabledChanged (EventArgs e)
1360 base.OnEnabledChanged (e);
1363 protected override void OnFontChanged (EventArgs e)
1365 base.OnFontChanged (e);
1369 protected override void OnHandleCreated (EventArgs e)
1371 base.OnHandleCreated (e);
1373 Controls.AddImplicit (this.v_scroll);
1374 Controls.AddImplicit (this.h_scroll);
1378 protected override void OnHandleDestroyed (EventArgs e)
1380 base.OnHandleDestroyed (e);
1383 protected virtual void OnItemActivate (EventArgs e)
1385 if (ItemActivate != null)
1386 ItemActivate (this, e);
1389 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1391 if (ItemCheck != null)
1392 ItemCheck (this, ice);
1395 protected virtual void OnItemDrag (ItemDragEventArgs e)
1397 if (ItemDrag != null)
1401 protected virtual void OnSelectedIndexChanged (EventArgs e)
1403 if (SelectedIndexChanged != null)
1404 SelectedIndexChanged (this, e);
1407 protected override void OnSystemColorsChanged (EventArgs e)
1409 base.OnSystemColorsChanged (e);
1412 protected void RealizeProperties ()
1417 protected void UpdateExtendedStyles ()
1422 protected override void WndProc (ref Message m)
1424 base.WndProc (ref m);
1426 #endregion // Protected Methods
1428 #region Public Instance Methods
1429 public void ArrangeIcons ()
1431 ArrangeIcons (this.alignment);
1434 public void ArrangeIcons (ListViewAlignment alignment)
1436 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1437 if (view == View.LargeIcon || view == View.SmallIcon) {
1438 this.CalculateListView (alignment);
1439 // we have done the calculations already
1440 this.Redraw (false);
1444 public void BeginUpdate ()
1446 // flag to avoid painting
1450 public void Clear ()
1452 SetFocusedItem (null);
1458 public void EndUpdate ()
1460 // flag to avoid painting
1463 // probably, now we need a redraw with recalculations
1467 public void EnsureVisible (int index)
1469 if (index < 0 || index >= this.items.Count || this.scrollable == false)
1472 // dimensions of visible area
1473 int view_wd = client_area.Width;
1474 int view_ht = client_area.Height;
1475 // visible area is decided by the h_marker and v_marker
1476 Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1478 // an item's bounding rect
1479 Rectangle rect = this.items [index].EntireRect;
1481 // we don't need to do anything if item is visible.
1482 // visible area is represented by (0,0,view_wd,view_ht)
1483 if (view_rect.Contains (rect))
1486 // Scroll Left or Up
1487 if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1488 if (rect.Left < view_rect.Left)
1489 this.h_scroll.Value -= (view_rect.Left - rect.Left);
1490 if (rect.Top < view_rect.Top)
1491 this.v_scroll.Value -= (view_rect.Top - rect.Top);
1493 // Scroll Right or Down
1495 if (rect.Right > view_rect.Right)
1496 this.h_scroll.Value += (rect.Right - view_rect.Right);
1497 if (rect.Bottom > view_rect.Bottom)
1498 this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1502 public ListViewItem GetItemAt (int x, int y)
1504 foreach (ListViewItem item in items) {
1505 if (item.Bounds.Contains (x, y))
1511 public Rectangle GetItemRect (int index)
1513 return GetItemRect (index, ItemBoundsPortion.Entire);
1516 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1518 if (index < 0 || index >= items.Count)
1519 throw new IndexOutOfRangeException ("Invalid Index");
1521 return items [index].GetBounds (portion);
1526 if (sort_order != SortOrder.None)
1527 items.list.Sort (item_sorter);
1529 if (sort_order == SortOrder.Descending)
1530 items.list.Reverse ();
1535 public override string ToString ()
1537 int count = this.Items.Count;
1540 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1542 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1544 #endregion // Public Instance Methods
1548 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1550 internal ArrayList list;
1551 private ListView owner;
1553 #region Public Constructor
1554 public CheckedIndexCollection (ListView owner)
1556 list = new ArrayList ();
1559 #endregion // Public Constructor
1561 #region Public Properties
1563 public virtual int Count {
1564 get { return list.Count; }
1567 public virtual bool IsReadOnly {
1568 get { return true; }
1571 public int this [int index] {
1573 if (index < 0 || index >= list.Count)
1574 throw new ArgumentOutOfRangeException ("Index out of range.");
1575 return (int) list [index];
1579 bool ICollection.IsSynchronized {
1580 get { return list.IsSynchronized; }
1583 object ICollection.SyncRoot {
1584 get { return list.SyncRoot; }
1587 bool IList.IsFixedSize {
1588 get { return list.IsFixedSize; }
1591 object IList.this [int index] {
1592 get { return this [index]; }
1593 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1595 #endregion // Public Properties
1597 #region Public Methods
1598 public bool Contains (int checkedIndex)
1600 return list.Contains (checkedIndex);
1603 public virtual IEnumerator GetEnumerator ()
1605 return list.GetEnumerator ();
1608 void ICollection.CopyTo (Array dest, int index)
1610 list.CopyTo (dest, index);
1613 int IList.Add (object value)
1615 throw new NotSupportedException ("Add operation is not supported.");
1620 throw new NotSupportedException ("Clear operation is not supported.");
1623 bool IList.Contains (object checkedIndex)
1625 return list.Contains (checkedIndex);
1628 int IList.IndexOf (object checkedIndex)
1630 return list.IndexOf (checkedIndex);
1633 void IList.Insert (int index, object value)
1635 throw new NotSupportedException ("Insert operation is not supported.");
1638 void IList.Remove (object value)
1640 throw new NotSupportedException ("Remove operation is not supported.");
1643 void IList.RemoveAt (int index)
1645 throw new NotSupportedException ("RemoveAt operation is not supported.");
1648 public int IndexOf (int checkedIndex)
1650 return list.IndexOf (checkedIndex);
1652 #endregion // Public Methods
1654 } // CheckedIndexCollection
1656 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1658 internal ArrayList list;
1659 private ListView owner;
1661 #region Public Constructor
1662 public CheckedListViewItemCollection (ListView owner)
1664 list = new ArrayList ();
1667 #endregion // Public Constructor
1669 #region Public Properties
1671 public virtual int Count {
1672 get { return list.Count; }
1675 public virtual bool IsReadOnly {
1676 get { return true; }
1679 public ListViewItem this [int index] {
1681 if (index < 0 || index >= list.Count)
1682 throw new ArgumentOutOfRangeException ("Index out of range.");
1683 return (ListViewItem) list [index];
1687 bool ICollection.IsSynchronized {
1688 get { return list.IsSynchronized; }
1691 object ICollection.SyncRoot {
1692 get { return list.SyncRoot; }
1695 bool IList.IsFixedSize {
1696 get { return list.IsFixedSize; }
1699 object IList.this [int index] {
1700 get { return this [index]; }
1701 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1703 #endregion // Public Properties
1705 #region Public Methods
1706 public bool Contains (ListViewItem item)
1708 return list.Contains (item);
1711 public virtual void CopyTo (Array dest, int index)
1713 list.CopyTo (dest, index);
1716 public virtual IEnumerator GetEnumerator ()
1718 return list.GetEnumerator ();
1721 int IList.Add (object value)
1723 throw new NotSupportedException ("Add operation is not supported.");
1728 throw new NotSupportedException ("Clear operation is not supported.");
1731 bool IList.Contains (object item)
1733 return list.Contains (item);
1736 int IList.IndexOf (object item)
1738 return list.IndexOf (item);
1741 void IList.Insert (int index, object value)
1743 throw new NotSupportedException ("Insert operation is not supported.");
1746 void IList.Remove (object value)
1748 throw new NotSupportedException ("Remove operation is not supported.");
1751 void IList.RemoveAt (int index)
1753 throw new NotSupportedException ("RemoveAt operation is not supported.");
1756 public int IndexOf (ListViewItem item)
1758 return list.IndexOf (item);
1760 #endregion // Public Methods
1762 } // CheckedListViewItemCollection
1764 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1766 internal ArrayList list;
1767 private ListView owner;
1769 #region Public Constructor
1770 public ColumnHeaderCollection (ListView owner)
1772 list = new ArrayList ();
1775 #endregion // Public Constructor
1777 #region Public Properties
1779 public virtual int Count {
1780 get { return list.Count; }
1783 public virtual bool IsReadOnly {
1784 get { return false; }
1787 public virtual ColumnHeader this [int index] {
1789 if (index < 0 || index >= list.Count)
1790 throw new ArgumentOutOfRangeException ("Index out of range.");
1791 return (ColumnHeader) list [index];
1795 bool ICollection.IsSynchronized {
1796 get { return list.IsSynchronized; }
1799 object ICollection.SyncRoot {
1800 get { return list.SyncRoot; }
1803 bool IList.IsFixedSize {
1804 get { return list.IsFixedSize; }
1807 object IList.this [int index] {
1808 get { return this [index]; }
1809 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1811 #endregion // Public Properties
1813 #region Public Methods
1814 public virtual int Add (ColumnHeader value)
1817 value.owner = this.owner;
1818 idx = list.Add (value);
1819 owner.Redraw (true);
1823 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1825 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1826 this.Add (colHeader);
1830 public virtual void AddRange (ColumnHeader [] values)
1832 foreach (ColumnHeader colHeader in values) {
1833 colHeader.owner = this.owner;
1837 owner.Redraw (true);
1840 public virtual void Clear ()
1843 owner.Redraw (true);
1846 public bool Contains (ColumnHeader value)
1848 return list.Contains (value);
1851 public virtual IEnumerator GetEnumerator ()
1853 return list.GetEnumerator ();
1856 void ICollection.CopyTo (Array dest, int index)
1858 list.CopyTo (dest, index);
1861 int IList.Add (object value)
1863 if (! (value is ColumnHeader)) {
1864 throw new ArgumentException ("Not of type ColumnHeader", "value");
1867 return this.Add ((ColumnHeader) value);
1870 bool IList.Contains (object value)
1872 if (! (value is ColumnHeader)) {
1873 throw new ArgumentException ("Not of type ColumnHeader", "value");
1876 return this.Contains ((ColumnHeader) value);
1879 int IList.IndexOf (object value)
1881 if (! (value is ColumnHeader)) {
1882 throw new ArgumentException ("Not of type ColumnHeader", "value");
1885 return this.IndexOf ((ColumnHeader) value);
1888 void IList.Insert (int index, object value)
1890 if (! (value is ColumnHeader)) {
1891 throw new ArgumentException ("Not of type ColumnHeader", "value");
1894 this.Insert (index, (ColumnHeader) value);
1897 void IList.Remove (object value)
1899 if (! (value is ColumnHeader)) {
1900 throw new ArgumentException ("Not of type ColumnHeader", "value");
1903 this.Remove ((ColumnHeader) value);
1906 public int IndexOf (ColumnHeader value)
1908 return list.IndexOf (value);
1911 public void Insert (int index, ColumnHeader value)
1913 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
1914 // but it's really only greater.
1915 if (index < 0 || index > list.Count)
1916 throw new ArgumentOutOfRangeException ("Index out of range.");
1918 value.owner = this.owner;
1919 list.Insert (index, value);
1920 owner.Redraw (true);
1923 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1925 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1926 this.Insert (index, colHeader);
1929 public virtual void Remove (ColumnHeader column)
1931 // TODO: Update Column internal index ?
1932 list.Remove (column);
1933 owner.Redraw (true);
1936 public virtual void RemoveAt (int index)
1938 if (index < 0 || index >= list.Count)
1939 throw new ArgumentOutOfRangeException ("Index out of range.");
1941 // TODO: Update Column internal index ?
1942 list.RemoveAt (index);
1943 owner.Redraw (true);
1945 #endregion // Public Methods
1948 } // ColumnHeaderCollection
1950 public class ListViewItemCollection : IList, ICollection, IEnumerable
1952 internal ArrayList list;
1953 private ListView owner;
1955 #region Public Constructor
1956 public ListViewItemCollection (ListView owner)
1958 list = new ArrayList ();
1961 #endregion // Public Constructor
1963 #region Public Properties
1965 public virtual int Count {
1966 get { return list.Count; }
1969 public virtual bool IsReadOnly {
1970 get { return false; }
1973 public virtual ListViewItem this [int displayIndex] {
1975 if (displayIndex < 0 || displayIndex >= list.Count)
1976 throw new ArgumentOutOfRangeException ("Index out of range.");
1977 return (ListViewItem) list [displayIndex];
1981 if (displayIndex < 0 || displayIndex >= list.Count)
1982 throw new ArgumentOutOfRangeException ("Index out of range.");
1984 if (list.Contains (value))
1985 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1987 value.owner = this.owner;
1988 list [displayIndex] = value;
1990 owner.Redraw (true);
1994 bool ICollection.IsSynchronized {
1995 get { return list.IsSynchronized; }
1998 object ICollection.SyncRoot {
1999 get { return list.SyncRoot; }
2002 bool IList.IsFixedSize {
2003 get { return list.IsFixedSize; }
2006 object IList.this [int index] {
2007 get { return this [index]; }
2009 if (value is ListViewItem)
2010 this [index] = (ListViewItem) value;
2012 this [index] = new ListViewItem (value.ToString ());
2015 #endregion // Public Properties
2017 #region Public Methods
2018 public virtual ListViewItem Add (ListViewItem value)
2020 if (list.Contains (value))
2021 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2023 value.owner = this.owner;
2026 if (owner.Sorting != SortOrder.None)
2029 owner.Redraw (true);
2034 public virtual ListViewItem Add (string text)
2036 ListViewItem item = new ListViewItem (text);
2037 return this.Add (item);
2040 public virtual ListViewItem Add (string text, int imageIndex)
2042 ListViewItem item = new ListViewItem (text, imageIndex);
2043 return this.Add (item);
2046 public void AddRange (ListViewItem [] values)
2050 foreach (ListViewItem item in values) {
2051 item.owner = this.owner;
2055 if (owner.Sorting != SortOrder.None)
2058 owner.Redraw (true);
2061 public virtual void Clear ()
2066 public bool Contains (ListViewItem item)
2068 return list.Contains (item);
2071 public virtual void CopyTo (Array dest, int index)
2073 list.CopyTo (dest, index);
2076 public virtual IEnumerator GetEnumerator ()
2078 return list.GetEnumerator ();
2081 int IList.Add (object item)
2086 if (item is ListViewItem) {
2087 li = (ListViewItem) item;
2088 if (list.Contains (li))
2089 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2092 li = new ListViewItem (item.ToString ());
2094 li.owner = this.owner;
2095 result = list.Add (li);
2096 owner.Redraw (true);
2101 bool IList.Contains (object item)
2103 return list.Contains (item);
2106 int IList.IndexOf (object item)
2108 return list.IndexOf (item);
2111 void IList.Insert (int index, object item)
2113 if (item is ListViewItem)
2114 this.Insert (index, (ListViewItem) item);
2116 this.Insert (index, item.ToString ());
2119 void IList.Remove (object item)
2121 if (list.Contains (item)) {
2123 owner.Redraw (true);
2127 public int IndexOf (ListViewItem item)
2129 return list.IndexOf (item);
2132 public ListViewItem Insert (int index, ListViewItem item)
2134 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2135 // but it's really only greater.
2136 if (index < 0 || index > list.Count)
2137 throw new ArgumentOutOfRangeException ("Index out of range.");
2139 if (list.Contains (item))
2140 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2142 item.owner = this.owner;
2143 list.Insert (index, item);
2144 owner.Redraw (true);
2148 public ListViewItem Insert (int index, string text)
2150 return this.Insert (index, new ListViewItem (text));
2153 public ListViewItem Insert (int index, string text, int imageIndex)
2155 return this.Insert (index, new ListViewItem (text, imageIndex));
2158 public virtual void Remove (ListViewItem item)
2160 if (list.Contains (item)) {
2162 owner.Redraw (true);
2166 public virtual void RemoveAt (int index)
2168 if (index < 0 || index >= list.Count)
2169 throw new ArgumentOutOfRangeException ("Index out of range.");
2171 list.RemoveAt (index);
2172 owner.Redraw (false);
2174 #endregion // Public Methods
2176 } // ListViewItemCollection
2178 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2180 internal ArrayList list;
2181 private ListView owner;
2183 #region Public Constructor
2184 public SelectedIndexCollection (ListView owner)
2186 list = new ArrayList ();
2189 #endregion // Public Constructor
2191 #region Public Properties
2193 public virtual int Count {
2194 get { return list.Count; }
2197 public virtual bool IsReadOnly {
2198 get { return true; }
2201 public int this [int index] {
2203 if (index < 0 || index >= list.Count)
2204 throw new ArgumentOutOfRangeException ("Index out of range.");
2205 return (int) list [index];
2209 bool ICollection.IsSynchronized {
2210 get { return list.IsSynchronized; }
2213 object ICollection.SyncRoot {
2214 get { return list.SyncRoot; }
2217 bool IList.IsFixedSize {
2218 get { return list.IsFixedSize; }
2221 object IList.this [int index] {
2222 get { return this [index]; }
2223 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2225 #endregion // Public Properties
2227 #region Public Methods
2228 public bool Contains (int selectedIndex)
2230 return list.Contains (selectedIndex);
2233 public virtual void CopyTo (Array dest, int index)
2235 list.CopyTo (dest, index);
2238 public virtual IEnumerator GetEnumerator ()
2240 return list.GetEnumerator ();
2243 int IList.Add (object value)
2245 throw new NotSupportedException ("Add operation is not supported.");
2250 throw new NotSupportedException ("Clear operation is not supported.");
2253 bool IList.Contains (object selectedIndex)
2255 return list.Contains (selectedIndex);
2258 int IList.IndexOf (object selectedIndex)
2260 return list.IndexOf (selectedIndex);
2263 void IList.Insert (int index, object value)
2265 throw new NotSupportedException ("Insert operation is not supported.");
2268 void IList.Remove (object value)
2270 throw new NotSupportedException ("Remove operation is not supported.");
2273 void IList.RemoveAt (int index)
2275 throw new NotSupportedException ("RemoveAt operation is not supported.");
2278 public int IndexOf (int selectedIndex)
2280 return list.IndexOf (selectedIndex);
2282 #endregion // Public Methods
2284 } // SelectedIndexCollection
2286 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2288 internal ArrayList list;
2289 private ListView owner;
2291 #region Public Constructor
2292 public SelectedListViewItemCollection (ListView owner)
2294 list = new ArrayList ();
2297 #endregion // Public Constructor
2299 #region Public Properties
2301 public virtual int Count {
2302 get { return list.Count; }
2305 public virtual bool IsReadOnly {
2306 get { return true; }
2309 public ListViewItem this [int index] {
2311 if (index < 0 || index >= list.Count)
2312 throw new ArgumentOutOfRangeException ("Index out of range.");
2313 return (ListViewItem) list [index];
2317 bool ICollection.IsSynchronized {
2318 get { return list.IsSynchronized; }
2321 object ICollection.SyncRoot {
2322 get { return list.SyncRoot; }
2325 bool IList.IsFixedSize {
2326 get { return list.IsFixedSize; }
2329 object IList.this [int index] {
2330 get { return this [index]; }
2331 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2333 #endregion // Public Properties
2335 #region Public Methods
2336 public virtual void Clear ()
2338 // mark the items as unselected before clearing the list
2339 for (int i = 0; i < list.Count; i++)
2340 ((ListViewItem) list [i]).selected = false;
2345 owner.Invalidate ();
2348 public bool Contains (ListViewItem item)
2350 return list.Contains (item);
2353 public virtual void CopyTo (Array dest, int index)
2355 list.CopyTo (dest, index);
2358 public virtual IEnumerator GetEnumerator ()
2360 return list.GetEnumerator ();
2363 int IList.Add (object value)
2365 throw new NotSupportedException ("Add operation is not supported.");
2368 bool IList.Contains (object item)
2370 return list.Contains (item);
2373 int IList.IndexOf (object item)
2375 return list.IndexOf (item);
2378 void IList.Insert (int index, object value)
2380 throw new NotSupportedException ("Insert operation is not supported.");
2383 void IList.Remove (object value)
2385 throw new NotSupportedException ("Remove operation is not supported.");
2388 void IList.RemoveAt (int index)
2390 throw new NotSupportedException ("RemoveAt operation is not supported.");
2393 public int IndexOf (ListViewItem item)
2395 return list.IndexOf (item);
2397 #endregion // Public Methods
2399 } // SelectedListViewItemCollection
2401 #endregion // Subclasses