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, "System.ComponentModel.Design.IDesigner")]
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 scrollable = true;
81 private SelectedIndexCollection selected_indices;
82 private SelectedListViewItemCollection selected_items;
83 private SortOrder sort_order = SortOrder.None;
84 private ImageList state_image_list;
85 private bool updating = false;
86 private View view = View.LargeIcon;
87 private int layout_wd; // We might draw more than our client area
88 private int layout_ht; // therefore we need to have these two.
89 //private TextBox editor; // Used for editing an item text
90 private ScrollBar h_scroll; // used for scrolling horizontally
91 private ScrollBar v_scroll; // used for scrolling vertically
92 private int h_marker; // Position markers for scrolling
96 internal ImageList large_image_list;
97 internal ImageList small_image_list;
98 internal Size text_size = Size.Empty;
101 public event LabelEditEventHandler AfterLabelEdit;
104 [EditorBrowsable (EditorBrowsableState.Never)]
105 public new event EventHandler BackgroundImageChanged;
107 public event LabelEditEventHandler BeforeLabelEdit;
108 public event ColumnClickEventHandler ColumnClick;
109 public event EventHandler ItemActivate;
110 public event ItemCheckEventHandler ItemCheck;
111 public event ItemDragEventHandler ItemDrag;
114 [EditorBrowsable (EditorBrowsableState.Never)]
115 public new event PaintEventHandler Paint;
117 public event EventHandler SelectedIndexChanged;
120 [EditorBrowsable (EditorBrowsableState.Never)]
121 public new event EventHandler TextChanged;
124 #region Public Constructors
127 background_color = ThemeEngine.Current.ColorWindow;
128 checked_indices = new CheckedIndexCollection (this);
129 checked_items = new CheckedListViewItemCollection (this);
130 columns = new ColumnHeaderCollection (this);
131 foreground_color = SystemColors.WindowText;
132 items = new ListViewItemCollection (this);
133 selected_indices = new SelectedIndexCollection (this);
134 selected_items = new SelectedListViewItemCollection (this);
136 border_style = BorderStyle.Fixed3D;
138 // we are mostly scrollable
139 h_scroll = new HScrollBar ();
140 v_scroll = new VScrollBar ();
141 h_marker = v_marker = 0;
143 // scroll bars are disabled initially
144 h_scroll.Visible = false;
145 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
146 v_scroll.Visible = false;
147 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
150 base.DoubleClick += new EventHandler(ListView_DoubleClick);
151 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
152 base.KeyUp += new KeyEventHandler(ListView_KeyUp);
153 base.MouseDown += new MouseEventHandler(ListView_MouseDown);
154 base.MouseHover += new EventHandler(ListView_MouseHover);
155 base.MouseUp += new MouseEventHandler(ListView_MouseUp);
156 base.MouseMove += new MouseEventHandler(ListView_MouseMove);
157 base.Paint += new PaintEventHandler (ListView_Paint);
158 SizeChanged += new EventHandler (ListView_SizeChanged);
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);
584 internal Size GetChildColumnSize (int index)
586 Size ret_size = Size.Empty;
587 ColumnHeader col = this.columns [index];
589 if (col.Width == -2) { // autosize = max(items, columnheader)
590 Size size = Size.Ceiling (this.DeviceContext.MeasureString
591 (col.Text, this.Font));
592 ret_size = BiggestItem (index);
593 if (size.Width > ret_size.Width)
596 else { // -1 and all the values < -2 are put under one category
597 ret_size = BiggestItem (index);
598 // fall back to empty columns' width if no subitem is available for a column
599 if (ret_size.IsEmpty) {
600 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
601 if (col.Text.Length > 0)
602 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
603 (col.Text, this.Font)).Height;
605 ret_size.Height = this.Font.Height;
609 // adjust the size for icon and checkbox for 0th column
611 ret_size.Width += (this.CheckBoxSize.Width + 4);
612 if (this.small_image_list != null)
613 ret_size.Width += this.small_image_list.ImageSize.Width;
618 // Returns the size of biggest item text in a column.
619 private Size BiggestItem (int col)
621 Size temp = Size.Empty;
622 Size ret_size = Size.Empty;
624 // 0th column holds the item text, we check the size of
625 // the various subitems falling in that column and get
626 // the biggest one's size.
627 foreach (ListViewItem item in items) {
628 if (col >= item.SubItems.Count)
631 temp = Size.Ceiling (this.DeviceContext.MeasureString
632 (item.SubItems [col].Text, this.Font));
633 if (temp.Width > ret_size.Width)
637 // adjustment for space
638 if (!ret_size.IsEmpty)
644 // Sets the size of the biggest item text as per the view
645 private void CalcTextSize ()
647 // clear the old value
648 text_size = Size.Empty;
650 if (items.Count == 0)
653 text_size = BiggestItem (0);
655 if (view == View.LargeIcon && this.label_wrap) {
656 Size temp = Size.Empty;
657 if (this.check_boxes)
658 temp.Width += 2 * this.CheckBoxSize.Width;
659 if (large_image_list != null)
660 temp.Width += large_image_list.ImageSize.Width;
663 // wrapping is done for two lines only
664 if (text_size.Width > temp.Width) {
665 text_size.Width = temp.Width;
666 text_size.Height *= 2;
669 else if (view == View.List) {
670 // in list view max text shown in determined by the
671 // control width, even if scolling is enabled.
672 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
673 if (this.small_image_list != null)
674 max_wd -= this.small_image_list.ImageSize.Width;
676 if (text_size.Width > max_wd)
677 text_size.Width = max_wd;
680 // we do the default settings, if we have got 0's
681 if (text_size.Height <= 0)
682 text_size.Height = this.Font.Height;
683 if (text_size.Width <= 0)
684 text_size.Width = this.Width;
687 text_size.Width += 4;
688 text_size.Height += 2;
691 private void CalculateScrollBars ()
693 if (!this.scrollable || this.items.Count <= 0) {
694 h_scroll.Visible = false;
695 v_scroll.Visible = false;
699 // making a scroll bar visible might make
700 // other scroll bar visible
701 if (layout_wd > this.Width) {
702 h_scroll.Visible = true;
703 if ((layout_ht + h_scroll.Height) > Height)
704 v_scroll.Visible = true;
705 } else if (layout_ht > Height) {
706 v_scroll.Visible = true;
707 if ((layout_wd + v_scroll.Width) > Width)
708 h_scroll.Visible = true;
711 if (h_scroll.Visible) {
712 h_scroll.Location = new Point (0, Height - h_scroll.Height);
713 h_scroll.Minimum = 0;
715 // if v_scroll is visible, adjust the maximum of the
716 // h_scroll to account for the width of v_scroll
717 if (v_scroll.Visible) {
718 h_scroll.Maximum = layout_wd + v_scroll.Width;
719 h_scroll.Width = Width - v_scroll.Width;
722 h_scroll.Maximum = layout_wd;
723 h_scroll.Width = Width;
726 h_scroll.LargeChange = Width;
727 h_scroll.SmallChange = Font.Height;
730 // vertical scrollbar
731 if (v_scroll.Visible) {
732 v_scroll.Location = new Point (Width - v_scroll.Width, 0);
733 v_scroll.Minimum = 0;
735 // if h_scroll is visible, adjust the maximum of the
736 // v_scroll to account for the height of h_scroll
737 if (h_scroll.Visible) {
738 v_scroll.Maximum = layout_ht + h_scroll.Height;
739 v_scroll.Height = Height - h_scroll.Height;
741 v_scroll.Maximum = layout_ht;
742 v_scroll.Height = Height;
745 v_scroll.LargeChange = Height;
746 v_scroll.SmallChange = Font.Height;
750 // Sets the location of every item on
751 // the ListView as per the view
752 private void CalculateListView (ListViewAlignment align)
754 int current_pos_x = 0; // our x-position marker
755 int current_pos_y = 0; // our y-position marker
758 int max; // max x_pos or y_pos depending on the alignment
759 int current = 0; // current row or column
760 int vertical_spacing = ThemeEngine.Current.ListViewVerticalSpacing;
761 int horizontal_spacing = ThemeEngine.Current.ListViewHorizontalSpacing;
768 // ColumnHeaders are not drawn if headerstyle is none
769 int ht = (this.header_style == ColumnHeaderStyle.None) ?
770 2 : this.Font.Height + 5;
771 if (columns.Count > 0) {
772 foreach (ColumnHeader col in columns) {
773 col.X = current_pos_x;
775 col.CalcColumnHeader ();
776 current_pos_x += col.Wd;
778 this.layout_wd = current_pos_x;
780 // set the position marker for placing items
784 if (items.Count > 0) {
785 foreach (ListViewItem item in items) {
787 item.location.Y = current_pos_y;
788 item.CalcListViewItem ();
789 current_pos_y += item.EntireRect.Height;
791 this.layout_ht = current_pos_y;
793 // some space for bottom gridline
800 vertical_spacing = 0;
801 horizontal_spacing = 0;
802 goto case View.LargeIcon;
805 if (items.Count > 0) {
806 items [0].CalcListViewItem ();
807 item_ht = items [0].EntireRect.Height;
808 item_wd = items [0].EntireRect.Width;
810 // top (default) and snaptogrid alignments are handled same way
811 if (align == ListViewAlignment.Left) {
813 foreach (ListViewItem item in items) {
814 item.location.X = current_pos_x +
816 item.location.Y = current_pos_y;
817 item.CalcListViewItem ();
818 current_pos_y += item_ht;
820 current ++; // just to know about the last element
821 // we just did the last item
822 if (current == items.Count) {
823 if (max < current_pos_y)
825 current_pos_x = item.EntireRect.Right;
829 // is there enough space for another row ?
830 if ((current_pos_y + vertical_spacing
831 + item_ht) <= this.Height)
832 current_pos_y += vertical_spacing;
834 // start another column
835 // make current_pos_y as the
836 // max value and reset
837 // current_pos_y value.
839 current_pos_x += item_wd;
844 // adjust the layout dimensions
845 this.layout_ht = max;
846 this.layout_wd = current_pos_x;
848 else { // other default/top alignment
850 foreach (ListViewItem item in items) {
851 item.location.X = current_pos_x +
854 item.location.Y = current_pos_y;
855 item.CalcListViewItem ();
856 current_pos_x += item_wd;
858 current ++; // just to know about the last element
859 // we just did the last item
860 if (current == items.Count) {
861 if (max < current_pos_x)
863 current_pos_y = item.EntireRect.Bottom;
867 // is there enough space for another column?
868 if ((current_pos_x + horizontal_spacing
869 + item_wd) <= this.Width)
873 // make current_pos_x as the
874 // max value and reset
875 // current_pos_x value.
877 current_pos_y += (item_ht +
883 // adjust the layout dimensions
884 this.layout_wd = max;
885 this.layout_ht = current_pos_y;
891 if (items.Count > 0) {
892 items [0].CalcListViewItem ();
893 item_ht = items [0].EntireRect.Height;
894 item_wd = items [0].EntireRect.Width;
896 max = this.Height / item_ht;
898 max = 1; // we draw at least one row
900 foreach (ListViewItem item in items) {
901 item.location.X = current_pos_x;
902 item.location.Y = current_pos_y;
903 item.CalcListViewItem ();
905 if (current == max) {
906 current_pos_x += item_wd;
911 current_pos_y += item_ht;
914 // adjust the layout dimensions
915 this.layout_ht = max * item_ht;
916 if (current == 0) // we have fully filled layout
917 this.layout_wd = current_pos_x;
919 this.layout_wd = current_pos_x + item_wd;
924 CalculateScrollBars ();
929 private void ListView_DoubleClick (object sender, EventArgs e)
931 if (this.activation == ItemActivation.Standard
932 && this.ItemActivate != null)
933 this.ItemActivate (this, e);
936 private void ListView_KeyDown (object sender, KeyEventArgs ke)
944 switch (ke.KeyCode) {
946 case Keys.ControlKey:
947 this.ctrl_pressed = true;
955 this.v_scroll.Value = this.v_scroll.Maximum;
959 this.v_scroll.Value = this.v_scroll.Minimum;
964 if (this.last_clicked_item != null)
965 index = this.last_clicked_item.Index;
972 this.last_clicked_item = this.items [index];
973 this.last_clicked_item.Selected = true;
974 this.EnsureVisible (index);
978 if (this.last_clicked_item != null)
979 index = this.last_clicked_item.Index + 1;
983 if (index == this.items.Count)
986 this.last_clicked_item = this.items [index];
987 this.last_clicked_item.Selected = true;
988 this.EnsureVisible (index);
992 this.shift_pressed = true;
1005 private void ListView_KeyUp (object sender, KeyEventArgs ke)
1008 if (ke.KeyCode == Keys.ControlKey)
1009 this.ctrl_pressed = false;
1011 if (ke.KeyCode == Keys.ShiftKey)
1012 this.shift_pressed = false;
1017 private void ListView_MouseDown (object sender, MouseEventArgs me)
1019 if (items.Count == 0)
1022 Point hit = Point.Empty;
1023 if (this.HeaderStyle != ColumnHeaderStyle.None) {
1024 // take horizontal scrolling into account
1025 hit = new Point (me.X + h_marker, me.Y);
1027 // hit test on columns
1028 if (this.view == View.Details && this.columns.Count > 0) {
1029 foreach (ColumnHeader col in this.columns) {
1030 if (col.Rect.Contains (hit)) {
1031 this.clicked_column = col;
1032 this.Capture = true;
1037 if (this.clicked_column != null) {
1038 this.clicked_column.pressed = true;
1039 this.draw_headers = true;
1040 this.Redraw (false);
1046 // hit test on items
1047 // we need to take scrolling into account
1048 hit = new Point (me.X + h_marker, me.Y + v_marker);
1049 foreach (ListViewItem item in this.items) {
1050 if (item.CheckRect.Contains (hit)) {
1051 CheckState curr_state = item.Checked ?
1052 CheckState.Checked : CheckState.Unchecked;
1054 item.Checked = false;
1056 item.Checked = true;
1058 CheckState new_state = item.Checked ?
1059 CheckState.Checked : CheckState.Unchecked;
1060 this.Redraw (false);
1062 // Raise the ItemCheck event
1063 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index,
1066 this.OnItemCheck (ice);
1070 if (this.view == View.Details &&
1071 this.FullRowSelect == false) {
1072 if (item.LabelRect.Contains (hit)) {
1073 this.clicked_item = item;
1078 if (item.EntireRect.Contains (hit)) {
1079 this.clicked_item = item;
1085 // set the FocusedItem to be the current clicked_item
1086 this.focused_item = this.clicked_item;
1088 if (this.clicked_item != null) {
1089 this.clicked_item.Selected = true;
1091 this.OnSelectedIndexChanged (new EventArgs ());
1093 this.Redraw (false);
1097 private void ListView_MouseHover (object sender, EventArgs e)
1099 // handle the hover events only when the mouse
1101 if (this.hover_selection == false || this.Capture)
1104 // hit test for the items
1105 Point hit = this.PointToClient (Control.MousePosition);
1106 ListViewItem item = this.GetItemAt (hit.X, hit.Y);
1109 item.Selected = true;
1111 this.OnSelectedIndexChanged (new EventArgs ());
1113 this.Redraw (false);
1117 private void ListView_MouseMove (object sender, MouseEventArgs me)
1119 // Column header is always at the top. It can
1120 // scroll only horizontally. So, we have to take
1121 // only horizontal scrolling into account
1122 Point hit = new Point (me.X + h_marker, me.Y);
1124 // non-null clicked_col means mouse down has happened
1126 if (this.clicked_column != null) {
1127 if (this.clicked_column.pressed == false &&
1128 this.clicked_column.Rect.Contains (hit)) {
1129 this.clicked_column.pressed = true;
1130 this.draw_headers = true;
1131 this.Redraw (false);
1133 else if (this.clicked_column.pressed &&
1134 ! this.clicked_column.Rect.Contains (hit)) {
1135 this.clicked_column.pressed = false;
1136 this.draw_headers = true;
1137 this.Redraw (false);
1142 private void ListView_MouseUp (object sender, MouseEventArgs me)
1144 this.Capture = false;
1145 if (items.Count == 0)
1148 Point hit = new Point (me.X, me.Y);
1150 if (this.clicked_column != null) {
1151 if (this.clicked_column.pressed) {
1152 this.clicked_column.pressed = false;
1153 this.draw_headers = true;
1154 this.Redraw (false);
1156 // Raise the ColumnClick event
1157 this.OnColumnClick (new ColumnClickEventArgs
1158 (this.clicked_column.Index));
1162 // Raise the ItemActivate event
1163 Rectangle rect = Rectangle.Empty;
1164 if (this.clicked_item != null) {
1165 if (this.view == View.Details && !this.full_row_select)
1166 rect = this.clicked_item.LabelRect;
1168 rect = this.clicked_item.EntireRect;
1170 // We handle double click in a separate handler
1171 if (this.activation != ItemActivation.Standard &&
1172 rect.Contains (hit)) {
1173 if (this.activation == ItemActivation.OneClick)
1174 this.ItemActivate (this, EventArgs.Empty);
1176 // ItemActivate is raised on the second click on the same item
1177 else if (this.activation == ItemActivation.TwoClick) {
1178 if (this.last_clicked_item == this.clicked_item) {
1179 this.ItemActivate (this, EventArgs.Empty);
1180 this.last_clicked_item = null;
1183 this.last_clicked_item = this.clicked_item;
1188 this.clicked_column = null;
1189 this.clicked_item = null;
1192 private void ListView_Paint (object sender, PaintEventArgs pe)
1194 if (this.Width <= 0 || this.Height <= 0 ||
1195 this.Visible == false || this.updating == true)
1198 CalculateScrollBars ();
1200 ThemeEngine.Current.DrawListView (pe.Graphics,
1201 pe.ClipRectangle, this);
1203 // We paint on the screen as per the location set
1204 // by the two scrollbars. In case of details view
1205 // since column headers can scroll only horizontally
1206 // and items can scroll in both directions, paiting is
1207 // done separtely for the column header and the items.
1209 Rectangle srcRect = this.ClientRectangle;
1210 Rectangle dstRect = this.ClientRectangle;
1212 // set the visible starting point
1214 srcRect.X += h_marker;
1215 srcRect.Y += v_marker;
1217 if (h_scroll.Visible) {
1218 srcRect.Height -= h_scroll.Height;
1219 dstRect.Height -= h_scroll.Height;
1222 if (v_scroll.Visible) {
1223 srcRect.Width -= v_scroll.Width;
1224 dstRect.Width -= v_scroll.Width;
1228 // We paint the column headers always at the top, in case
1229 // of vertical scrolling. Therefore, we advance the painting
1230 // by the amount equal to the column height.
1232 if (this.view == View.Details &&
1233 this.Columns.Count > 0 &&
1234 this.header_style != ColumnHeaderStyle.None &&
1237 int col_ht = this.Columns [0].Ht;
1239 if (this.draw_headers) {
1240 this.draw_headers = false;
1241 // Move the source rect by the amount of horizontal
1242 // scrolling done so far.
1243 Rectangle headerSrc = new Rectangle (h_marker, 0,
1244 srcRect.Width, col_ht);
1245 // dest rect is always stable at 0,0
1246 Rectangle headerDst = new Rectangle (0, 0, srcRect.Width, col_ht);
1247 pe.Graphics.DrawImage (this.ImageBuffer, headerDst,
1248 headerSrc, GraphicsUnit.Pixel);
1251 dstRect.Y += col_ht;
1252 srcRect.Y += col_ht;
1256 // Draw the border of the list view
1257 // The border is painted here separately, because
1258 // our imagebuffer might be scrollable
1259 ThemeEngine.Current.CPDrawBorderStyle (pe.Graphics,
1260 this.ClientRectangle,
1263 // Raise the Paint event
1268 private void ListView_SizeChanged (object sender, EventArgs e)
1270 CalculateScrollBars ();
1273 private void HorizontalScroller (object sender, EventArgs e)
1275 // Avoid unnecessary flickering, when button is
1276 // kept pressed at the end
1277 if (h_marker != h_scroll.Value) {
1278 h_marker = h_scroll.Value;
1279 // draw the headers again
1280 this.draw_headers = true;
1285 private void VerticalScroller (object sender, EventArgs e)
1287 // Avoid unnecessary flickering, when button is
1288 // kept pressed at the end
1289 if (v_marker != v_scroll.Value) {
1290 v_marker = v_scroll.Value;
1294 #endregion // Internal Methods Properties
1296 #region Protected Methods
1297 protected override void CreateHandle ()
1299 base.CreateHandle ();
1302 protected override void Dispose (bool disposing)
1304 base.Dispose (disposing);
1307 protected override bool IsInputKey (Keys keyData)
1309 return base.IsInputKey (keyData);
1312 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1314 if (AfterLabelEdit != null)
1315 AfterLabelEdit (this, e);
1318 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1320 if (BeforeLabelEdit != null)
1321 BeforeLabelEdit (this, e);
1324 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1326 if (ColumnClick != null)
1327 ColumnClick (this, e);
1330 protected override void OnEnabledChanged (EventArgs e)
1332 base.OnEnabledChanged (e);
1335 protected override void OnFontChanged (EventArgs e)
1337 base.OnFontChanged (e);
1341 protected override void OnHandleCreated (EventArgs e)
1343 base.OnHandleCreated (e);
1345 Controls.AddImplicit (this.v_scroll);
1346 Controls.AddImplicit (this.h_scroll);
1350 protected override void OnHandleDestroyed (EventArgs e)
1352 base.OnHandleDestroyed (e);
1355 protected virtual void OnItemActivate (EventArgs e)
1357 if (ItemActivate != null)
1358 ItemActivate (this, e);
1361 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1363 if (ItemCheck != null)
1364 ItemCheck (this, ice);
1367 protected virtual void OnItemDrag (ItemDragEventArgs e)
1369 if (ItemDrag != null)
1373 protected virtual void OnSelectedIndexChanged (EventArgs e)
1375 if (SelectedIndexChanged != null)
1376 SelectedIndexChanged (this, e);
1379 protected override void OnSystemColorsChanged (EventArgs e)
1381 base.OnSystemColorsChanged (e);
1384 protected void RealizeProperties ()
1389 protected void UpdateExtendedStyles ()
1394 protected override void WndProc (ref Message m)
1396 base.WndProc (ref m);
1398 #endregion // Protected Methods
1400 #region Public Instance Methods
1401 public void ArrangeIcons ()
1403 ArrangeIcons (this.alignment);
1406 public void ArrangeIcons (ListViewAlignment alignment)
1408 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1409 if (view == View.LargeIcon || view == View.SmallIcon) {
1410 this.CalculateListView (alignment);
1411 // we have done the calculations already
1412 this.Redraw (false);
1416 public void BeginUpdate ()
1418 // flag to avoid painting
1422 public void Clear ()
1429 public void EndUpdate ()
1431 // flag to avoid painting
1434 // probably, now we need a redraw with recalculations
1438 public void EnsureVisible (int index)
1440 if (index < 0 || index >= this.items.Count || this.scrollable == false)
1443 // dimensions of visible area
1444 int view_wd = this.Width - (this.v_scroll.Visible ? this.v_scroll.Width : 0);
1445 int view_ht = this.Height - (this.h_scroll.Visible ? this.h_scroll.Height : 0);
1446 // visible area is decided by the h_marker and v_marker
1447 Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1449 // an item's bounding rect
1450 Rectangle rect = this.items [index].EntireRect;
1452 // we don't need to do anything if item is visible.
1453 // visible area is represented by (0,0,view_wd,view_ht)
1454 if (view_rect.Contains (rect))
1457 // Scroll Left or Up
1458 if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1459 if (rect.Left < view_rect.Left)
1460 this.h_scroll.Value -= (view_rect.Left - rect.Left);
1461 if (rect.Top < view_rect.Top)
1462 this.v_scroll.Value -= (view_rect.Top - rect.Top);
1464 // Scroll Right or Down
1466 if (rect.Right > view_rect.Right)
1467 this.h_scroll.Value += (rect.Right - view_rect.Right);
1468 if (rect.Bottom > view_rect.Bottom)
1469 this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1473 public ListViewItem GetItemAt (int x, int y)
1475 foreach (ListViewItem item in items) {
1476 if (item.Bounds.Contains (x, y))
1482 public Rectangle GetItemRect (int index)
1484 return GetItemRect (index, ItemBoundsPortion.Entire);
1487 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1489 if (index < 0 || index >= items.Count)
1490 throw new IndexOutOfRangeException ("Invalid Index");
1492 return items [index].GetBounds (portion);
1497 if (sort_order != SortOrder.None)
1498 items.list.Sort (item_sorter);
1500 if (sort_order == SortOrder.Descending)
1501 items.list.Reverse ();
1506 public override string ToString ()
1508 int count = this.Items.Count;
1511 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1513 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1515 #endregion // Public Instance Methods
1519 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1521 internal ArrayList list;
1522 private ListView owner;
1524 #region Public Constructor
1525 public CheckedIndexCollection (ListView owner)
1527 list = new ArrayList ();
1530 #endregion // Public Constructor
1532 #region Public Properties
1534 public virtual int Count {
1535 get { return list.Count; }
1538 public virtual bool IsReadOnly {
1539 get { return true; }
1542 public int this [int index] {
1544 if (index < 0 || index >= list.Count)
1545 throw new ArgumentOutOfRangeException ("Index out of range.");
1546 return (int) list [index];
1550 bool ICollection.IsSynchronized {
1551 get { return list.IsSynchronized; }
1554 object ICollection.SyncRoot {
1555 get { return list.SyncRoot; }
1558 bool IList.IsFixedSize {
1559 get { return list.IsFixedSize; }
1562 object IList.this [int index] {
1563 get { return this [index]; }
1564 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1566 #endregion // Public Properties
1568 #region Public Methods
1569 public bool Contains (int checkedIndex)
1571 return list.Contains (checkedIndex);
1574 public virtual IEnumerator GetEnumerator ()
1576 return list.GetEnumerator ();
1579 void ICollection.CopyTo (Array dest, int index)
1581 list.CopyTo (dest, index);
1584 int IList.Add (object value)
1586 throw new NotSupportedException ("Add operation is not supported.");
1591 throw new NotSupportedException ("Clear operation is not supported.");
1594 bool IList.Contains (object checkedIndex)
1596 return list.Contains (checkedIndex);
1599 int IList.IndexOf (object checkedIndex)
1601 return list.IndexOf (checkedIndex);
1604 void IList.Insert (int index, object value)
1606 throw new NotSupportedException ("Insert operation is not supported.");
1609 void IList.Remove (object value)
1611 throw new NotSupportedException ("Remove operation is not supported.");
1614 void IList.RemoveAt (int index)
1616 throw new NotSupportedException ("RemoveAt operation is not supported.");
1619 public int IndexOf (int checkedIndex)
1621 return list.IndexOf (checkedIndex);
1623 #endregion // Public Methods
1625 } // CheckedIndexCollection
1627 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1629 internal ArrayList list;
1630 private ListView owner;
1632 #region Public Constructor
1633 public CheckedListViewItemCollection (ListView owner)
1635 list = new ArrayList ();
1638 #endregion // Public Constructor
1640 #region Public Properties
1642 public virtual int Count {
1643 get { return list.Count; }
1646 public virtual bool IsReadOnly {
1647 get { return true; }
1650 public ListViewItem this [int index] {
1652 if (index < 0 || index >= list.Count)
1653 throw new ArgumentOutOfRangeException ("Index out of range.");
1654 return (ListViewItem) list [index];
1658 bool ICollection.IsSynchronized {
1659 get { return list.IsSynchronized; }
1662 object ICollection.SyncRoot {
1663 get { return list.SyncRoot; }
1666 bool IList.IsFixedSize {
1667 get { return list.IsFixedSize; }
1670 object IList.this [int index] {
1671 get { return this [index]; }
1672 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1674 #endregion // Public Properties
1676 #region Public Methods
1677 public bool Contains (ListViewItem item)
1679 return list.Contains (item);
1682 public virtual void CopyTo (Array dest, int index)
1684 list.CopyTo (dest, index);
1687 public virtual IEnumerator GetEnumerator ()
1689 return list.GetEnumerator ();
1692 int IList.Add (object value)
1694 throw new NotSupportedException ("Add operation is not supported.");
1699 throw new NotSupportedException ("Clear operation is not supported.");
1702 bool IList.Contains (object item)
1704 return list.Contains (item);
1707 int IList.IndexOf (object item)
1709 return list.IndexOf (item);
1712 void IList.Insert (int index, object value)
1714 throw new NotSupportedException ("Insert operation is not supported.");
1717 void IList.Remove (object value)
1719 throw new NotSupportedException ("Remove operation is not supported.");
1722 void IList.RemoveAt (int index)
1724 throw new NotSupportedException ("RemoveAt operation is not supported.");
1727 public int IndexOf (ListViewItem item)
1729 return list.IndexOf (item);
1731 #endregion // Public Methods
1733 } // CheckedListViewItemCollection
1735 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1737 internal ArrayList list;
1738 private ListView owner;
1740 #region Public Constructor
1741 public ColumnHeaderCollection (ListView owner)
1743 list = new ArrayList ();
1746 #endregion // Public Constructor
1748 #region Public Properties
1750 public virtual int Count {
1751 get { return list.Count; }
1754 public virtual bool IsReadOnly {
1755 get { return false; }
1758 public virtual ColumnHeader this [int index] {
1760 if (index < 0 || index >= list.Count)
1761 throw new ArgumentOutOfRangeException ("Index out of range.");
1762 return (ColumnHeader) list [index];
1766 bool ICollection.IsSynchronized {
1767 get { return list.IsSynchronized; }
1770 object ICollection.SyncRoot {
1771 get { return list.SyncRoot; }
1774 bool IList.IsFixedSize {
1775 get { return list.IsFixedSize; }
1778 object IList.this [int index] {
1779 get { return this [index]; }
1780 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1782 #endregion // Public Properties
1784 #region Public Methods
1785 public virtual int Add (ColumnHeader value)
1788 value.owner = this.owner;
1789 idx = list.Add (value);
1790 owner.Redraw (true);
1794 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1796 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1797 this.Add (colHeader);
1801 public virtual void AddRange (ColumnHeader [] values)
1803 foreach (ColumnHeader colHeader in values) {
1804 colHeader.owner = this.owner;
1808 owner.Redraw (true);
1811 public virtual void Clear ()
1814 owner.Redraw (true);
1817 public bool Contains (ColumnHeader value)
1819 return list.Contains (value);
1822 public virtual IEnumerator GetEnumerator ()
1824 return list.GetEnumerator ();
1827 void ICollection.CopyTo (Array dest, int index)
1829 list.CopyTo (dest, index);
1832 int IList.Add (object value)
1834 if (! (value is ColumnHeader)) {
1835 throw new ArgumentException ("Not of type ColumnHeader", "value");
1838 return this.Add ((ColumnHeader) value);
1841 bool IList.Contains (object value)
1843 if (! (value is ColumnHeader)) {
1844 throw new ArgumentException ("Not of type ColumnHeader", "value");
1847 return this.Contains ((ColumnHeader) value);
1850 int IList.IndexOf (object value)
1852 if (! (value is ColumnHeader)) {
1853 throw new ArgumentException ("Not of type ColumnHeader", "value");
1856 return this.IndexOf ((ColumnHeader) value);
1859 void IList.Insert (int index, object value)
1861 if (! (value is ColumnHeader)) {
1862 throw new ArgumentException ("Not of type ColumnHeader", "value");
1865 this.Insert (index, (ColumnHeader) value);
1868 void IList.Remove (object value)
1870 if (! (value is ColumnHeader)) {
1871 throw new ArgumentException ("Not of type ColumnHeader", "value");
1874 this.Remove ((ColumnHeader) value);
1877 public int IndexOf (ColumnHeader value)
1879 return list.IndexOf (value);
1882 public void Insert (int index, ColumnHeader value)
1884 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
1885 // but it's really only greater.
1886 if (index < 0 || index > list.Count)
1887 throw new ArgumentOutOfRangeException ("Index out of range.");
1889 value.owner = this.owner;
1890 list.Insert (index, value);
1891 owner.Redraw (true);
1894 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1896 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1897 this.Insert (index, colHeader);
1900 public virtual void Remove (ColumnHeader column)
1902 // TODO: Update Column internal index ?
1903 list.Remove (column);
1904 owner.Redraw (true);
1907 public virtual void RemoveAt (int index)
1909 if (index < 0 || index >= list.Count)
1910 throw new ArgumentOutOfRangeException ("Index out of range.");
1912 // TODO: Update Column internal index ?
1913 list.RemoveAt (index);
1914 owner.Redraw (true);
1916 #endregion // Public Methods
1919 } // ColumnHeaderCollection
1921 public class ListViewItemCollection : IList, ICollection, IEnumerable
1923 internal ArrayList list;
1924 private ListView owner;
1926 #region Public Constructor
1927 public ListViewItemCollection (ListView owner)
1929 list = new ArrayList ();
1932 #endregion // Public Constructor
1934 #region Public Properties
1936 public virtual int Count {
1937 get { return list.Count; }
1940 public virtual bool IsReadOnly {
1941 get { return false; }
1944 public virtual ListViewItem this [int displayIndex] {
1946 if (displayIndex < 0 || displayIndex >= list.Count)
1947 throw new ArgumentOutOfRangeException ("Index out of range.");
1948 return (ListViewItem) list [displayIndex];
1952 if (displayIndex < 0 || displayIndex >= list.Count)
1953 throw new ArgumentOutOfRangeException ("Index out of range.");
1955 if (list.Contains (value))
1956 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1958 value.owner = this.owner;
1959 list [displayIndex] = value;
1961 owner.Redraw (true);
1965 bool ICollection.IsSynchronized {
1966 get { return list.IsSynchronized; }
1969 object ICollection.SyncRoot {
1970 get { return list.SyncRoot; }
1973 bool IList.IsFixedSize {
1974 get { return list.IsFixedSize; }
1977 object IList.this [int index] {
1978 get { return this [index]; }
1980 if (value is ListViewItem)
1981 this [index] = (ListViewItem) value;
1983 this [index] = new ListViewItem (value.ToString ());
1986 #endregion // Public Properties
1988 #region Public Methods
1989 public virtual ListViewItem Add (ListViewItem value)
1991 if (list.Contains (value))
1992 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1994 value.owner = this.owner;
1997 if (owner.Sorting != SortOrder.None)
2000 owner.Redraw (true);
2005 public virtual ListViewItem Add (string text)
2007 ListViewItem item = new ListViewItem (text);
2008 return this.Add (item);
2011 public virtual ListViewItem Add (string text, int imageIndex)
2013 ListViewItem item = new ListViewItem (text, imageIndex);
2014 return this.Add (item);
2017 public void AddRange (ListViewItem [] values)
2021 foreach (ListViewItem item in values) {
2022 item.owner = this.owner;
2026 if (owner.Sorting != SortOrder.None)
2029 owner.Redraw (true);
2032 public virtual void Clear ()
2037 public bool Contains (ListViewItem item)
2039 return list.Contains (item);
2042 public virtual void CopyTo (Array dest, int index)
2044 list.CopyTo (dest, index);
2047 public virtual IEnumerator GetEnumerator ()
2049 return list.GetEnumerator ();
2052 int IList.Add (object item)
2057 if (item is ListViewItem) {
2058 li = (ListViewItem) item;
2059 if (list.Contains (li))
2060 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2063 li = new ListViewItem (item.ToString ());
2065 li.owner = this.owner;
2066 result = list.Add (li);
2067 owner.Redraw (true);
2072 bool IList.Contains (object item)
2074 return list.Contains (item);
2077 int IList.IndexOf (object item)
2079 return list.IndexOf (item);
2082 void IList.Insert (int index, object item)
2084 if (item is ListViewItem)
2085 this.Insert (index, (ListViewItem) item);
2087 this.Insert (index, item.ToString ());
2090 void IList.Remove (object item)
2092 if (list.Contains (item)) {
2094 owner.Redraw (true);
2098 public int IndexOf (ListViewItem item)
2100 return list.IndexOf (item);
2103 public ListViewItem Insert (int index, ListViewItem item)
2105 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2106 // but it's really only greater.
2107 if (index < 0 || index > list.Count)
2108 throw new ArgumentOutOfRangeException ("Index out of range.");
2110 if (list.Contains (item))
2111 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2113 item.owner = this.owner;
2114 list.Insert (index, item);
2115 owner.Redraw (true);
2119 public ListViewItem Insert (int index, string text)
2121 return this.Insert (index, new ListViewItem (text));
2124 public ListViewItem Insert (int index, string text, int imageIndex)
2126 return this.Insert (index, new ListViewItem (text, imageIndex));
2129 public virtual void Remove (ListViewItem item)
2131 if (list.Contains (item)) {
2133 owner.Redraw (true);
2137 public virtual void RemoveAt (int index)
2139 if (index < 0 || index >= list.Count)
2140 throw new ArgumentOutOfRangeException ("Index out of range.");
2142 list.RemoveAt (index);
2143 owner.Redraw (false);
2145 #endregion // Public Methods
2147 } // ListViewItemCollection
2149 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2151 internal ArrayList list;
2152 private ListView owner;
2154 #region Public Constructor
2155 public SelectedIndexCollection (ListView owner)
2157 list = new ArrayList ();
2160 #endregion // Public Constructor
2162 #region Public Properties
2164 public virtual int Count {
2165 get { return list.Count; }
2168 public virtual bool IsReadOnly {
2169 get { return true; }
2172 public int this [int index] {
2174 if (index < 0 || index >= list.Count)
2175 throw new ArgumentOutOfRangeException ("Index out of range.");
2176 return (int) list [index];
2180 bool ICollection.IsSynchronized {
2181 get { return list.IsSynchronized; }
2184 object ICollection.SyncRoot {
2185 get { return list.SyncRoot; }
2188 bool IList.IsFixedSize {
2189 get { return list.IsFixedSize; }
2192 object IList.this [int index] {
2193 get { return this [index]; }
2194 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2196 #endregion // Public Properties
2198 #region Public Methods
2199 public bool Contains (int selectedIndex)
2201 return list.Contains (selectedIndex);
2204 public virtual void CopyTo (Array dest, int index)
2206 list.CopyTo (dest, index);
2209 public virtual IEnumerator GetEnumerator ()
2211 return list.GetEnumerator ();
2214 int IList.Add (object value)
2216 throw new NotSupportedException ("Add operation is not supported.");
2221 throw new NotSupportedException ("Clear operation is not supported.");
2224 bool IList.Contains (object selectedIndex)
2226 return list.Contains (selectedIndex);
2229 int IList.IndexOf (object selectedIndex)
2231 return list.IndexOf (selectedIndex);
2234 void IList.Insert (int index, object value)
2236 throw new NotSupportedException ("Insert operation is not supported.");
2239 void IList.Remove (object value)
2241 throw new NotSupportedException ("Remove operation is not supported.");
2244 void IList.RemoveAt (int index)
2246 throw new NotSupportedException ("RemoveAt operation is not supported.");
2249 public int IndexOf (int selectedIndex)
2251 return list.IndexOf (selectedIndex);
2253 #endregion // Public Methods
2255 } // SelectedIndexCollection
2257 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2259 internal ArrayList list;
2260 private ListView owner;
2262 #region Public Constructor
2263 public SelectedListViewItemCollection (ListView owner)
2265 list = new ArrayList ();
2268 #endregion // Public Constructor
2270 #region Public Properties
2272 public virtual int Count {
2273 get { return list.Count; }
2276 public virtual bool IsReadOnly {
2277 get { return true; }
2280 public ListViewItem this [int index] {
2282 if (index < 0 || index >= list.Count)
2283 throw new ArgumentOutOfRangeException ("Index out of range.");
2284 return (ListViewItem) list [index];
2288 bool ICollection.IsSynchronized {
2289 get { return list.IsSynchronized; }
2292 object ICollection.SyncRoot {
2293 get { return list.SyncRoot; }
2296 bool IList.IsFixedSize {
2297 get { return list.IsFixedSize; }
2300 object IList.this [int index] {
2301 get { return this [index]; }
2302 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2304 #endregion // Public Properties
2306 #region Public Methods
2307 public virtual void Clear ()
2309 // mark the items as unselected before clearing the list
2310 for (int i = 0; i < list.Count; i++)
2311 ((ListViewItem) list [i]).selected = false;
2316 public bool Contains (ListViewItem item)
2318 return list.Contains (item);
2321 public virtual void CopyTo (Array dest, int index)
2323 list.CopyTo (dest, index);
2326 public virtual IEnumerator GetEnumerator ()
2328 return list.GetEnumerator ();
2331 int IList.Add (object value)
2333 throw new NotSupportedException ("Add operation is not supported.");
2336 bool IList.Contains (object item)
2338 return list.Contains (item);
2341 int IList.IndexOf (object item)
2343 return list.IndexOf (item);
2346 void IList.Insert (int index, object value)
2348 throw new NotSupportedException ("Insert operation is not supported.");
2351 void IList.Remove (object value)
2353 throw new NotSupportedException ("Remove operation is not supported.");
2356 void IList.RemoveAt (int index)
2358 throw new NotSupportedException ("RemoveAt operation is not supported.");
2361 public int IndexOf (ListViewItem item)
2363 return list.IndexOf (item);
2365 #endregion // Public Methods
2367 } // SelectedListViewItemCollection
2369 #endregion // Subclasses