1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc. (http://www.novell.com)
23 // Ravindra Kumar (rkumar@novell.com)
24 // Jordi Mas i Hernandez, jordi@ximian.com
27 // - Keys to be handled ENTER/PAGE UP/PAGE DOWN/HOME/END/ARROWS/CTRL/SHIFT
28 // - Item text editing
29 // - Column resizing/reodering
30 // - Feedback for item activation, change in cursor types as mouse moves.
32 // - Focused item (broken and not drawn)
34 // - Manual column resizing
42 using System.Collections;
43 using System.ComponentModel;
44 using System.ComponentModel.Design;
46 using System.Runtime.InteropServices;
48 namespace System.Windows.Forms
50 [DefaultEvent ("SelectedIndexChanged")]
51 [DefaultProperty ("Items")]
52 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, (string)null)]
53 public class ListView : Control
55 private ItemActivation activation = ItemActivation.Standard;
56 private ListViewAlignment alignment = ListViewAlignment.Top;
57 private bool allow_column_reorder = false;
58 private bool auto_arrange = true;
59 private bool check_boxes = false;
60 private CheckedIndexCollection checked_indices;
61 private CheckedListViewItemCollection checked_items;
62 private ColumnHeader clicked_column;
63 private ListViewItem clicked_item;
64 private ListViewItem last_clicked_item;
65 private ColumnHeaderCollection columns;
66 private bool ctrl_pressed;
67 private bool shift_pressed;
68 private bool draw_headers = true; // Used for painting. Do we need to draw column headers ?
69 private ListViewItem focused_item;
70 private bool full_row_select = false;
71 private bool grid_lines = false;
72 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
73 private bool hide_selection = true;
74 private bool hover_selection = false;
75 private IComparer item_sorter;
76 private ListViewItemCollection items;
77 private bool label_edit = false;
78 private bool label_wrap = true;
79 private bool multiselect = true;
80 private bool redraw = true;
81 private bool scrollable = true;
82 private SelectedIndexCollection selected_indices;
83 private SelectedListViewItemCollection selected_items;
84 private SortOrder sort_order = SortOrder.None;
85 private ImageList state_image_list;
86 private bool updating = false;
87 private View view = View.LargeIcon;
88 private int layout_wd; // We might draw more than our client area
89 private int layout_ht; // therefore we need to have these two.
90 //private TextBox editor; // Used for editing an item text
91 private ScrollBar h_scroll; // used for scrolling horizontally
92 private ScrollBar v_scroll; // used for scrolling vertically
93 private int h_marker; // Position markers for scrolling
97 internal ImageList large_image_list;
98 internal ImageList small_image_list;
99 internal Size text_size = Size.Empty;
102 public event LabelEditEventHandler AfterLabelEdit;
105 [EditorBrowsable (EditorBrowsableState.Never)]
106 public new event EventHandler BackgroundImageChanged;
108 public event LabelEditEventHandler BeforeLabelEdit;
109 public event ColumnClickEventHandler ColumnClick;
110 public event EventHandler ItemActivate;
111 public event ItemCheckEventHandler ItemCheck;
112 public event ItemDragEventHandler ItemDrag;
115 [EditorBrowsable (EditorBrowsableState.Never)]
116 public new event PaintEventHandler Paint;
118 public event EventHandler SelectedIndexChanged;
121 [EditorBrowsable (EditorBrowsableState.Never)]
122 public new event EventHandler TextChanged;
125 #region Public Constructors
128 background_color = ThemeEngine.Current.ColorWindow;
129 checked_indices = new CheckedIndexCollection (this);
130 checked_items = new CheckedListViewItemCollection (this);
131 columns = new ColumnHeaderCollection (this);
132 foreground_color = SystemColors.WindowText;
133 items = new ListViewItemCollection (this);
134 selected_indices = new SelectedIndexCollection (this);
135 selected_items = new SelectedListViewItemCollection (this);
137 border_style = BorderStyle.Fixed3D;
139 // we are mostly scrollable
140 h_scroll = new HScrollBar ();
141 v_scroll = new VScrollBar ();
142 h_marker = v_marker = 0;
144 // scroll bars are disabled initially
145 h_scroll.Visible = false;
146 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
147 v_scroll.Visible = false;
148 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
151 base.DoubleClick += new EventHandler(ListView_DoubleClick);
152 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
153 base.KeyUp += new KeyEventHandler(ListView_KeyUp);
154 base.MouseDown += new MouseEventHandler(ListView_MouseDown);
155 base.MouseHover += new EventHandler(ListView_MouseHover);
156 base.MouseUp += new MouseEventHandler(ListView_MouseUp);
157 base.MouseMove += new MouseEventHandler(ListView_MouseMove);
158 base.Paint += new PaintEventHandler (ListView_Paint);
160 this.SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
162 #endregion // Public Constructors
164 #region Private Internal Properties
165 internal Size CheckBoxSize {
167 if (this.check_boxes) {
168 if (this.state_image_list != null)
169 return this.state_image_list.ImageSize;
171 return ThemeEngine.Current.ListViewCheckBoxSize;
177 internal bool CanMultiselect {
179 if (this.multiselect &&
180 (this.ctrl_pressed || this.shift_pressed))
186 #endregion // Private Internal Properties
188 #region Protected Properties
189 protected override CreateParams CreateParams {
190 get { return base.CreateParams; }
193 protected override Size DefaultSize {
194 get { return ThemeEngine.Current.ListViewDefaultSize; }
196 #endregion // Protected Properties
198 #region Public Instance Properties
199 [DefaultValue (ItemActivation.Standard)]
200 public ItemActivation Activation {
201 get { return activation; }
203 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
204 value != ItemActivation.TwoClick) {
205 throw new InvalidEnumArgumentException (string.Format
206 ("Enum argument value '{0}' is not valid for Activation", value));
213 [DefaultValue (ListViewAlignment.Top)]
215 public ListViewAlignment Alignment {
216 get { return alignment; }
218 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
219 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
220 throw new InvalidEnumArgumentException (string.Format
221 ("Enum argument value '{0}' is not valid for Alignment", value));
224 if (this.alignment != value) {
226 // alignment does not matter in Details/List views
227 if (this.view == View.LargeIcon ||
228 this.View == View.SmallIcon)
234 [DefaultValue (false)]
235 public bool AllowColumnReorder {
236 get { return allow_column_reorder; }
238 if (this.allow_column_reorder != value) {
239 allow_column_reorder = value;
240 // column reorder does not matter in Details view
241 if (this.view != View.Details)
247 [DefaultValue (true)]
248 public bool AutoArrange {
249 get { return auto_arrange; }
251 if (auto_arrange != value) {
252 auto_arrange = value;
253 // autoarrange does not matter in Details/List views
254 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
260 public override Color BackColor {
262 if (background_color.IsEmpty)
263 return ThemeEngine.Current.ColorWindow;
265 return background_color;
267 set { background_color = value; }
271 [EditorBrowsable (EditorBrowsableState.Never)]
272 public override Image BackgroundImage {
273 get { return background_image; }
275 if (value == background_image)
278 background_image = value;
279 if (BackgroundImageChanged != null)
280 BackgroundImageChanged (this, new EventArgs ());
284 [DefaultValue (BorderStyle.Fixed3D)]
286 public BorderStyle BorderStyle {
287 get { return border_style; }
289 if (value != BorderStyle.Fixed3D && value != BorderStyle.FixedSingle &&
290 value != BorderStyle.None) {
291 throw new InvalidEnumArgumentException (string.Format
292 ("Enum argument value '{0}' is not valid for BorderStyle", value));
295 if (border_style != value) {
296 border_style = value;
302 [DefaultValue (false)]
303 public bool CheckBoxes {
304 get { return check_boxes; }
306 if (check_boxes != value) {
314 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
315 public CheckedIndexCollection CheckedIndices {
316 get { return checked_indices; }
320 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
321 public CheckedListViewItemCollection CheckedItems {
322 get { return checked_items; }
325 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
327 [MergableProperty (false)]
328 public ColumnHeaderCollection Columns {
329 get { return columns; }
333 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
334 public ListViewItem FocusedItem {
335 get { return focused_item; }
338 public override Color ForeColor {
340 if (foreground_color.IsEmpty)
341 return ThemeEngine.Current.ColorWindowText;
343 return foreground_color;
345 set { foreground_color = value; }
348 [DefaultValue (false)]
349 public bool FullRowSelect {
350 get { return full_row_select; }
351 set { full_row_select = value; }
354 [DefaultValue (false)]
355 public bool GridLines {
356 get { return grid_lines; }
358 if (grid_lines != value) {
365 [DefaultValue (ColumnHeaderStyle.Clickable)]
366 public ColumnHeaderStyle HeaderStyle {
367 get { return header_style; }
369 if (value != ColumnHeaderStyle.Clickable && value != ColumnHeaderStyle.Nonclickable &&
370 value != ColumnHeaderStyle.None) {
371 throw new InvalidEnumArgumentException (string.Format
372 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
375 if (header_style != value) {
376 header_style = value;
377 // header style matters only in Details view
378 if (this.view == View.Details)
384 [DefaultValue (true)]
385 public bool HideSelection {
386 get { return hide_selection; }
388 if (hide_selection != value) {
389 hide_selection = value;
395 [DefaultValue (false)]
396 public bool HoverSelection {
397 get { return hover_selection; }
398 set { hover_selection = value; }
401 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
403 [MergableProperty (false)]
404 public ListViewItemCollection Items {
405 get { return items; }
408 [DefaultValue (false)]
409 public bool LabelEdit {
410 get { return label_edit; }
411 set { label_edit = value; }
414 [DefaultValue (true)]
416 public bool LabelWrap {
417 get { return label_wrap; }
419 if (label_wrap != value) {
426 [DefaultValue (null)]
427 public ImageList LargeImageList {
428 get { return large_image_list; }
430 large_image_list = value;
436 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
437 public IComparer ListViewItemSorter {
438 get { return item_sorter; }
439 set { item_sorter = value; }
442 [DefaultValue (true)]
443 public bool MultiSelect {
444 get { return multiselect; }
445 set { multiselect = value; }
448 [DefaultValue (true)]
449 public bool Scrollable {
450 get { return scrollable; }
452 if (scrollable != value) {
460 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
461 public SelectedIndexCollection SelectedIndices {
462 get { return selected_indices; }
466 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
467 public SelectedListViewItemCollection SelectedItems {
468 get { return selected_items; }
471 [DefaultValue (null)]
472 public ImageList SmallImageList {
473 get { return small_image_list; }
475 small_image_list = value;
480 [DefaultValue (SortOrder.None)]
481 public SortOrder Sorting {
482 get { return sort_order; }
484 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
485 value != SortOrder.None) {
486 throw new InvalidEnumArgumentException (string.Format
487 ("Enum argument value '{0}' is not valid for Sorting", value));
490 if (sort_order != value) {
497 [DefaultValue (null)]
498 public ImageList StateImageList {
499 get { return state_image_list; }
501 state_image_list = value;
508 [EditorBrowsable (EditorBrowsableState.Never)]
509 public override string Text {
518 if (TextChanged != null)
519 TextChanged (this, new EventArgs ());
524 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
525 public ListViewItem TopItem {
528 if (this.items.Count == 0)
530 // if contents are not scrolled
531 // it is the first item
532 else if (h_marker == 0 && v_marker == 0)
533 return this.items [0];
534 // do a hit test for the scrolled position
536 foreach (ListViewItem item in this.items) {
537 if (item.EntireRect.Contains (h_marker, v_marker))
545 [DefaultValue (View.LargeIcon)]
549 if (value != View.Details && value != View.LargeIcon &&
550 value != View.List && value != View.SmallIcon ) {
551 throw new InvalidEnumArgumentException (string.Format
552 ("Enum argument value '{0}' is not valid for View", value));
561 #endregion // Public Instance Properties
563 #region Internal Methods Properties
564 internal int TotalWidth {
565 get { return Math.Max (this.Width, this.layout_wd); }
568 internal int TotalHeight {
569 get { return Math.Max (this.Height, this.layout_ht); }
572 internal void Redraw (bool recalculate)
574 // Avoid calculations when control is being updated
579 CalculateListView (this.alignment);
585 internal Size GetChildColumnSize (int index)
587 Size ret_size = Size.Empty;
588 ColumnHeader col = this.columns [index];
590 if (col.Width == -2) { // autosize = max(items, columnheader)
591 Size size = Size.Ceiling (this.DeviceContext.MeasureString
592 (col.Text, this.Font));
593 ret_size = BiggestItem (index);
594 if (size.Width > ret_size.Width)
597 else { // -1 and all the values < -2 are put under one category
598 ret_size = BiggestItem (index);
599 // fall back to empty columns' width if no subitem is available for a column
600 if (ret_size.IsEmpty) {
601 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
602 if (col.Text.Length > 0)
603 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
604 (col.Text, this.Font)).Height;
606 ret_size.Height = this.Font.Height;
610 // adjust the size for icon and checkbox for 0th column
612 ret_size.Width += (this.CheckBoxSize.Width + 4);
613 if (this.small_image_list != null)
614 ret_size.Width += this.small_image_list.ImageSize.Width;
619 // Returns the size of biggest item text in a column.
620 private Size BiggestItem (int col)
622 Size temp = Size.Empty;
623 Size ret_size = Size.Empty;
625 // 0th column holds the item text, we check the size of
626 // the various subitems falling in that column and get
627 // the biggest one's size.
628 foreach (ListViewItem item in items) {
629 if (col >= item.SubItems.Count)
632 temp = Size.Ceiling (this.DeviceContext.MeasureString
633 (item.SubItems [col].Text, this.Font));
634 if (temp.Width > ret_size.Width)
638 // adjustment for space
639 if (!ret_size.IsEmpty)
645 // Sets the size of the biggest item text as per the view
646 private void CalcTextSize ()
648 // clear the old value
649 text_size = Size.Empty;
651 if (items.Count == 0)
654 text_size = BiggestItem (0);
656 if (view == View.LargeIcon && this.label_wrap) {
657 Size temp = Size.Empty;
658 if (this.check_boxes)
659 temp.Width += 2 * this.CheckBoxSize.Width;
660 if (large_image_list != null)
661 temp.Width += large_image_list.ImageSize.Width;
664 // wrapping is done for two lines only
665 if (text_size.Width > temp.Width) {
666 text_size.Width = temp.Width;
667 text_size.Height *= 2;
670 else if (view == View.List) {
671 // in list view max text shown in determined by the
672 // control width, even if scolling is enabled.
673 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
674 if (this.small_image_list != null)
675 max_wd -= this.small_image_list.ImageSize.Width;
677 if (text_size.Width > max_wd)
678 text_size.Width = max_wd;
681 // we do the default settings, if we have got 0's
682 if (text_size.Height <= 0)
683 text_size.Height = this.Font.Height;
684 if (text_size.Width <= 0)
685 text_size.Width = this.Width;
688 text_size.Width += 4;
689 text_size.Height += 2;
692 // Sets the location of every item on
693 // the ListView as per the view
694 private void CalculateListView (ListViewAlignment align)
696 int current_pos_x = 0; // our x-position marker
697 int current_pos_y = 0; // our y-position marker
700 int max; // max x_pos or y_pos depending on the alignment
701 int current = 0; // current row or column
702 int vertical_spacing = ThemeEngine.Current.ListViewVerticalSpacing;
703 int horizontal_spacing = ThemeEngine.Current.ListViewHorizontalSpacing;
710 // ColumnHeaders are not drawn if headerstyle is none
711 int ht = (this.header_style == ColumnHeaderStyle.None) ?
712 2 : this.Font.Height + 5;
713 if (columns.Count > 0) {
714 foreach (ColumnHeader col in columns) {
715 col.X = current_pos_x;
717 col.CalcColumnHeader ();
718 current_pos_x += col.Wd;
720 this.layout_wd = current_pos_x;
722 // set the position marker for placing items
726 if (items.Count > 0) {
727 foreach (ListViewItem item in items) {
729 item.location.Y = current_pos_y;
730 item.CalcListViewItem ();
731 current_pos_y += item.EntireRect.Height;
733 this.layout_ht = current_pos_y;
735 // some space for bottom gridline
742 vertical_spacing = 0;
743 horizontal_spacing = 0;
744 goto case View.LargeIcon;
747 if (items.Count > 0) {
748 items [0].CalcListViewItem ();
749 item_ht = items [0].EntireRect.Height;
750 item_wd = items [0].EntireRect.Width;
752 // top (default) and snaptogrid alignments are handled same way
753 if (align == ListViewAlignment.Left) {
755 foreach (ListViewItem item in items) {
756 item.location.X = current_pos_x +
758 item.location.Y = current_pos_y;
759 item.CalcListViewItem ();
760 current_pos_y += item_ht;
762 current ++; // just to know about the last element
763 // we just did the last item
764 if (current == items.Count) {
765 if (max < current_pos_y)
767 current_pos_x = item.EntireRect.Right;
771 // is there enough space for another row ?
772 if ((current_pos_y + vertical_spacing
773 + item_ht) <= this.Height)
774 current_pos_y += vertical_spacing;
776 // start another column
777 // make current_pos_y as the
778 // max value and reset
779 // current_pos_y value.
781 current_pos_x += item_wd;
786 // adjust the layout dimensions
787 this.layout_ht = max;
788 this.layout_wd = current_pos_x;
790 else { // other default/top alignment
792 foreach (ListViewItem item in items) {
793 item.location.X = current_pos_x +
796 item.location.Y = current_pos_y;
797 item.CalcListViewItem ();
798 current_pos_x += item_wd;
800 current ++; // just to know about the last element
801 // we just did the last item
802 if (current == items.Count) {
803 if (max < current_pos_x)
805 current_pos_y = item.EntireRect.Bottom;
809 // is there enough space for another column?
810 if ((current_pos_x + horizontal_spacing
811 + item_wd) <= this.Width)
815 // make current_pos_x as the
816 // max value and reset
817 // current_pos_x value.
819 current_pos_y += (item_ht +
825 // adjust the layout dimensions
826 this.layout_wd = max;
827 this.layout_ht = current_pos_y;
833 if (items.Count > 0) {
834 items [0].CalcListViewItem ();
835 item_ht = items [0].EntireRect.Height;
836 item_wd = items [0].EntireRect.Width;
838 max = this.Height / item_ht;
840 max = 1; // we draw at least one row
842 foreach (ListViewItem item in items) {
843 item.location.X = current_pos_x;
844 item.location.Y = current_pos_y;
845 item.CalcListViewItem ();
847 if (current == max) {
848 current_pos_x += item_wd;
853 current_pos_y += item_ht;
856 // adjust the layout dimensions
857 this.layout_ht = max * item_ht;
858 if (current == 0) // we have fully filled layout
859 this.layout_wd = current_pos_x;
861 this.layout_wd = current_pos_x + item_wd;
866 if (this.scrollable && this.items.Count > 0) {
867 // making a scroll bar visible might make
868 // other scroll bar visible
869 if (this.layout_wd > this.Width) {
870 this.h_scroll.Visible = true;
871 if ((this.layout_ht + this.h_scroll.Height) > this.Height)
872 this.v_scroll.Visible = true;
874 else if (this.layout_ht > this.Height) {
875 this.v_scroll.Visible = true;
876 if ((this.layout_wd + this.v_scroll.Width) > this.Width)
877 this.h_scroll.Visible = true;
880 // create big enough buffers
881 if (this.layout_wd > this.Width ||
882 this.layout_ht > this.Height)
883 this.CreateBuffers (this.TotalWidth, this.TotalHeight);
885 if (this.h_scroll.Visible) {
886 this.h_scroll.Location = new Point (0, this.Height
887 - this.h_scroll.Height);
889 this.h_scroll.Minimum = 0;
891 // if v_scroll is visible, adjust the maximum of the
892 // h_scroll to account for the width of v_scroll
893 if (this.v_scroll.Visible) {
894 this.h_scroll.Maximum = this.layout_wd + this.v_scroll.Width;
895 this.h_scroll.Width = this.Width - this.v_scroll.Width;
898 this.h_scroll.Maximum = this.layout_wd;
899 this.h_scroll.Width = this.Width;
902 this.h_scroll.LargeChange = this.Width;
903 this.h_scroll.SmallChange = this.Font.Height;
906 // vertical scrollbar
907 if (this.v_scroll.Visible) {
908 this.v_scroll.Location = new Point (this.Width
909 - this.v_scroll.Width, 0);
911 this.v_scroll.Minimum = 0;
913 // if h_scroll is visible, adjust the maximum of the
914 // v_scroll to account for the height of h_scroll
915 if (this.h_scroll.Visible) {
916 this.v_scroll.Maximum = this.layout_ht + this.h_scroll.Height;
917 this.v_scroll.Height = this.Height - this.h_scroll.Height;
920 this.v_scroll.Maximum = this.layout_ht;
921 this.v_scroll.Height = this.Height;
924 this.v_scroll.LargeChange = this.Height;
925 this.v_scroll.SmallChange = this.Font.Height;
929 this.h_scroll.Visible = false;
930 this.v_scroll.Visible = false;
936 private void ListView_DoubleClick (object sender, EventArgs e)
938 if (this.activation == ItemActivation.Standard
939 && this.ItemActivate != null)
940 this.ItemActivate (this, e);
943 private void ListView_KeyDown (object sender, KeyEventArgs ke)
951 switch (ke.KeyCode) {
953 case Keys.ControlKey:
954 this.ctrl_pressed = true;
962 this.v_scroll.Value = this.v_scroll.Maximum;
966 this.v_scroll.Value = this.v_scroll.Minimum;
971 if (this.last_clicked_item != null)
972 index = this.last_clicked_item.Index;
979 this.last_clicked_item = this.items [index];
980 this.last_clicked_item.Selected = true;
981 this.EnsureVisible (index);
985 if (this.last_clicked_item != null)
986 index = this.last_clicked_item.Index + 1;
990 if (index == this.items.Count)
993 this.last_clicked_item = this.items [index];
994 this.last_clicked_item.Selected = true;
995 this.EnsureVisible (index);
999 this.shift_pressed = true;
1012 private void ListView_KeyUp (object sender, KeyEventArgs ke)
1015 if (ke.KeyCode == Keys.ControlKey)
1016 this.ctrl_pressed = false;
1018 if (ke.KeyCode == Keys.ShiftKey)
1019 this.shift_pressed = false;
1024 private void ListView_MouseDown (object sender, MouseEventArgs me)
1026 if (items.Count == 0)
1029 Point hit = Point.Empty;
1030 if (this.HeaderStyle != ColumnHeaderStyle.None) {
1031 // take horizontal scrolling into account
1032 hit = new Point (me.X + h_marker, me.Y);
1034 // hit test on columns
1035 if (this.view == View.Details && this.columns.Count > 0) {
1036 foreach (ColumnHeader col in this.columns) {
1037 if (col.Rect.Contains (hit)) {
1038 this.clicked_column = col;
1039 this.Capture = true;
1044 if (this.clicked_column != null) {
1045 this.clicked_column.pressed = true;
1046 this.draw_headers = true;
1047 this.Redraw (false);
1053 // hit test on items
1054 // we need to take scrolling into account
1055 hit = new Point (me.X + h_marker, me.Y + v_marker);
1056 foreach (ListViewItem item in this.items) {
1057 if (item.CheckRect.Contains (hit)) {
1058 CheckState curr_state = item.Checked ?
1059 CheckState.Checked : CheckState.Unchecked;
1061 item.Checked = false;
1063 item.Checked = true;
1065 CheckState new_state = item.Checked ?
1066 CheckState.Checked : CheckState.Unchecked;
1067 this.Redraw (false);
1069 // Raise the ItemCheck event
1070 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index,
1073 this.OnItemCheck (ice);
1077 if (this.view == View.Details &&
1078 this.FullRowSelect == false) {
1079 if (item.LabelRect.Contains (hit)) {
1080 this.clicked_item = item;
1085 if (item.EntireRect.Contains (hit)) {
1086 this.clicked_item = item;
1092 // set the FocusedItem to be the current clicked_item
1093 this.focused_item = this.clicked_item;
1095 if (this.clicked_item != null) {
1096 this.clicked_item.Selected = true;
1098 this.OnSelectedIndexChanged (new EventArgs ());
1100 this.Redraw (false);
1104 private void ListView_MouseHover (object sender, EventArgs e)
1106 // handle the hover events only when the mouse
1108 if (this.hover_selection == false || this.Capture)
1111 // hit test for the items
1112 Point hit = this.PointToClient (Control.MousePosition);
1113 ListViewItem item = this.GetItemAt (hit.X, hit.Y);
1116 item.Selected = true;
1118 this.OnSelectedIndexChanged (new EventArgs ());
1120 this.Redraw (false);
1124 private void ListView_MouseMove (object sender, MouseEventArgs me)
1126 // Column header is always at the top. It can
1127 // scroll only horizontally. So, we have to take
1128 // only horizontal scrolling into account
1129 Point hit = new Point (me.X + h_marker, me.Y);
1131 // non-null clicked_col means mouse down has happened
1133 if (this.clicked_column != null) {
1134 if (this.clicked_column.pressed == false &&
1135 this.clicked_column.Rect.Contains (hit)) {
1136 this.clicked_column.pressed = true;
1137 this.draw_headers = true;
1138 this.Redraw (false);
1140 else if (this.clicked_column.pressed &&
1141 ! this.clicked_column.Rect.Contains (hit)) {
1142 this.clicked_column.pressed = false;
1143 this.draw_headers = true;
1144 this.Redraw (false);
1149 private void ListView_MouseUp (object sender, MouseEventArgs me)
1151 this.Capture = false;
1152 if (items.Count == 0)
1155 Point hit = new Point (me.X, me.Y);
1157 if (this.clicked_column != null) {
1158 if (this.clicked_column.pressed) {
1159 this.clicked_column.pressed = false;
1160 this.draw_headers = true;
1161 this.Redraw (false);
1163 // Raise the ColumnClick event
1164 this.OnColumnClick (new ColumnClickEventArgs
1165 (this.clicked_column.Index));
1169 // Raise the ItemActivate event
1170 Rectangle rect = Rectangle.Empty;
1171 if (this.clicked_item != null) {
1172 if (this.view == View.Details && !this.full_row_select)
1173 rect = this.clicked_item.LabelRect;
1175 rect = this.clicked_item.EntireRect;
1177 // We handle double click in a separate handler
1178 if (this.activation != ItemActivation.Standard &&
1179 rect.Contains (hit)) {
1180 if (this.activation == ItemActivation.OneClick)
1181 this.ItemActivate (this, EventArgs.Empty);
1183 // ItemActivate is raised on the second click on the same item
1184 else if (this.activation == ItemActivation.TwoClick) {
1185 if (this.last_clicked_item == this.clicked_item) {
1186 this.ItemActivate (this, EventArgs.Empty);
1187 this.last_clicked_item = null;
1190 this.last_clicked_item = this.clicked_item;
1195 this.clicked_column = null;
1196 this.clicked_item = null;
1199 private void ListView_Paint (object sender, PaintEventArgs pe)
1201 Console.WriteLine ("ListView_Paint {0} {1}", this.TotalWidth, this.TotalHeight);
1203 if (this.Width <= 0 || this.Height <= 0 ||
1204 this.Visible == false || this.updating == true)
1208 ThemeEngine.Current.DrawListView (this.DeviceContext,
1209 pe.ClipRectangle, this);
1213 // We paint on the screen as per the location set
1214 // by the two scrollbars. In case of details view
1215 // since column headers can scroll only horizontally
1216 // and items can scroll in both directions, paiting is
1217 // done separtely for the column header and the items.
1219 Rectangle srcRect = this.ClientRectangle;
1220 Rectangle dstRect = this.ClientRectangle;
1222 // set the visible starting point
1224 srcRect.X += h_marker;
1225 srcRect.Y += v_marker;
1227 if (h_scroll.Visible) {
1228 srcRect.Height -= h_scroll.Height;
1229 dstRect.Height -= h_scroll.Height;
1232 if (v_scroll.Visible) {
1233 srcRect.Width -= v_scroll.Width;
1234 dstRect.Width -= v_scroll.Width;
1238 // We paint the column headers always at the top, in case
1239 // of vertical scrolling. Therefore, we advance the painting
1240 // by the amount equal to the column height.
1241 if (this.view == View.Details &&
1242 this.Columns.Count > 0 &&
1243 this.header_style != ColumnHeaderStyle.None &&
1246 int col_ht = this.Columns [0].Ht;
1248 if (this.draw_headers) {
1249 this.draw_headers = false;
1250 // Move the source rect by the amount of horizontal
1251 // scrolling done so far.
1252 Rectangle headerSrc = new Rectangle (h_marker, 0,
1253 srcRect.Width, col_ht);
1254 // dest rect is always stable at 0,0
1255 Rectangle headerDst = new Rectangle (0, 0, srcRect.Width, col_ht);
1256 pe.Graphics.DrawImage (this.ImageBuffer, headerDst,
1257 headerSrc, GraphicsUnit.Pixel);
1260 dstRect.Y += col_ht;
1261 srcRect.Y += col_ht;
1265 pe.Graphics.DrawImage (this.ImageBuffer, dstRect,
1266 srcRect, GraphicsUnit.Pixel);
1268 // Draw the border of the list view
1269 // The border is painted here separately, because
1270 // our imagebuffer might be scrollable
1271 ThemeEngine.Current.CPDrawBorderStyle (pe.Graphics,
1272 this.ClientRectangle,
1275 // Raise the Paint event
1280 private void HorizontalScroller (object sender, EventArgs e)
1282 // Avoid unnecessary flickering, when button is
1283 // kept pressed at the end
1284 if (h_marker != h_scroll.Value) {
1285 h_marker = h_scroll.Value;
1286 // draw the headers again
1287 this.draw_headers = true;
1292 private void VerticalScroller (object sender, EventArgs e)
1294 // Avoid unnecessary flickering, when button is
1295 // kept pressed at the end
1296 if (v_marker != v_scroll.Value) {
1297 v_marker = v_scroll.Value;
1301 #endregion // Internal Methods Properties
1303 #region Protected Methods
1304 protected override void CreateHandle ()
1306 base.CreateHandle ();
1309 protected override void Dispose (bool disposing)
1311 base.Dispose (disposing);
1314 protected override bool IsInputKey (Keys keyData)
1316 return base.IsInputKey (keyData);
1319 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1321 if (AfterLabelEdit != null)
1322 AfterLabelEdit (this, e);
1325 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1327 if (BeforeLabelEdit != null)
1328 BeforeLabelEdit (this, e);
1331 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1333 if (ColumnClick != null)
1334 ColumnClick (this, e);
1337 protected override void OnEnabledChanged (EventArgs e)
1339 base.OnEnabledChanged (e);
1342 protected override void OnFontChanged (EventArgs e)
1344 base.OnFontChanged (e);
1348 protected override void OnHandleCreated (EventArgs e)
1350 base.OnHandleCreated (e);
1351 this.Controls.Add (this.v_scroll);
1352 this.Controls.Add (this.h_scroll);
1355 protected override void OnHandleDestroyed (EventArgs e)
1357 base.OnHandleDestroyed (e);
1360 protected virtual void OnItemActivate (EventArgs e)
1362 if (ItemActivate != null)
1363 ItemActivate (this, e);
1366 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1368 if (ItemCheck != null)
1369 ItemCheck (this, ice);
1372 protected virtual void OnItemDrag (ItemDragEventArgs e)
1374 if (ItemDrag != null)
1378 protected virtual void OnSelectedIndexChanged (EventArgs e)
1380 if (SelectedIndexChanged != null)
1381 SelectedIndexChanged (this, e);
1384 protected override void OnSystemColorsChanged (EventArgs e)
1386 base.OnSystemColorsChanged (e);
1389 protected void RealizeProperties ()
1394 protected void UpdateExtendedStyles ()
1399 protected override void WndProc (ref Message m)
1401 base.WndProc (ref m);
1403 #endregion // Protected Methods
1405 #region Public Instance Methods
1406 public void ArrangeIcons ()
1408 ArrangeIcons (this.alignment);
1411 public void ArrangeIcons (ListViewAlignment alignment)
1413 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1414 if (view == View.LargeIcon || view == View.SmallIcon) {
1415 this.CalculateListView (alignment);
1416 // we have done the calculations already
1417 this.Redraw (false);
1421 public void BeginUpdate ()
1423 // flag to avoid painting
1427 public void Clear ()
1434 public void EndUpdate ()
1436 // flag to avoid painting
1439 // probably, now we need a redraw with recalculations
1443 public void EnsureVisible (int index)
1445 if (index < 0 || index >= this.items.Count || this.scrollable == false)
1448 // dimensions of visible area
1449 int view_wd = this.Width - (this.v_scroll.Visible ? this.v_scroll.Width : 0);
1450 int view_ht = this.Height - (this.h_scroll.Visible ? this.h_scroll.Height : 0);
1451 // visible area is decided by the h_marker and v_marker
1452 Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1454 // an item's bounding rect
1455 Rectangle rect = this.items [index].EntireRect;
1457 // we don't need to do anything if item is visible.
1458 // visible area is represented by (0,0,view_wd,view_ht)
1459 if (view_rect.Contains (rect))
1462 // Scroll Left or Up
1463 if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1464 if (rect.Left < view_rect.Left)
1465 this.h_scroll.Value -= (view_rect.Left - rect.Left);
1466 if (rect.Top < view_rect.Top)
1467 this.v_scroll.Value -= (view_rect.Top - rect.Top);
1469 // Scroll Right or Down
1471 if (rect.Right > view_rect.Right)
1472 this.h_scroll.Value += (rect.Right - view_rect.Right);
1473 if (rect.Bottom > view_rect.Bottom)
1474 this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1478 public ListViewItem GetItemAt (int x, int y)
1480 foreach (ListViewItem item in items) {
1481 if (item.Bounds.Contains (x, y))
1487 public Rectangle GetItemRect (int index)
1489 return GetItemRect (index, ItemBoundsPortion.Entire);
1492 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1494 if (index < 0 || index >= items.Count)
1495 throw new IndexOutOfRangeException ("Invalid Index");
1497 return items [index].GetBounds (portion);
1502 if (sort_order != SortOrder.None)
1503 items.list.Sort (item_sorter);
1505 if (sort_order == SortOrder.Descending)
1506 items.list.Reverse ();
1511 public override string ToString ()
1513 int count = this.Items.Count;
1516 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1518 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1520 #endregion // Public Instance Methods
1524 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1526 internal ArrayList list;
1527 private ListView owner;
1529 #region Public Constructor
1530 public CheckedIndexCollection (ListView owner)
1532 list = new ArrayList ();
1535 #endregion // Public Constructor
1537 #region Public Properties
1539 public virtual int Count {
1540 get { return list.Count; }
1543 public virtual bool IsReadOnly {
1544 get { return true; }
1547 public int this [int index] {
1549 if (index < 0 || index >= list.Count)
1550 throw new ArgumentOutOfRangeException ("Index out of range.");
1551 return (int) list [index];
1555 bool ICollection.IsSynchronized {
1556 get { return list.IsSynchronized; }
1559 object ICollection.SyncRoot {
1560 get { return list.SyncRoot; }
1563 bool IList.IsFixedSize {
1564 get { return list.IsFixedSize; }
1567 object IList.this [int index] {
1568 get { return this [index]; }
1569 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1571 #endregion // Public Properties
1573 #region Public Methods
1574 public bool Contains (int checkedIndex)
1576 return list.Contains (checkedIndex);
1579 public virtual IEnumerator GetEnumerator ()
1581 return list.GetEnumerator ();
1584 void ICollection.CopyTo (Array dest, int index)
1586 list.CopyTo (dest, index);
1589 int IList.Add (object value)
1591 throw new NotSupportedException ("Add operation is not supported.");
1596 throw new NotSupportedException ("Clear operation is not supported.");
1599 bool IList.Contains (object checkedIndex)
1601 return list.Contains (checkedIndex);
1604 int IList.IndexOf (object checkedIndex)
1606 return list.IndexOf (checkedIndex);
1609 void IList.Insert (int index, object value)
1611 throw new NotSupportedException ("Insert operation is not supported.");
1614 void IList.Remove (object value)
1616 throw new NotSupportedException ("Remove operation is not supported.");
1619 void IList.RemoveAt (int index)
1621 throw new NotSupportedException ("RemoveAt operation is not supported.");
1624 public int IndexOf (int checkedIndex)
1626 return list.IndexOf (checkedIndex);
1628 #endregion // Public Methods
1630 } // CheckedIndexCollection
1632 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1634 internal ArrayList list;
1635 private ListView owner;
1637 #region Public Constructor
1638 public CheckedListViewItemCollection (ListView owner)
1640 list = new ArrayList ();
1643 #endregion // Public Constructor
1645 #region Public Properties
1647 public virtual int Count {
1648 get { return list.Count; }
1651 public virtual bool IsReadOnly {
1652 get { return true; }
1655 public ListViewItem this [int index] {
1657 if (index < 0 || index >= list.Count)
1658 throw new ArgumentOutOfRangeException ("Index out of range.");
1659 return (ListViewItem) list [index];
1663 bool ICollection.IsSynchronized {
1664 get { return list.IsSynchronized; }
1667 object ICollection.SyncRoot {
1668 get { return list.SyncRoot; }
1671 bool IList.IsFixedSize {
1672 get { return list.IsFixedSize; }
1675 object IList.this [int index] {
1676 get { return this [index]; }
1677 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1679 #endregion // Public Properties
1681 #region Public Methods
1682 public bool Contains (ListViewItem item)
1684 return list.Contains (item);
1687 public virtual void CopyTo (Array dest, int index)
1689 list.CopyTo (dest, index);
1692 public virtual IEnumerator GetEnumerator ()
1694 return list.GetEnumerator ();
1697 int IList.Add (object value)
1699 throw new NotSupportedException ("Add operation is not supported.");
1704 throw new NotSupportedException ("Clear operation is not supported.");
1707 bool IList.Contains (object item)
1709 return list.Contains (item);
1712 int IList.IndexOf (object item)
1714 return list.IndexOf (item);
1717 void IList.Insert (int index, object value)
1719 throw new NotSupportedException ("Insert operation is not supported.");
1722 void IList.Remove (object value)
1724 throw new NotSupportedException ("Remove operation is not supported.");
1727 void IList.RemoveAt (int index)
1729 throw new NotSupportedException ("RemoveAt operation is not supported.");
1732 public int IndexOf (ListViewItem item)
1734 return list.IndexOf (item);
1736 #endregion // Public Methods
1738 } // CheckedListViewItemCollection
1740 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1742 internal ArrayList list;
1743 private ListView owner;
1745 #region Public Constructor
1746 public ColumnHeaderCollection (ListView owner)
1748 list = new ArrayList ();
1751 #endregion // Public Constructor
1753 #region Public Properties
1755 public virtual int Count {
1756 get { return list.Count; }
1759 public virtual bool IsReadOnly {
1760 get { return false; }
1763 public virtual ColumnHeader this [int index] {
1765 if (index < 0 || index >= list.Count)
1766 throw new ArgumentOutOfRangeException ("Index out of range.");
1767 return (ColumnHeader) list [index];
1771 bool ICollection.IsSynchronized {
1772 get { return list.IsSynchronized; }
1775 object ICollection.SyncRoot {
1776 get { return list.SyncRoot; }
1779 bool IList.IsFixedSize {
1780 get { return list.IsFixedSize; }
1783 object IList.this [int index] {
1784 get { return this [index]; }
1785 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1787 #endregion // Public Properties
1789 #region Public Methods
1790 public virtual int Add (ColumnHeader value)
1793 value.owner = this.owner;
1794 idx = list.Add (value);
1795 owner.Redraw (true);
1799 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1801 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1802 this.Add (colHeader);
1806 public virtual void AddRange (ColumnHeader [] values)
1808 foreach (ColumnHeader colHeader in values) {
1809 colHeader.owner = this.owner;
1813 owner.Redraw (true);
1816 public virtual void Clear ()
1819 owner.Redraw (true);
1822 public bool Contains (ColumnHeader value)
1824 return list.Contains (value);
1827 public virtual IEnumerator GetEnumerator ()
1829 return list.GetEnumerator ();
1832 void ICollection.CopyTo (Array dest, int index)
1834 list.CopyTo (dest, index);
1837 int IList.Add (object value)
1839 if (! (value is ColumnHeader)) {
1840 throw new ArgumentException ("Not of type ColumnHeader", "value");
1843 return this.Add ((ColumnHeader) value);
1846 bool IList.Contains (object value)
1848 if (! (value is ColumnHeader)) {
1849 throw new ArgumentException ("Not of type ColumnHeader", "value");
1852 return this.Contains ((ColumnHeader) value);
1855 int IList.IndexOf (object value)
1857 if (! (value is ColumnHeader)) {
1858 throw new ArgumentException ("Not of type ColumnHeader", "value");
1861 return this.IndexOf ((ColumnHeader) value);
1864 void IList.Insert (int index, object value)
1866 if (! (value is ColumnHeader)) {
1867 throw new ArgumentException ("Not of type ColumnHeader", "value");
1870 this.Insert (index, (ColumnHeader) value);
1873 void IList.Remove (object value)
1875 if (! (value is ColumnHeader)) {
1876 throw new ArgumentException ("Not of type ColumnHeader", "value");
1879 this.Remove ((ColumnHeader) value);
1882 public int IndexOf (ColumnHeader value)
1884 return list.IndexOf (value);
1887 public void Insert (int index, ColumnHeader value)
1889 if (index < 0 || index >= list.Count)
1890 throw new ArgumentOutOfRangeException ("Index out of range.");
1892 value.owner = this.owner;
1893 list.Insert (index, value);
1894 owner.Redraw (true);
1897 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1899 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1900 this.Insert (index, colHeader);
1903 public virtual void Remove (ColumnHeader column)
1905 // TODO: Update Column internal index ?
1906 list.Remove (column);
1907 owner.Redraw (true);
1910 public virtual void RemoveAt (int index)
1912 if (index < 0 || index >= list.Count)
1913 throw new ArgumentOutOfRangeException ("Index out of range.");
1915 // TODO: Update Column internal index ?
1916 list.RemoveAt (index);
1917 owner.Redraw (true);
1919 #endregion // Public Methods
1922 } // ColumnHeaderCollection
1924 public class ListViewItemCollection : IList, ICollection, IEnumerable
1926 internal ArrayList list;
1927 private ListView owner;
1929 #region Public Constructor
1930 public ListViewItemCollection (ListView owner)
1932 list = new ArrayList ();
1935 #endregion // Public Constructor
1937 #region Public Properties
1939 public virtual int Count {
1940 get { return list.Count; }
1943 public virtual bool IsReadOnly {
1944 get { return false; }
1947 public virtual ListViewItem this [int displayIndex] {
1949 if (displayIndex < 0 || displayIndex >= list.Count)
1950 throw new ArgumentOutOfRangeException ("Index out of range.");
1951 return (ListViewItem) list [displayIndex];
1955 if (displayIndex < 0 || displayIndex >= list.Count)
1956 throw new ArgumentOutOfRangeException ("Index out of range.");
1958 if (list.Contains (value))
1959 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1961 value.owner = this.owner;
1962 list [displayIndex] = value;
1964 owner.Redraw (true);
1968 bool ICollection.IsSynchronized {
1969 get { return list.IsSynchronized; }
1972 object ICollection.SyncRoot {
1973 get { return list.SyncRoot; }
1976 bool IList.IsFixedSize {
1977 get { return list.IsFixedSize; }
1980 object IList.this [int index] {
1981 get { return this [index]; }
1983 if (value is ListViewItem)
1984 this [index] = (ListViewItem) value;
1986 this [index] = new ListViewItem (value.ToString ());
1989 #endregion // Public Properties
1991 #region Public Methods
1992 public virtual ListViewItem Add (ListViewItem value)
1994 if (list.Contains (value))
1995 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
1997 value.owner = this.owner;
2000 if (owner.Sorting != SortOrder.None)
2003 owner.Redraw (true);
2008 public virtual ListViewItem Add (string text)
2010 ListViewItem item = new ListViewItem (text);
2011 return this.Add (item);
2014 public virtual ListViewItem Add (string text, int imageIndex)
2016 ListViewItem item = new ListViewItem (text, imageIndex);
2017 return this.Add (item);
2020 public void AddRange (ListViewItem [] values)
2024 foreach (ListViewItem item in values) {
2025 item.owner = this.owner;
2029 if (owner.Sorting != SortOrder.None)
2032 owner.Redraw (true);
2035 public virtual void Clear ()
2040 public bool Contains (ListViewItem item)
2042 return list.Contains (item);
2045 public virtual void CopyTo (Array dest, int index)
2047 list.CopyTo (dest, index);
2050 public virtual IEnumerator GetEnumerator ()
2052 return list.GetEnumerator ();
2055 int IList.Add (object item)
2060 if (item is ListViewItem) {
2061 li = (ListViewItem) item;
2062 if (list.Contains (li))
2063 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2066 li = new ListViewItem (item.ToString ());
2068 li.owner = this.owner;
2069 result = list.Add (li);
2070 owner.Redraw (true);
2075 bool IList.Contains (object item)
2077 return list.Contains (item);
2080 int IList.IndexOf (object item)
2082 return list.IndexOf (item);
2085 void IList.Insert (int index, object item)
2087 if (item is ListViewItem)
2088 this.Insert (index, (ListViewItem) item);
2090 this.Insert (index, item.ToString ());
2093 void IList.Remove (object item)
2095 if (list.Contains (item)) {
2097 owner.Redraw (true);
2101 public int IndexOf (ListViewItem item)
2103 return list.IndexOf (item);
2106 public ListViewItem Insert (int index, ListViewItem item)
2108 if (index < 0 || index >= list.Count)
2109 throw new ArgumentOutOfRangeException ("Index out of range.");
2111 if (list.Contains (item))
2112 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2114 item.owner = this.owner;
2115 list.Insert (index, item);
2116 owner.Redraw (true);
2120 public ListViewItem Insert (int index, string text)
2122 return this.Insert (index, new ListViewItem (text));
2125 public ListViewItem Insert (int index, string text, int imageIndex)
2127 return this.Insert (index, new ListViewItem (text, imageIndex));
2130 public virtual void Remove (ListViewItem item)
2132 if (list.Contains (item)) {
2134 owner.Redraw (true);
2138 public virtual void RemoveAt (int index)
2140 if (index < 0 || index >= list.Count)
2141 throw new ArgumentOutOfRangeException ("Index out of range.");
2143 list.RemoveAt (index);
2144 owner.Redraw (false);
2146 #endregion // Public Methods
2148 } // ListViewItemCollection
2150 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2152 internal ArrayList list;
2153 private ListView owner;
2155 #region Public Constructor
2156 public SelectedIndexCollection (ListView owner)
2158 list = new ArrayList ();
2161 #endregion // Public Constructor
2163 #region Public Properties
2165 public virtual int Count {
2166 get { return list.Count; }
2169 public virtual bool IsReadOnly {
2170 get { return true; }
2173 public int this [int index] {
2175 if (index < 0 || index >= list.Count)
2176 throw new ArgumentOutOfRangeException ("Index out of range.");
2177 return (int) list [index];
2181 bool ICollection.IsSynchronized {
2182 get { return list.IsSynchronized; }
2185 object ICollection.SyncRoot {
2186 get { return list.SyncRoot; }
2189 bool IList.IsFixedSize {
2190 get { return list.IsFixedSize; }
2193 object IList.this [int index] {
2194 get { return this [index]; }
2195 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2197 #endregion // Public Properties
2199 #region Public Methods
2200 public bool Contains (int selectedIndex)
2202 return list.Contains (selectedIndex);
2205 public virtual void CopyTo (Array dest, int index)
2207 list.CopyTo (dest, index);
2210 public virtual IEnumerator GetEnumerator ()
2212 return list.GetEnumerator ();
2215 int IList.Add (object value)
2217 throw new NotSupportedException ("Add operation is not supported.");
2222 throw new NotSupportedException ("Clear operation is not supported.");
2225 bool IList.Contains (object selectedIndex)
2227 return list.Contains (selectedIndex);
2230 int IList.IndexOf (object selectedIndex)
2232 return list.IndexOf (selectedIndex);
2235 void IList.Insert (int index, object value)
2237 throw new NotSupportedException ("Insert operation is not supported.");
2240 void IList.Remove (object value)
2242 throw new NotSupportedException ("Remove operation is not supported.");
2245 void IList.RemoveAt (int index)
2247 throw new NotSupportedException ("RemoveAt operation is not supported.");
2250 public int IndexOf (int selectedIndex)
2252 return list.IndexOf (selectedIndex);
2254 #endregion // Public Methods
2256 } // SelectedIndexCollection
2258 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2260 internal ArrayList list;
2261 private ListView owner;
2263 #region Public Constructor
2264 public SelectedListViewItemCollection (ListView owner)
2266 list = new ArrayList ();
2269 #endregion // Public Constructor
2271 #region Public Properties
2273 public virtual int Count {
2274 get { return list.Count; }
2277 public virtual bool IsReadOnly {
2278 get { return true; }
2281 public ListViewItem this [int index] {
2283 if (index < 0 || index >= list.Count)
2284 throw new ArgumentOutOfRangeException ("Index out of range.");
2285 return (ListViewItem) list [index];
2289 bool ICollection.IsSynchronized {
2290 get { return list.IsSynchronized; }
2293 object ICollection.SyncRoot {
2294 get { return list.SyncRoot; }
2297 bool IList.IsFixedSize {
2298 get { return list.IsFixedSize; }
2301 object IList.this [int index] {
2302 get { return this [index]; }
2303 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2305 #endregion // Public Properties
2307 #region Public Methods
2308 public virtual void Clear ()
2310 // mark the items as unselected before clearing the list
2311 for (int i = 0; i < list.Count; i++)
2312 ((ListViewItem) list [i]).selected = false;
2317 public bool Contains (ListViewItem item)
2319 return list.Contains (item);
2322 public virtual void CopyTo (Array dest, int index)
2324 list.CopyTo (dest, index);
2327 public virtual IEnumerator GetEnumerator ()
2329 return list.GetEnumerator ();
2332 int IList.Add (object value)
2334 throw new NotSupportedException ("Add operation is not supported.");
2337 bool IList.Contains (object item)
2339 return list.Contains (item);
2342 int IList.IndexOf (object item)
2344 return list.IndexOf (item);
2347 void IList.Insert (int index, object value)
2349 throw new NotSupportedException ("Insert operation is not supported.");
2352 void IList.Remove (object value)
2354 throw new NotSupportedException ("Remove operation is not supported.");
2357 void IList.RemoveAt (int index)
2359 throw new NotSupportedException ("RemoveAt operation is not supported.");
2362 public int IndexOf (ListViewItem item)
2364 return list.IndexOf (item);
2366 #endregion // Public Methods
2368 } // SelectedListViewItemCollection
2370 #endregion // Subclasses