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);
1344 this.Controls.Add (this.v_scroll);
1345 this.Controls.Add (this.h_scroll);
1348 protected override void OnHandleDestroyed (EventArgs e)
1350 base.OnHandleDestroyed (e);
1353 protected virtual void OnItemActivate (EventArgs e)
1355 if (ItemActivate != null)
1356 ItemActivate (this, e);
1359 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1361 if (ItemCheck != null)
1362 ItemCheck (this, ice);
1365 protected virtual void OnItemDrag (ItemDragEventArgs e)
1367 if (ItemDrag != null)
1371 protected virtual void OnSelectedIndexChanged (EventArgs e)
1373 if (SelectedIndexChanged != null)
1374 SelectedIndexChanged (this, e);
1377 protected override void OnSystemColorsChanged (EventArgs e)
1379 base.OnSystemColorsChanged (e);
1382 protected void RealizeProperties ()
1387 protected void UpdateExtendedStyles ()
1392 protected override void WndProc (ref Message m)
1394 base.WndProc (ref m);
1396 #endregion // Protected Methods
1398 #region Public Instance Methods
1399 public void ArrangeIcons ()
1401 ArrangeIcons (this.alignment);
1404 public void ArrangeIcons (ListViewAlignment alignment)
1406 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1407 if (view == View.LargeIcon || view == View.SmallIcon) {
1408 this.CalculateListView (alignment);
1409 // we have done the calculations already
1410 this.Redraw (false);
1414 public void BeginUpdate ()
1416 // flag to avoid painting
1420 public void Clear ()
1427 public void EndUpdate ()
1429 // flag to avoid painting
1432 // probably, now we need a redraw with recalculations
1436 public void EnsureVisible (int index)
1438 if (index < 0 || index >= this.items.Count || this.scrollable == false)
1441 // dimensions of visible area
1442 int view_wd = this.Width - (this.v_scroll.Visible ? this.v_scroll.Width : 0);
1443 int view_ht = this.Height - (this.h_scroll.Visible ? this.h_scroll.Height : 0);
1444 // visible area is decided by the h_marker and v_marker
1445 Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1447 // an item's bounding rect
1448 Rectangle rect = this.items [index].EntireRect;
1450 // we don't need to do anything if item is visible.
1451 // visible area is represented by (0,0,view_wd,view_ht)
1452 if (view_rect.Contains (rect))
1455 // Scroll Left or Up
1456 if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1457 if (rect.Left < view_rect.Left)
1458 this.h_scroll.Value -= (view_rect.Left - rect.Left);
1459 if (rect.Top < view_rect.Top)
1460 this.v_scroll.Value -= (view_rect.Top - rect.Top);
1462 // Scroll Right or Down
1464 if (rect.Right > view_rect.Right)
1465 this.h_scroll.Value += (rect.Right - view_rect.Right);
1466 if (rect.Bottom > view_rect.Bottom)
1467 this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1471 public ListViewItem GetItemAt (int x, int y)
1473 foreach (ListViewItem item in items) {
1474 if (item.Bounds.Contains (x, y))
1480 public Rectangle GetItemRect (int index)
1482 return GetItemRect (index, ItemBoundsPortion.Entire);
1485 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1487 if (index < 0 || index >= items.Count)
1488 throw new IndexOutOfRangeException ("Invalid Index");
1490 return items [index].GetBounds (portion);
1495 if (sort_order != SortOrder.None)
1496 items.list.Sort (item_sorter);
1498 if (sort_order == SortOrder.Descending)
1499 items.list.Reverse ();
1504 public override string ToString ()
1506 int count = this.Items.Count;
1509 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1511 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1513 #endregion // Public Instance Methods
1517 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1519 internal ArrayList list;
1520 private ListView owner;
1522 #region Public Constructor
1523 public CheckedIndexCollection (ListView owner)
1525 list = new ArrayList ();
1528 #endregion // Public Constructor
1530 #region Public Properties
1532 public virtual int Count {
1533 get { return list.Count; }
1536 public virtual bool IsReadOnly {
1537 get { return true; }
1540 public int this [int index] {
1542 if (index < 0 || index >= list.Count)
1543 throw new ArgumentOutOfRangeException ("Index out of range.");
1544 return (int) list [index];
1548 bool ICollection.IsSynchronized {
1549 get { return list.IsSynchronized; }
1552 object ICollection.SyncRoot {
1553 get { return list.SyncRoot; }
1556 bool IList.IsFixedSize {
1557 get { return list.IsFixedSize; }
1560 object IList.this [int index] {
1561 get { return this [index]; }
1562 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1564 #endregion // Public Properties
1566 #region Public Methods
1567 public bool Contains (int checkedIndex)
1569 return list.Contains (checkedIndex);
1572 public virtual IEnumerator GetEnumerator ()
1574 return list.GetEnumerator ();
1577 void ICollection.CopyTo (Array dest, int index)
1579 list.CopyTo (dest, index);
1582 int IList.Add (object value)
1584 throw new NotSupportedException ("Add operation is not supported.");
1589 throw new NotSupportedException ("Clear operation is not supported.");
1592 bool IList.Contains (object checkedIndex)
1594 return list.Contains (checkedIndex);
1597 int IList.IndexOf (object checkedIndex)
1599 return list.IndexOf (checkedIndex);
1602 void IList.Insert (int index, object value)
1604 throw new NotSupportedException ("Insert operation is not supported.");
1607 void IList.Remove (object value)
1609 throw new NotSupportedException ("Remove operation is not supported.");
1612 void IList.RemoveAt (int index)
1614 throw new NotSupportedException ("RemoveAt operation is not supported.");
1617 public int IndexOf (int checkedIndex)
1619 return list.IndexOf (checkedIndex);
1621 #endregion // Public Methods
1623 } // CheckedIndexCollection
1625 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1627 internal ArrayList list;
1628 private ListView owner;
1630 #region Public Constructor
1631 public CheckedListViewItemCollection (ListView owner)
1633 list = new ArrayList ();
1636 #endregion // Public Constructor
1638 #region Public Properties
1640 public virtual int Count {
1641 get { return list.Count; }
1644 public virtual bool IsReadOnly {
1645 get { return true; }
1648 public ListViewItem this [int index] {
1650 if (index < 0 || index >= list.Count)
1651 throw new ArgumentOutOfRangeException ("Index out of range.");
1652 return (ListViewItem) list [index];
1656 bool ICollection.IsSynchronized {
1657 get { return list.IsSynchronized; }
1660 object ICollection.SyncRoot {
1661 get { return list.SyncRoot; }
1664 bool IList.IsFixedSize {
1665 get { return list.IsFixedSize; }
1668 object IList.this [int index] {
1669 get { return this [index]; }
1670 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1672 #endregion // Public Properties
1674 #region Public Methods
1675 public bool Contains (ListViewItem item)
1677 return list.Contains (item);
1680 public virtual void CopyTo (Array dest, int index)
1682 list.CopyTo (dest, index);
1685 public virtual IEnumerator GetEnumerator ()
1687 return list.GetEnumerator ();
1690 int IList.Add (object value)
1692 throw new NotSupportedException ("Add operation is not supported.");
1697 throw new NotSupportedException ("Clear operation is not supported.");
1700 bool IList.Contains (object item)
1702 return list.Contains (item);
1705 int IList.IndexOf (object item)
1707 return list.IndexOf (item);
1710 void IList.Insert (int index, object value)
1712 throw new NotSupportedException ("Insert operation is not supported.");
1715 void IList.Remove (object value)
1717 throw new NotSupportedException ("Remove operation is not supported.");
1720 void IList.RemoveAt (int index)
1722 throw new NotSupportedException ("RemoveAt operation is not supported.");
1725 public int IndexOf (ListViewItem item)
1727 return list.IndexOf (item);
1729 #endregion // Public Methods
1731 } // CheckedListViewItemCollection
1733 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1735 internal ArrayList list;
1736 private ListView owner;
1738 #region Public Constructor
1739 public ColumnHeaderCollection (ListView owner)
1741 list = new ArrayList ();
1744 #endregion // Public Constructor
1746 #region Public Properties
1748 public virtual int Count {
1749 get { return list.Count; }
1752 public virtual bool IsReadOnly {
1753 get { return false; }
1756 public virtual ColumnHeader this [int index] {
1758 if (index < 0 || index >= list.Count)
1759 throw new ArgumentOutOfRangeException ("Index out of range.");
1760 return (ColumnHeader) list [index];
1764 bool ICollection.IsSynchronized {
1765 get { return list.IsSynchronized; }
1768 object ICollection.SyncRoot {
1769 get { return list.SyncRoot; }
1772 bool IList.IsFixedSize {
1773 get { return list.IsFixedSize; }
1776 object IList.this [int index] {
1777 get { return this [index]; }
1778 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1780 #endregion // Public Properties
1782 #region Public Methods
1783 public virtual int Add (ColumnHeader value)
1786 value.owner = this.owner;
1787 idx = list.Add (value);
1788 owner.Redraw (true);
1792 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1794 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1795 this.Add (colHeader);
1799 public virtual void AddRange (ColumnHeader [] values)
1801 foreach (ColumnHeader colHeader in values) {
1802 colHeader.owner = this.owner;
1806 owner.Redraw (true);
1809 public virtual void Clear ()
1812 owner.Redraw (true);
1815 public bool Contains (ColumnHeader value)
1817 return list.Contains (value);
1820 public virtual IEnumerator GetEnumerator ()
1822 return list.GetEnumerator ();
1825 void ICollection.CopyTo (Array dest, int index)
1827 list.CopyTo (dest, index);
1830 int IList.Add (object value)
1832 if (! (value is ColumnHeader)) {
1833 throw new ArgumentException ("Not of type ColumnHeader", "value");
1836 return this.Add ((ColumnHeader) value);
1839 bool IList.Contains (object value)
1841 if (! (value is ColumnHeader)) {
1842 throw new ArgumentException ("Not of type ColumnHeader", "value");
1845 return this.Contains ((ColumnHeader) value);
1848 int IList.IndexOf (object value)
1850 if (! (value is ColumnHeader)) {
1851 throw new ArgumentException ("Not of type ColumnHeader", "value");
1854 return this.IndexOf ((ColumnHeader) value);
1857 void IList.Insert (int index, object value)
1859 if (! (value is ColumnHeader)) {
1860 throw new ArgumentException ("Not of type ColumnHeader", "value");
1863 this.Insert (index, (ColumnHeader) value);
1866 void IList.Remove (object value)
1868 if (! (value is ColumnHeader)) {
1869 throw new ArgumentException ("Not of type ColumnHeader", "value");
1872 this.Remove ((ColumnHeader) value);
1875 public int IndexOf (ColumnHeader value)
1877 return list.IndexOf (value);
1880 public void Insert (int index, ColumnHeader value)
1882 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
1883 // but it's really only greater.
1884 if (index < 0 || index > list.Count)
1885 throw new ArgumentOutOfRangeException ("Index out of range.");
1887 value.owner = this.owner;
1888 list.Insert (index, value);
1889 owner.Redraw (true);
1892 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1894 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1895 this.Insert (index, colHeader);
1898 public virtual void Remove (ColumnHeader column)
1900 // TODO: Update Column internal index ?
1901 list.Remove (column);
1902 owner.Redraw (true);
1905 public virtual void RemoveAt (int index)
1907 if (index < 0 || index >= list.Count)
1908 throw new ArgumentOutOfRangeException ("Index out of range.");
1910 // TODO: Update Column internal index ?
1911 list.RemoveAt (index);
1912 owner.Redraw (true);
1914 #endregion // Public Methods
1917 } // ColumnHeaderCollection
1919 public class ListViewItemCollection : IList, ICollection, IEnumerable
1921 internal ArrayList list;
1922 private ListView owner;
1924 #region Public Constructor
1925 public ListViewItemCollection (ListView owner)
1927 list = new ArrayList ();
1930 #endregion // Public Constructor
1932 #region Public Properties
1934 public virtual int Count {
1935 get { return list.Count; }
1938 public virtual bool IsReadOnly {
1939 get { return false; }
1942 public virtual ListViewItem this [int displayIndex] {
1944 if (displayIndex < 0 || displayIndex >= list.Count)
1945 throw new ArgumentOutOfRangeException ("Index out of range.");
1946 return (ListViewItem) list [displayIndex];
1950 if (displayIndex < 0 || displayIndex >= list.Count)
1951 throw new ArgumentOutOfRangeException ("Index out of range.");
1953 if (list.Contains (value))
1954 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1956 value.owner = this.owner;
1957 list [displayIndex] = value;
1959 owner.Redraw (true);
1963 bool ICollection.IsSynchronized {
1964 get { return list.IsSynchronized; }
1967 object ICollection.SyncRoot {
1968 get { return list.SyncRoot; }
1971 bool IList.IsFixedSize {
1972 get { return list.IsFixedSize; }
1975 object IList.this [int index] {
1976 get { return this [index]; }
1978 if (value is ListViewItem)
1979 this [index] = (ListViewItem) value;
1981 this [index] = new ListViewItem (value.ToString ());
1984 #endregion // Public Properties
1986 #region Public Methods
1987 public virtual ListViewItem Add (ListViewItem value)
1989 if (list.Contains (value))
1990 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1992 value.owner = this.owner;
1995 if (owner.Sorting != SortOrder.None)
1998 owner.Redraw (true);
2003 public virtual ListViewItem Add (string text)
2005 ListViewItem item = new ListViewItem (text);
2006 return this.Add (item);
2009 public virtual ListViewItem Add (string text, int imageIndex)
2011 ListViewItem item = new ListViewItem (text, imageIndex);
2012 return this.Add (item);
2015 public void AddRange (ListViewItem [] values)
2019 foreach (ListViewItem item in values) {
2020 item.owner = this.owner;
2024 if (owner.Sorting != SortOrder.None)
2027 owner.Redraw (true);
2030 public virtual void Clear ()
2035 public bool Contains (ListViewItem item)
2037 return list.Contains (item);
2040 public virtual void CopyTo (Array dest, int index)
2042 list.CopyTo (dest, index);
2045 public virtual IEnumerator GetEnumerator ()
2047 return list.GetEnumerator ();
2050 int IList.Add (object item)
2055 if (item is ListViewItem) {
2056 li = (ListViewItem) item;
2057 if (list.Contains (li))
2058 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2061 li = new ListViewItem (item.ToString ());
2063 li.owner = this.owner;
2064 result = list.Add (li);
2065 owner.Redraw (true);
2070 bool IList.Contains (object item)
2072 return list.Contains (item);
2075 int IList.IndexOf (object item)
2077 return list.IndexOf (item);
2080 void IList.Insert (int index, object item)
2082 if (item is ListViewItem)
2083 this.Insert (index, (ListViewItem) item);
2085 this.Insert (index, item.ToString ());
2088 void IList.Remove (object item)
2090 if (list.Contains (item)) {
2092 owner.Redraw (true);
2096 public int IndexOf (ListViewItem item)
2098 return list.IndexOf (item);
2101 public ListViewItem Insert (int index, ListViewItem item)
2103 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2104 // but it's really only greater.
2105 if (index < 0 || index > list.Count)
2106 throw new ArgumentOutOfRangeException ("Index out of range.");
2108 if (list.Contains (item))
2109 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2111 item.owner = this.owner;
2112 list.Insert (index, item);
2113 owner.Redraw (true);
2117 public ListViewItem Insert (int index, string text)
2119 return this.Insert (index, new ListViewItem (text));
2122 public ListViewItem Insert (int index, string text, int imageIndex)
2124 return this.Insert (index, new ListViewItem (text, imageIndex));
2127 public virtual void Remove (ListViewItem item)
2129 if (list.Contains (item)) {
2131 owner.Redraw (true);
2135 public virtual void RemoveAt (int index)
2137 if (index < 0 || index >= list.Count)
2138 throw new ArgumentOutOfRangeException ("Index out of range.");
2140 list.RemoveAt (index);
2141 owner.Redraw (false);
2143 #endregion // Public Methods
2145 } // ListViewItemCollection
2147 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2149 internal ArrayList list;
2150 private ListView owner;
2152 #region Public Constructor
2153 public SelectedIndexCollection (ListView owner)
2155 list = new ArrayList ();
2158 #endregion // Public Constructor
2160 #region Public Properties
2162 public virtual int Count {
2163 get { return list.Count; }
2166 public virtual bool IsReadOnly {
2167 get { return true; }
2170 public int this [int index] {
2172 if (index < 0 || index >= list.Count)
2173 throw new ArgumentOutOfRangeException ("Index out of range.");
2174 return (int) list [index];
2178 bool ICollection.IsSynchronized {
2179 get { return list.IsSynchronized; }
2182 object ICollection.SyncRoot {
2183 get { return list.SyncRoot; }
2186 bool IList.IsFixedSize {
2187 get { return list.IsFixedSize; }
2190 object IList.this [int index] {
2191 get { return this [index]; }
2192 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2194 #endregion // Public Properties
2196 #region Public Methods
2197 public bool Contains (int selectedIndex)
2199 return list.Contains (selectedIndex);
2202 public virtual void CopyTo (Array dest, int index)
2204 list.CopyTo (dest, index);
2207 public virtual IEnumerator GetEnumerator ()
2209 return list.GetEnumerator ();
2212 int IList.Add (object value)
2214 throw new NotSupportedException ("Add operation is not supported.");
2219 throw new NotSupportedException ("Clear operation is not supported.");
2222 bool IList.Contains (object selectedIndex)
2224 return list.Contains (selectedIndex);
2227 int IList.IndexOf (object selectedIndex)
2229 return list.IndexOf (selectedIndex);
2232 void IList.Insert (int index, object value)
2234 throw new NotSupportedException ("Insert operation is not supported.");
2237 void IList.Remove (object value)
2239 throw new NotSupportedException ("Remove operation is not supported.");
2242 void IList.RemoveAt (int index)
2244 throw new NotSupportedException ("RemoveAt operation is not supported.");
2247 public int IndexOf (int selectedIndex)
2249 return list.IndexOf (selectedIndex);
2251 #endregion // Public Methods
2253 } // SelectedIndexCollection
2255 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2257 internal ArrayList list;
2258 private ListView owner;
2260 #region Public Constructor
2261 public SelectedListViewItemCollection (ListView owner)
2263 list = new ArrayList ();
2266 #endregion // Public Constructor
2268 #region Public Properties
2270 public virtual int Count {
2271 get { return list.Count; }
2274 public virtual bool IsReadOnly {
2275 get { return true; }
2278 public ListViewItem this [int index] {
2280 if (index < 0 || index >= list.Count)
2281 throw new ArgumentOutOfRangeException ("Index out of range.");
2282 return (ListViewItem) list [index];
2286 bool ICollection.IsSynchronized {
2287 get { return list.IsSynchronized; }
2290 object ICollection.SyncRoot {
2291 get { return list.SyncRoot; }
2294 bool IList.IsFixedSize {
2295 get { return list.IsFixedSize; }
2298 object IList.this [int index] {
2299 get { return this [index]; }
2300 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2302 #endregion // Public Properties
2304 #region Public Methods
2305 public virtual void Clear ()
2307 // mark the items as unselected before clearing the list
2308 for (int i = 0; i < list.Count; i++)
2309 ((ListViewItem) list [i]).selected = false;
2314 public bool Contains (ListViewItem item)
2316 return list.Contains (item);
2319 public virtual void CopyTo (Array dest, int index)
2321 list.CopyTo (dest, index);
2324 public virtual IEnumerator GetEnumerator ()
2326 return list.GetEnumerator ();
2329 int IList.Add (object value)
2331 throw new NotSupportedException ("Add operation is not supported.");
2334 bool IList.Contains (object item)
2336 return list.Contains (item);
2339 int IList.IndexOf (object item)
2341 return list.IndexOf (item);
2344 void IList.Insert (int index, object value)
2346 throw new NotSupportedException ("Insert operation is not supported.");
2349 void IList.Remove (object value)
2351 throw new NotSupportedException ("Remove operation is not supported.");
2354 void IList.RemoveAt (int index)
2356 throw new NotSupportedException ("RemoveAt operation is not supported.");
2359 public int IndexOf (ListViewItem item)
2361 return list.IndexOf (item);
2363 #endregion // Public Methods
2365 } // SelectedListViewItemCollection
2367 #endregion // Subclasses