1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc. (http://www.novell.com)
23 // Ravindra Kumar (rkumar@novell.com)
24 // Jordi Mas i Hernandez, jordi@ximian.com
27 // - Item text editing
28 // - Column resizing/reodering
29 // - Feedback for item activation, change in cursor types as mouse moves.
32 // - Manual column resizing
39 using System.Collections;
40 using System.ComponentModel;
41 using System.ComponentModel.Design;
43 using System.Runtime.InteropServices;
44 using System.Globalization;
46 namespace System.Windows.Forms
48 [DefaultEvent ("SelectedIndexChanged")]
49 [DefaultProperty ("Items")]
50 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
51 public class ListView : Control
53 private ItemActivation activation = ItemActivation.Standard;
54 private ListViewAlignment alignment = ListViewAlignment.Top;
55 private bool allow_column_reorder = false;
56 private bool auto_arrange = true;
57 private bool check_boxes = false;
58 private CheckedIndexCollection checked_indices;
59 private CheckedListViewItemCollection checked_items;
60 private ColumnHeader clicked_column;
61 private ListViewItem clicked_item;
62 private ListViewItem last_clicked_item;
63 private ColumnHeaderCollection columns;
64 private bool ctrl_pressed;
65 private bool shift_pressed;
66 internal ListViewItem focused_item;
67 private bool full_row_select = false;
68 private bool grid_lines = false;
69 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
70 private bool hide_selection = true;
71 private bool hover_selection = false;
72 private IComparer item_sorter;
73 private ListViewItemCollection items;
74 private bool label_edit = false;
75 private bool label_wrap = true;
76 private bool multiselect = true;
77 private bool scrollable = true;
78 private SelectedIndexCollection selected_indices;
79 private SelectedListViewItemCollection selected_items;
80 private SortOrder sort_order = SortOrder.None;
81 private ImageList state_image_list;
82 private bool updating = false;
83 private View view = View.LargeIcon;
84 private int layout_wd; // We might draw more than our client area
85 private int layout_ht; // therefore we need to have these two.
86 //private TextBox editor; // Used for editing an item text
87 internal ScrollBar h_scroll; // used for scrolling horizontally
88 internal ScrollBar v_scroll; // used for scrolling vertically
89 internal int h_marker; // Position markers for scrolling
90 internal int v_marker;
91 internal Rectangle client_area; // ClientRectangle - scrollbars
92 private int keysearch_tickcnt;
93 private string keysearch_text;
94 static private readonly int keysearch_keydelay = 1000;
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;
143 keysearch_tickcnt = 0;
145 // scroll bars are disabled initially
146 h_scroll.Visible = false;
147 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
148 v_scroll.Visible = false;
149 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
152 base.DoubleClick += new EventHandler(ListView_DoubleClick);
153 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
154 base.KeyUp += new KeyEventHandler(ListView_KeyUp);
155 base.MouseDown += new MouseEventHandler(ListView_MouseDown);
156 base.MouseHover += new EventHandler(ListView_MouseHover);
157 base.MouseUp += new MouseEventHandler(ListView_MouseUp);
158 base.MouseMove += new MouseEventHandler(ListView_MouseMove);
159 base.Paint += new PaintEventHandler (ListView_Paint);
160 SizeChanged += new EventHandler (ListView_SizeChanged);
162 this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
164 #endregion // Public Constructors
166 #region Private Internal Properties
167 internal Size CheckBoxSize {
169 if (this.check_boxes) {
170 if (this.state_image_list != null)
171 return this.state_image_list.ImageSize;
173 return ThemeEngine.Current.ListViewCheckBoxSize;
179 internal bool CanMultiselect {
181 if (this.multiselect &&
182 (this.ctrl_pressed || this.shift_pressed))
188 #endregion // Private Internal Properties
190 #region Protected Properties
191 protected override CreateParams CreateParams {
192 get { return base.CreateParams; }
195 protected override Size DefaultSize {
196 get { return ThemeEngine.Current.ListViewDefaultSize; }
198 #endregion // Protected Properties
200 #region Public Instance Properties
201 [DefaultValue (ItemActivation.Standard)]
202 public ItemActivation Activation {
203 get { return activation; }
205 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
206 value != ItemActivation.TwoClick) {
207 throw new InvalidEnumArgumentException (string.Format
208 ("Enum argument value '{0}' is not valid for Activation", value));
215 [DefaultValue (ListViewAlignment.Top)]
217 public ListViewAlignment Alignment {
218 get { return alignment; }
220 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
221 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
222 throw new InvalidEnumArgumentException (string.Format
223 ("Enum argument value '{0}' is not valid for Alignment", value));
226 if (this.alignment != value) {
228 // alignment does not matter in Details/List views
229 if (this.view == View.LargeIcon ||
230 this.View == View.SmallIcon)
236 [DefaultValue (false)]
237 public bool AllowColumnReorder {
238 get { return allow_column_reorder; }
240 if (this.allow_column_reorder != value) {
241 allow_column_reorder = value;
242 // column reorder does not matter in Details view
243 if (this.view != View.Details)
249 [DefaultValue (true)]
250 public bool AutoArrange {
251 get { return auto_arrange; }
253 if (auto_arrange != value) {
254 auto_arrange = value;
255 // autoarrange does not matter in Details/List views
256 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
262 public override Color BackColor {
264 if (background_color.IsEmpty)
265 return ThemeEngine.Current.ColorWindow;
267 return background_color;
269 set { background_color = value; }
273 [EditorBrowsable (EditorBrowsableState.Never)]
274 public override Image BackgroundImage {
275 get { return background_image; }
277 if (value == background_image)
280 background_image = value;
281 if (BackgroundImageChanged != null)
282 BackgroundImageChanged (this, new EventArgs ());
286 [DefaultValue (BorderStyle.Fixed3D)]
288 public BorderStyle BorderStyle {
289 get { return InternalBorderStyle; }
290 set { InternalBorderStyle = value; }
293 [DefaultValue (false)]
294 public bool CheckBoxes {
295 get { return check_boxes; }
297 if (check_boxes != value) {
305 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
306 public CheckedIndexCollection CheckedIndices {
307 get { return checked_indices; }
311 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
312 public CheckedListViewItemCollection CheckedItems {
313 get { return checked_items; }
316 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
318 [MergableProperty (false)]
319 public ColumnHeaderCollection Columns {
320 get { return columns; }
324 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
325 public ListViewItem FocusedItem {
326 get { return focused_item; }
329 public override Color ForeColor {
331 if (foreground_color.IsEmpty)
332 return ThemeEngine.Current.ColorWindowText;
334 return foreground_color;
336 set { foreground_color = value; }
339 [DefaultValue (false)]
340 public bool FullRowSelect {
341 get { return full_row_select; }
342 set { full_row_select = value; }
345 [DefaultValue (false)]
346 public bool GridLines {
347 get { return grid_lines; }
349 if (grid_lines != value) {
356 [DefaultValue (ColumnHeaderStyle.Clickable)]
357 public ColumnHeaderStyle HeaderStyle {
358 get { return header_style; }
360 if (value != ColumnHeaderStyle.Clickable && value != ColumnHeaderStyle.Nonclickable &&
361 value != ColumnHeaderStyle.None) {
362 throw new InvalidEnumArgumentException (string.Format
363 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
366 if (header_style != value) {
367 header_style = value;
368 // header style matters only in Details view
369 if (this.view == View.Details)
375 [DefaultValue (true)]
376 public bool HideSelection {
377 get { return hide_selection; }
379 if (hide_selection != value) {
380 hide_selection = value;
386 [DefaultValue (false)]
387 public bool HoverSelection {
388 get { return hover_selection; }
389 set { hover_selection = value; }
392 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
394 [MergableProperty (false)]
395 public ListViewItemCollection Items {
396 get { return items; }
399 [DefaultValue (false)]
400 public bool LabelEdit {
401 get { return label_edit; }
402 set { label_edit = value; }
405 [DefaultValue (true)]
407 public bool LabelWrap {
408 get { return label_wrap; }
410 if (label_wrap != value) {
417 [DefaultValue (null)]
418 public ImageList LargeImageList {
419 get { return large_image_list; }
421 large_image_list = value;
427 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
428 public IComparer ListViewItemSorter {
429 get { return item_sorter; }
430 set { item_sorter = value; }
433 [DefaultValue (true)]
434 public bool MultiSelect {
435 get { return multiselect; }
436 set { multiselect = value; }
439 [DefaultValue (true)]
440 public bool Scrollable {
441 get { return scrollable; }
443 if (scrollable != value) {
451 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
452 public SelectedIndexCollection SelectedIndices {
453 get { return selected_indices; }
457 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
458 public SelectedListViewItemCollection SelectedItems {
459 get { return selected_items; }
462 [DefaultValue (null)]
463 public ImageList SmallImageList {
464 get { return small_image_list; }
466 small_image_list = value;
471 [DefaultValue (SortOrder.None)]
472 public SortOrder Sorting {
473 get { return sort_order; }
475 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
476 value != SortOrder.None) {
477 throw new InvalidEnumArgumentException (string.Format
478 ("Enum argument value '{0}' is not valid for Sorting", value));
481 if (sort_order != value) {
488 [DefaultValue (null)]
489 public ImageList StateImageList {
490 get { return state_image_list; }
492 state_image_list = value;
499 [EditorBrowsable (EditorBrowsableState.Never)]
500 public override string Text {
509 if (TextChanged != null)
510 TextChanged (this, new EventArgs ());
515 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
516 public ListViewItem TopItem {
519 if (this.items.Count == 0)
521 // if contents are not scrolled
522 // it is the first item
523 else if (h_marker == 0 && v_marker == 0)
524 return this.items [0];
525 // do a hit test for the scrolled position
527 foreach (ListViewItem item in this.items) {
528 if (item.EntireRect.X >= h_marker && item.EntireRect.Y >= v_marker)
536 [DefaultValue (View.LargeIcon)]
540 if (value != View.Details && value != View.LargeIcon &&
541 value != View.List && value != View.SmallIcon ) {
542 throw new InvalidEnumArgumentException (string.Format
543 ("Enum argument value '{0}' is not valid for View", value));
547 h_scroll.Value = v_scroll.Value = 0;
553 #endregion // Public Instance Properties
555 #region Internal Methods Properties
557 internal int FirstVisibleIndex {
560 if (this.items.Count == 0)
563 if (h_marker == 0 && v_marker == 0)
566 foreach (ListViewItem item in this.items) {
567 if (item.EntireRect.X + item.EntireRect.Width >= h_marker
568 && item.EntireRect.Y + item.EntireRect.Height >= v_marker)
577 internal int LastItemIndex {
579 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
580 if (Items[i].EntireRect.Y > v_marker + ClientRectangle.Bottom)
584 return Items.Count - 1;
588 internal int TotalWidth {
589 get { return Math.Max (this.Width, this.layout_wd); }
592 internal int TotalHeight {
593 get { return Math.Max (this.Height, this.layout_ht); }
596 internal void Redraw (bool recalculate)
598 // Avoid calculations when control is being updated
603 CalculateListView (this.alignment);
608 internal Size GetChildColumnSize (int index)
610 Size ret_size = Size.Empty;
611 ColumnHeader col = this.columns [index];
613 if (col.Width == -2) { // autosize = max(items, columnheader)
614 Size size = Size.Ceiling (this.DeviceContext.MeasureString
615 (col.Text, this.Font));
616 ret_size = BiggestItem (index);
617 if (size.Width > ret_size.Width)
620 else { // -1 and all the values < -2 are put under one category
621 ret_size = BiggestItem (index);
622 // fall back to empty columns' width if no subitem is available for a column
623 if (ret_size.IsEmpty) {
624 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
625 if (col.Text.Length > 0)
626 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
627 (col.Text, this.Font)).Height;
629 ret_size.Height = this.Font.Height;
633 // adjust the size for icon and checkbox for 0th column
635 ret_size.Width += (this.CheckBoxSize.Width + 4);
636 if (this.small_image_list != null)
637 ret_size.Width += this.small_image_list.ImageSize.Width;
642 // Returns the size of biggest item text in a column.
643 private Size BiggestItem (int col)
645 Size temp = Size.Empty;
646 Size ret_size = Size.Empty;
648 // 0th column holds the item text, we check the size of
649 // the various subitems falling in that column and get
650 // the biggest one's size.
651 foreach (ListViewItem item in items) {
652 if (col >= item.SubItems.Count)
655 temp = Size.Ceiling (this.DeviceContext.MeasureString
656 (item.SubItems [col].Text, this.Font));
657 if (temp.Width > ret_size.Width)
661 // adjustment for space
662 if (!ret_size.IsEmpty)
668 // Sets the size of the biggest item text as per the view
669 private void CalcTextSize ()
671 // clear the old value
672 text_size = Size.Empty;
674 if (items.Count == 0)
677 text_size = BiggestItem (0);
679 if (view == View.LargeIcon && this.label_wrap) {
680 Size temp = Size.Empty;
681 if (this.check_boxes)
682 temp.Width += 2 * this.CheckBoxSize.Width;
683 if (large_image_list != null)
684 temp.Width += large_image_list.ImageSize.Width;
687 // wrapping is done for two lines only
688 if (text_size.Width > temp.Width) {
689 text_size.Width = temp.Width;
690 text_size.Height *= 2;
693 else if (view == View.List) {
694 // in list view max text shown in determined by the
695 // control width, even if scolling is enabled.
696 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
697 if (this.small_image_list != null)
698 max_wd -= this.small_image_list.ImageSize.Width;
700 if (text_size.Width > max_wd)
701 text_size.Width = max_wd;
704 // we do the default settings, if we have got 0's
705 if (text_size.Height <= 0)
706 text_size.Height = this.Font.Height;
707 if (text_size.Width <= 0)
708 text_size.Width = this.Width;
711 text_size.Width += 4;
712 text_size.Height += 2;
715 private void CalculateScrollBars ()
717 client_area = ClientRectangle;
719 if (!this.scrollable || this.items.Count <= 0) {
720 h_scroll.Visible = false;
721 v_scroll.Visible = false;
725 // making a scroll bar visible might make
726 // other scroll bar visible
727 if (layout_wd > client_area.Right) {
728 h_scroll.Visible = true;
729 if ((layout_ht + h_scroll.Height) > client_area.Bottom) {
730 v_scroll.Visible = true;
733 v_scroll.Visible = false;
735 } else if (layout_ht > client_area.Bottom) {
736 v_scroll.Visible = true;
737 if ((layout_wd + v_scroll.Width) > client_area.Right) {
738 h_scroll.Visible = true;
741 h_scroll.Visible = false;
744 h_scroll.Visible = false;
745 v_scroll.Visible = false;
748 if (h_scroll.Visible) {
749 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
750 h_scroll.Minimum = 0;
752 // if v_scroll is visible, adjust the maximum of the
753 // h_scroll to account for the width of v_scroll
754 if (v_scroll.Visible) {
755 h_scroll.Maximum = layout_wd + v_scroll.Width;
756 h_scroll.Width = client_area.Width - v_scroll.Width;
759 h_scroll.Maximum = layout_wd;
760 h_scroll.Width = client_area.Width;
763 h_scroll.LargeChange = client_area.Width;
764 h_scroll.SmallChange = Font.Height;
765 client_area.Height -= h_scroll.Height;
768 // vertical scrollbar
769 if (v_scroll.Visible) {
770 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
771 v_scroll.Minimum = 0;
773 // if h_scroll is visible, adjust the maximum of the
774 // v_scroll to account for the height of h_scroll
775 if (h_scroll.Visible) {
776 v_scroll.Maximum = layout_ht + h_scroll.Height;
777 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
779 v_scroll.Maximum = layout_ht;
780 v_scroll.Height = client_area.Height;
783 v_scroll.LargeChange = client_area.Height;
784 v_scroll.SmallChange = Font.Height;
785 client_area.Width -= v_scroll.Width;
790 // Sets the location of every item on
791 // the ListView as per the view
792 private void CalculateListView (ListViewAlignment align)
794 int current_pos_x = 0; // our x-position marker
795 int current_pos_y = 0; // our y-position marker
798 int max; // max x_pos or y_pos depending on the alignment
799 int current = 0; // current row or column
800 int vertical_spacing = ThemeEngine.Current.ListViewVerticalSpacing;
801 int horizontal_spacing = ThemeEngine.Current.ListViewHorizontalSpacing;
808 // ColumnHeaders are not drawn if headerstyle is none
809 int ht = (this.header_style == ColumnHeaderStyle.None) ?
810 0 : this.Font.Height + 3;
812 if (columns.Count > 0) {
813 foreach (ColumnHeader col in columns) {
814 col.X = current_pos_x;
815 col.Y = current_pos_y;
816 col.CalcColumnHeader ();
817 current_pos_x += col.Wd;
819 this.layout_wd = current_pos_x;
821 // set the position marker for placing items
825 if (items.Count > 0) {
826 foreach (ListViewItem item in items) {
828 item.location.Y = current_pos_y;
829 item.CalcListViewItem ();
830 current_pos_y += item.EntireRect.Height;
832 this.layout_ht = current_pos_y;
834 // some space for bottom gridline
841 vertical_spacing = 0;
842 horizontal_spacing = 0;
843 goto case View.LargeIcon;
846 if (items.Count > 0) {
847 items [0].CalcListViewItem ();
848 item_ht = items [0].EntireRect.Height;
849 item_wd = items [0].EntireRect.Width;
851 // top (default) and snaptogrid alignments are handled same way
852 if (align == ListViewAlignment.Left) {
853 max = client_area.Height;
854 foreach (ListViewItem item in items) {
855 item.location.X = current_pos_x +
858 item.CalcListViewItem ();
859 current_pos_y += item_ht;
861 current ++; // just to know about the last element
862 // we just did the last item
863 if (current == items.Count) {
864 if (max < current_pos_y)
866 current_pos_x = item.EntireRect.Right;
870 // is there enough space for another row ?
871 if ((current_pos_y + vertical_spacing
872 + item_ht) <= client_area.Height)
873 current_pos_y += vertical_spacing;
875 // start another column
876 // make current_pos_y as the
877 // max value and reset
878 // current_pos_y value.
880 current_pos_x += item_wd;
885 // adjust the layout dimensions
886 this.layout_ht = max;
887 this.layout_wd = current_pos_x;
889 else { // other default/top alignment
890 max = client_area.Width;
891 foreach (ListViewItem item in items) {
892 item.location.X = current_pos_x +
895 item.location.Y = current_pos_y;
896 item.CalcListViewItem ();
897 current_pos_x += item_wd;
899 current ++; // just to know about the last element
900 // we just did the last item
901 if (current == items.Count) {
902 if (max < current_pos_x)
904 current_pos_y = item.EntireRect.Bottom;
908 // is there enough space for another column?
909 if ((current_pos_x + horizontal_spacing
910 + item_wd) <= client_area.Width)
914 // make current_pos_x as the
915 // max value and reset
916 // current_pos_x value.
918 current_pos_y += (item_ht +
924 // adjust the layout dimensions
925 this.layout_wd = max;
926 this.layout_ht = current_pos_y;
932 if (items.Count > 0) {
933 items [0].CalcListViewItem ();
934 item_ht = items [0].EntireRect.Height;
935 item_wd = items [0].EntireRect.Width;
937 max = client_area.Height / item_ht;
939 max = 1; // we draw at least one row
941 foreach (ListViewItem item in items) {
942 item.location.X = current_pos_x;
943 item.location.Y = current_pos_y;
944 item.CalcListViewItem ();
946 if (current == max) {
947 current_pos_x += item_wd;
952 current_pos_y += item_ht;
955 // adjust the layout dimensions
956 this.layout_ht = max * item_ht;
957 if (current == 0) // we have fully filled layout
958 this.layout_wd = current_pos_x;
960 this.layout_wd = current_pos_x + item_wd;
965 CalculateScrollBars ();
969 private bool KeySearchString (KeyEventArgs ke)
971 int current_tickcnt = Environment.TickCount;
972 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
973 keysearch_text = string.Empty;
976 keysearch_text += (char) ke.KeyData;
977 keysearch_tickcnt = current_tickcnt;
979 int i = FocusedItem.Index;
981 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
982 CompareOptions.IgnoreCase)) {
983 SetFocusedItem (Items [i]);
984 items [i].Selected = true;
988 i = (i + 1 < Items.Count) ? i+1 : 0;
990 if (i == FocusedItem.Index)
998 private void ListView_DoubleClick (object sender, EventArgs e)
1000 if (this.activation == ItemActivation.Standard
1001 && this.ItemActivate != null)
1002 this.ItemActivate (this, e);
1005 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1008 if (ke.Handled || Items.Count == 0)
1013 switch (ke.KeyCode) {
1015 case Keys.ControlKey:
1016 ctrl_pressed = true;
1020 if (focused_item != null && focused_item.Index + 1 < Items.Count) {
1021 index = focused_item.Index + 1;
1026 index = Items.Count - 1;
1035 if (focused_item != null)
1036 index = focused_item.Index;
1046 if (focused_item != null)
1047 index = focused_item.Index + 1;
1051 if (index == items.Count)
1057 shift_pressed = true;
1061 if (focused_item != null)
1062 index = focused_item.Index;
1075 if (KeySearchString (ke)) {
1084 items [index].Selected = true;
1085 SetFocusedItem (items [index]);
1086 EnsureVisible (index);
1090 private void ListView_KeyUp (object sender, KeyEventArgs ke)
1093 if (ke.KeyCode == Keys.ControlKey)
1094 this.ctrl_pressed = false;
1096 if (ke.KeyCode == Keys.ShiftKey)
1097 this.shift_pressed = false;
1102 private void ListView_MouseDown (object sender, MouseEventArgs me)
1104 if (items.Count == 0)
1107 Point hit = Point.Empty;
1108 if (this.HeaderStyle != ColumnHeaderStyle.None) {
1109 // take horizontal scrolling into account
1110 hit = new Point (me.X + h_marker, me.Y);
1112 // hit test on columns
1113 if (this.view == View.Details && this.columns.Count > 0) {
1114 foreach (ColumnHeader col in this.columns) {
1115 if (col.Rect.Contains (hit)) {
1116 this.clicked_column = col;
1117 this.Capture = true;
1122 if (this.clicked_column != null) {
1123 this.clicked_column.pressed = true;
1124 this.Redraw (false);
1130 // hit test on items
1131 // we need to take scrolling into account
1132 hit = new Point (me.X + h_marker, me.Y + v_marker);
1133 foreach (ListViewItem item in this.items) {
1134 if (item.CheckRect.Contains (hit)) {
1135 CheckState curr_state = item.Checked ?
1136 CheckState.Checked : CheckState.Unchecked;
1138 item.Checked = false;
1140 item.Checked = true;
1142 CheckState new_state = item.Checked ?
1143 CheckState.Checked : CheckState.Unchecked;
1144 this.Redraw (false);
1146 // Raise the ItemCheck event
1147 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index,
1150 this.OnItemCheck (ice);
1154 if (this.view == View.Details &&
1155 this.FullRowSelect == false) {
1156 if (item.LabelRect.Contains (hit)) {
1157 this.clicked_item = item;
1162 if (item.EntireRect.Contains (hit)) {
1163 this.clicked_item = item;
1169 // set the FocusedItem to be the current clicked_item
1170 SetFocusedItem (clicked_item);
1172 if (clicked_item != null) {
1173 bool changed = !clicked_item.Selected;
1174 clicked_item.Selected = true;
1176 // Only Raise the event if the selected item has changed
1178 OnSelectedIndexChanged (EventArgs.Empty);
1180 // Raise double click if the item was clicked. On MS the
1181 // double click is only raised if you double click an item
1182 if (me.Clicks > 1 && this.clicked_item != null)
1183 OnDoubleClick (EventArgs.Empty);
1184 else if (me.Clicks == 1 && clicked_item != null)
1185 OnClick (EventArgs.Empty);
1187 this.Redraw (false);
1188 } else if (selected_indices.Count > 0) {
1189 // NOTE: selected_indices isn't computed properly so
1190 // this doesn't actually work
1192 // Raise the event if there was at least one item
1193 // selected and the user click on a dead area (unselecting all)
1194 OnSelectedIndexChanged (EventArgs.Empty);
1199 private void ListView_MouseHover (object sender, EventArgs e)
1201 // handle the hover events only when the mouse
1203 if (this.hover_selection == false || this.Capture)
1206 // hit test for the items
1207 Point hit = this.PointToClient (Control.MousePosition);
1208 ListViewItem item = this.GetItemAt (hit.X, hit.Y);
1211 item.Selected = true;
1213 this.OnSelectedIndexChanged (new EventArgs ());
1215 this.Redraw (false);
1219 private void ListView_MouseMove (object sender, MouseEventArgs me)
1221 // Column header is always at the top. It can
1222 // scroll only horizontally. So, we have to take
1223 // only horizontal scrolling into account
1224 Point hit = new Point (me.X + h_marker, me.Y);
1226 // non-null clicked_col means mouse down has happened
1228 if (this.clicked_column != null) {
1229 if (this.clicked_column.pressed == false &&
1230 this.clicked_column.Rect.Contains (hit)) {
1231 this.clicked_column.pressed = true;
1232 this.Redraw (false);
1234 else if (this.clicked_column.pressed &&
1235 ! this.clicked_column.Rect.Contains (hit)) {
1236 this.clicked_column.pressed = false;
1237 this.Redraw (false);
1242 private void ListView_MouseUp (object sender, MouseEventArgs me)
1244 this.Capture = false;
1245 if (items.Count == 0)
1248 Point hit = new Point (me.X, me.Y);
1250 if (this.clicked_column != null) {
1251 if (this.clicked_column.pressed) {
1252 this.clicked_column.pressed = false;
1253 this.Redraw (false);
1255 // Raise the ColumnClick event
1256 this.OnColumnClick (new ColumnClickEventArgs
1257 (this.clicked_column.Index));
1261 // Raise the ItemActivate event
1262 Rectangle rect = Rectangle.Empty;
1263 if (this.clicked_item != null) {
1264 if (this.view == View.Details && !this.full_row_select)
1265 rect = this.clicked_item.LabelRect;
1267 rect = this.clicked_item.EntireRect;
1269 // We handle double click in a separate handler
1270 if (this.activation != ItemActivation.Standard &&
1271 rect.Contains (hit)) {
1272 if (this.activation == ItemActivation.OneClick)
1273 this.ItemActivate (this, EventArgs.Empty);
1275 // ItemActivate is raised on the second click on the same item
1276 else if (this.activation == ItemActivation.TwoClick) {
1277 if (this.last_clicked_item == this.clicked_item) {
1278 this.ItemActivate (this, EventArgs.Empty);
1279 this.last_clicked_item = null;
1282 this.last_clicked_item = this.clicked_item;
1287 this.clicked_column = null;
1288 this.clicked_item = null;
1291 private void ListView_Paint (object sender, PaintEventArgs pe)
1293 if (this.Width <= 0 || this.Height <= 0 ||
1294 this.Visible == false || this.updating == true)
1297 CalculateScrollBars ();
1299 ThemeEngine.Current.DrawListView (pe.Graphics,
1300 pe.ClipRectangle, this);
1302 // Raise the Paint event
1307 private void ListView_SizeChanged (object sender, EventArgs e)
1309 CalculateListView (alignment);
1312 private void SetFocusedItem (ListViewItem item)
1314 if (focused_item != null)
1315 focused_item.Focused = false;
1318 item.Focused = true;
1320 focused_item = item;
1323 private void HorizontalScroller (object sender, EventArgs e)
1325 // Avoid unnecessary flickering, when button is
1326 // kept pressed at the end
1327 if (h_marker != h_scroll.Value) {
1329 int pixels = h_marker - h_scroll.Value;
1330 Rectangle area = client_area;
1332 if (View == View.Details && Columns.Count > 0) {
1333 area.Y += Columns[0].Ht;
1334 area.Height -= Columns[0].Ht;
1337 h_marker = h_scroll.Value;
1338 XplatUI.ScrollWindow (Handle, area, pixels, 0, false);
1342 private void VerticalScroller (object sender, EventArgs e)
1344 // Avoid unnecessary flickering, when button is
1345 // kept pressed at the end
1346 if (v_marker != v_scroll.Value) {
1347 int pixels = v_marker - v_scroll.Value;
1348 Rectangle area = client_area;
1350 if (View == View.Details && header_style != ColumnHeaderStyle.None && Columns.Count > 0) {
1351 area.Y += Columns[0].Ht;
1352 area.Height -= Columns[0].Ht;
1355 v_marker = v_scroll.Value;
1356 XplatUI.ScrollWindow (Handle, area, 0, pixels, false);
1359 #endregion // Internal Methods Properties
1361 #region Protected Methods
1362 protected override void CreateHandle ()
1364 base.CreateHandle ();
1367 protected override void Dispose (bool disposing)
1370 h_scroll.Dispose ();
1371 v_scroll.Dispose ();
1373 large_image_list = null;
1374 small_image_list = null;
1375 state_image_list = null;
1378 base.Dispose (disposing);
1381 protected override bool IsInputKey (Keys keyData)
1398 return base.IsInputKey (keyData);
1401 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1403 if (AfterLabelEdit != null)
1404 AfterLabelEdit (this, e);
1407 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1409 if (BeforeLabelEdit != null)
1410 BeforeLabelEdit (this, e);
1413 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1415 if (ColumnClick != null)
1416 ColumnClick (this, e);
1419 protected override void OnEnabledChanged (EventArgs e)
1421 base.OnEnabledChanged (e);
1424 protected override void OnFontChanged (EventArgs e)
1426 base.OnFontChanged (e);
1430 protected override void OnHandleCreated (EventArgs e)
1432 base.OnHandleCreated (e);
1434 Controls.AddImplicit (this.v_scroll);
1435 Controls.AddImplicit (this.h_scroll);
1439 protected override void OnHandleDestroyed (EventArgs e)
1441 base.OnHandleDestroyed (e);
1444 protected virtual void OnItemActivate (EventArgs e)
1446 if (ItemActivate != null)
1447 ItemActivate (this, e);
1450 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1452 if (ItemCheck != null)
1453 ItemCheck (this, ice);
1456 protected virtual void OnItemDrag (ItemDragEventArgs e)
1458 if (ItemDrag != null)
1462 protected virtual void OnSelectedIndexChanged (EventArgs e)
1464 if (SelectedIndexChanged != null)
1465 SelectedIndexChanged (this, e);
1468 protected override void OnSystemColorsChanged (EventArgs e)
1470 base.OnSystemColorsChanged (e);
1473 protected void RealizeProperties ()
1478 protected void UpdateExtendedStyles ()
1483 protected override void WndProc (ref Message m)
1485 base.WndProc (ref m);
1487 #endregion // Protected Methods
1489 #region Public Instance Methods
1490 public void ArrangeIcons ()
1492 ArrangeIcons (this.alignment);
1495 public void ArrangeIcons (ListViewAlignment alignment)
1497 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1498 if (view == View.LargeIcon || view == View.SmallIcon) {
1499 this.CalculateListView (alignment);
1500 // we have done the calculations already
1501 this.Redraw (false);
1505 public void BeginUpdate ()
1507 // flag to avoid painting
1511 public void Clear ()
1514 items.Clear (); // Redraw (true) called here
1517 public void EndUpdate ()
1519 // flag to avoid painting
1522 // probably, now we need a redraw with recalculations
1526 public void EnsureVisible (int index)
1528 if (index < 0 || index >= this.items.Count || this.scrollable == false)
1531 // dimensions of visible area
1532 int view_wd = client_area.Width;
1533 int view_ht = client_area.Height;
1534 // visible area is decided by the h_marker and v_marker
1535 Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1537 // an item's bounding rect
1538 Rectangle rect = this.items [index].EntireRect;
1540 // we don't need to do anything if item is visible.
1541 // visible area is represented by (0,0,view_wd,view_ht)
1542 if (view_rect.Contains (rect))
1545 // Scroll Left or Up
1546 if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1547 if (rect.Left < view_rect.Left)
1548 this.h_scroll.Value -= (view_rect.Left - rect.Left);
1549 if (rect.Top < view_rect.Top)
1550 this.v_scroll.Value -= (view_rect.Top - rect.Top);
1552 // Scroll Right or Down
1554 if (rect.Right > view_rect.Right)
1555 this.h_scroll.Value += (rect.Right - view_rect.Right);
1556 if (rect.Bottom > view_rect.Bottom)
1557 this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1561 public ListViewItem GetItemAt (int x, int y)
1563 foreach (ListViewItem item in items) {
1564 if (item.Bounds.Contains (x, y))
1570 public Rectangle GetItemRect (int index)
1572 return GetItemRect (index, ItemBoundsPortion.Entire);
1575 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1577 if (index < 0 || index >= items.Count)
1578 throw new IndexOutOfRangeException ("Invalid Index");
1580 return items [index].GetBounds (portion);
1585 if (sort_order != SortOrder.None)
1586 items.list.Sort (item_sorter);
1588 if (sort_order == SortOrder.Descending)
1589 items.list.Reverse ();
1594 public override string ToString ()
1596 int count = this.Items.Count;
1599 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1601 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1603 #endregion // Public Instance Methods
1607 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1609 internal ArrayList list;
1610 private ListView owner;
1612 #region Public Constructor
1613 public CheckedIndexCollection (ListView owner)
1615 list = new ArrayList ();
1618 #endregion // Public Constructor
1620 #region Public Properties
1622 public virtual int Count {
1623 get { return list.Count; }
1626 public virtual bool IsReadOnly {
1627 get { return true; }
1630 public int this [int index] {
1632 if (index < 0 || index >= list.Count)
1633 throw new ArgumentOutOfRangeException ("Index out of range.");
1634 return (int) list [index];
1638 bool ICollection.IsSynchronized {
1639 get { return false; }
1642 object ICollection.SyncRoot {
1643 get { return this; }
1646 bool IList.IsFixedSize {
1647 get { return true; }
1650 object IList.this [int index] {
1651 get { return this [index]; }
1652 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1654 #endregion // Public Properties
1656 #region Public Methods
1657 public bool Contains (int checkedIndex)
1659 return list.Contains (checkedIndex);
1662 public virtual IEnumerator GetEnumerator ()
1664 return list.GetEnumerator ();
1667 void ICollection.CopyTo (Array dest, int index)
1669 list.CopyTo (dest, index);
1672 int IList.Add (object value)
1674 throw new NotSupportedException ("Add operation is not supported.");
1679 throw new NotSupportedException ("Clear operation is not supported.");
1682 bool IList.Contains (object checkedIndex)
1684 return list.Contains (checkedIndex);
1687 int IList.IndexOf (object checkedIndex)
1689 return list.IndexOf (checkedIndex);
1692 void IList.Insert (int index, object value)
1694 throw new NotSupportedException ("Insert operation is not supported.");
1697 void IList.Remove (object value)
1699 throw new NotSupportedException ("Remove operation is not supported.");
1702 void IList.RemoveAt (int index)
1704 throw new NotSupportedException ("RemoveAt operation is not supported.");
1707 public int IndexOf (int checkedIndex)
1709 return list.IndexOf (checkedIndex);
1711 #endregion // Public Methods
1713 } // CheckedIndexCollection
1715 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1717 internal ArrayList list;
1718 private ListView owner;
1720 #region Public Constructor
1721 public CheckedListViewItemCollection (ListView owner)
1723 list = new ArrayList ();
1726 #endregion // Public Constructor
1728 #region Public Properties
1730 public virtual int Count {
1731 get { return list.Count; }
1734 public virtual bool IsReadOnly {
1735 get { return true; }
1738 public ListViewItem this [int index] {
1740 if (index < 0 || index >= list.Count)
1741 throw new ArgumentOutOfRangeException ("Index out of range.");
1742 return (ListViewItem) list [index];
1746 bool ICollection.IsSynchronized {
1747 get { return list.IsSynchronized; }
1750 object ICollection.SyncRoot {
1751 get { return this; }
1754 bool IList.IsFixedSize {
1755 get { return true; }
1758 object IList.this [int index] {
1759 get { return this [index]; }
1760 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1762 #endregion // Public Properties
1764 #region Public Methods
1765 public bool Contains (ListViewItem item)
1767 return list.Contains (item);
1770 public virtual void CopyTo (Array dest, int index)
1772 list.CopyTo (dest, index);
1775 public virtual IEnumerator GetEnumerator ()
1777 return list.GetEnumerator ();
1780 int IList.Add (object value)
1782 throw new NotSupportedException ("Add operation is not supported.");
1787 throw new NotSupportedException ("Clear operation is not supported.");
1790 bool IList.Contains (object item)
1792 return list.Contains (item);
1795 int IList.IndexOf (object item)
1797 return list.IndexOf (item);
1800 void IList.Insert (int index, object value)
1802 throw new NotSupportedException ("Insert operation is not supported.");
1805 void IList.Remove (object value)
1807 throw new NotSupportedException ("Remove operation is not supported.");
1810 void IList.RemoveAt (int index)
1812 throw new NotSupportedException ("RemoveAt operation is not supported.");
1815 public int IndexOf (ListViewItem item)
1817 return list.IndexOf (item);
1819 #endregion // Public Methods
1821 } // CheckedListViewItemCollection
1823 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1825 internal ArrayList list;
1826 private ListView owner;
1828 #region Public Constructor
1829 public ColumnHeaderCollection (ListView owner)
1831 list = new ArrayList ();
1834 #endregion // Public Constructor
1836 #region Public Properties
1838 public virtual int Count {
1839 get { return list.Count; }
1842 public virtual bool IsReadOnly {
1843 get { return false; }
1846 public virtual ColumnHeader this [int index] {
1848 if (index < 0 || index >= list.Count)
1849 throw new ArgumentOutOfRangeException ("Index out of range.");
1850 return (ColumnHeader) list [index];
1854 bool ICollection.IsSynchronized {
1855 get { return true; }
1858 object ICollection.SyncRoot {
1859 get { return this; }
1862 bool IList.IsFixedSize {
1863 get { return list.IsFixedSize; }
1866 object IList.this [int index] {
1867 get { return this [index]; }
1868 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1870 #endregion // Public Properties
1872 #region Public Methods
1873 public virtual int Add (ColumnHeader value)
1876 value.owner = this.owner;
1877 idx = list.Add (value);
1878 owner.Redraw (true);
1882 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1884 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1885 this.Add (colHeader);
1889 public virtual void AddRange (ColumnHeader [] values)
1891 foreach (ColumnHeader colHeader in values) {
1892 colHeader.owner = this.owner;
1896 owner.Redraw (true);
1899 public virtual void Clear ()
1902 owner.Redraw (true);
1905 public bool Contains (ColumnHeader value)
1907 return list.Contains (value);
1910 public virtual IEnumerator GetEnumerator ()
1912 return list.GetEnumerator ();
1915 void ICollection.CopyTo (Array dest, int index)
1917 list.CopyTo (dest, index);
1920 int IList.Add (object value)
1922 if (! (value is ColumnHeader)) {
1923 throw new ArgumentException ("Not of type ColumnHeader", "value");
1926 return this.Add ((ColumnHeader) value);
1929 bool IList.Contains (object value)
1931 if (! (value is ColumnHeader)) {
1932 throw new ArgumentException ("Not of type ColumnHeader", "value");
1935 return this.Contains ((ColumnHeader) value);
1938 int IList.IndexOf (object value)
1940 if (! (value is ColumnHeader)) {
1941 throw new ArgumentException ("Not of type ColumnHeader", "value");
1944 return this.IndexOf ((ColumnHeader) value);
1947 void IList.Insert (int index, object value)
1949 if (! (value is ColumnHeader)) {
1950 throw new ArgumentException ("Not of type ColumnHeader", "value");
1953 this.Insert (index, (ColumnHeader) value);
1956 void IList.Remove (object value)
1958 if (! (value is ColumnHeader)) {
1959 throw new ArgumentException ("Not of type ColumnHeader", "value");
1962 this.Remove ((ColumnHeader) value);
1965 public int IndexOf (ColumnHeader value)
1967 return list.IndexOf (value);
1970 public void Insert (int index, ColumnHeader value)
1972 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
1973 // but it's really only greater.
1974 if (index < 0 || index > list.Count)
1975 throw new ArgumentOutOfRangeException ("Index out of range.");
1977 value.owner = this.owner;
1978 list.Insert (index, value);
1979 owner.Redraw (true);
1982 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1984 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1985 this.Insert (index, colHeader);
1988 public virtual void Remove (ColumnHeader column)
1990 // TODO: Update Column internal index ?
1991 list.Remove (column);
1992 owner.Redraw (true);
1995 public virtual void RemoveAt (int index)
1997 if (index < 0 || index >= list.Count)
1998 throw new ArgumentOutOfRangeException ("Index out of range.");
2000 // TODO: Update Column internal index ?
2001 list.RemoveAt (index);
2002 owner.Redraw (true);
2004 #endregion // Public Methods
2007 } // ColumnHeaderCollection
2009 public class ListViewItemCollection : IList, ICollection, IEnumerable
2011 internal ArrayList list;
2012 private ListView owner;
2014 #region Public Constructor
2015 public ListViewItemCollection (ListView owner)
2017 list = new ArrayList ();
2020 #endregion // Public Constructor
2022 #region Public Properties
2024 public virtual int Count {
2025 get { return list.Count; }
2028 public virtual bool IsReadOnly {
2029 get { return false; }
2032 public virtual ListViewItem this [int displayIndex] {
2034 if (displayIndex < 0 || displayIndex >= list.Count)
2035 throw new ArgumentOutOfRangeException ("Index out of range.");
2036 return (ListViewItem) list [displayIndex];
2040 if (displayIndex < 0 || displayIndex >= list.Count)
2041 throw new ArgumentOutOfRangeException ("Index out of range.");
2043 if (list.Contains (value))
2044 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2046 value.owner = this.owner;
2047 list [displayIndex] = value;
2049 owner.Redraw (true);
2053 bool ICollection.IsSynchronized {
2054 get { return true; }
2057 object ICollection.SyncRoot {
2058 get { return this; }
2061 bool IList.IsFixedSize {
2062 get { return list.IsFixedSize; }
2065 object IList.this [int index] {
2066 get { return this [index]; }
2068 if (value is ListViewItem)
2069 this [index] = (ListViewItem) value;
2071 this [index] = new ListViewItem (value.ToString ());
2074 #endregion // Public Properties
2076 #region Public Methods
2077 public virtual ListViewItem Add (ListViewItem value)
2079 if (list.Contains (value))
2080 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2082 value.owner = this.owner;
2085 if (owner.Sorting != SortOrder.None)
2088 owner.Redraw (true);
2093 public virtual ListViewItem Add (string text)
2095 ListViewItem item = new ListViewItem (text);
2096 return this.Add (item);
2099 public virtual ListViewItem Add (string text, int imageIndex)
2101 ListViewItem item = new ListViewItem (text, imageIndex);
2102 return this.Add (item);
2105 public void AddRange (ListViewItem [] values)
2108 owner.SelectedItems.list.Clear ();
2109 owner.SelectedIndices.list.Clear ();
2110 owner.CheckedItems.list.Clear ();
2111 owner.CheckedIndices.list.Clear ();
2113 foreach (ListViewItem item in values) {
2114 item.owner = this.owner;
2118 if (owner.Sorting != SortOrder.None)
2121 owner.Redraw (true);
2124 public virtual void Clear ()
2126 owner.SetFocusedItem (null);
2127 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2129 owner.SelectedItems.list.Clear ();
2130 owner.SelectedIndices.list.Clear ();
2131 owner.CheckedItems.list.Clear ();
2132 owner.CheckedIndices.list.Clear ();
2133 owner.Redraw (true);
2136 public bool Contains (ListViewItem item)
2138 return list.Contains (item);
2141 public virtual void CopyTo (Array dest, int index)
2143 list.CopyTo (dest, index);
2146 public virtual IEnumerator GetEnumerator ()
2148 return list.GetEnumerator ();
2151 int IList.Add (object item)
2156 if (item is ListViewItem) {
2157 li = (ListViewItem) item;
2158 if (list.Contains (li))
2159 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2162 li = new ListViewItem (item.ToString ());
2164 li.owner = this.owner;
2165 result = list.Add (li);
2166 owner.Redraw (true);
2171 bool IList.Contains (object item)
2173 return list.Contains (item);
2176 int IList.IndexOf (object item)
2178 return list.IndexOf (item);
2181 void IList.Insert (int index, object item)
2183 if (item is ListViewItem)
2184 this.Insert (index, (ListViewItem) item);
2186 this.Insert (index, item.ToString ());
2189 void IList.Remove (object item)
2191 Remove ((ListViewItem) item);
2194 public int IndexOf (ListViewItem item)
2196 return list.IndexOf (item);
2199 public ListViewItem Insert (int index, ListViewItem item)
2201 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2202 // but it's really only greater.
2203 if (index < 0 || index > list.Count)
2204 throw new ArgumentOutOfRangeException ("Index out of range.");
2206 if (list.Contains (item))
2207 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2209 item.owner = this.owner;
2210 list.Insert (index, item);
2211 owner.Redraw (true);
2215 public ListViewItem Insert (int index, string text)
2217 return this.Insert (index, new ListViewItem (text));
2220 public ListViewItem Insert (int index, string text, int imageIndex)
2222 return this.Insert (index, new ListViewItem (text, imageIndex));
2225 public virtual void Remove (ListViewItem item)
2227 if (!list.Contains (item))
2230 owner.SelectedItems.list.Remove (item);
2231 owner.SelectedIndices.list.Remove (item.Index);
2232 owner.CheckedItems.list.Remove (item);
2233 owner.CheckedIndices.list.Remove (item.Index);
2235 owner.Redraw (true);
2238 public virtual void RemoveAt (int index)
2240 if (index < 0 || index >= list.Count)
2241 throw new ArgumentOutOfRangeException ("Index out of range.");
2243 list.RemoveAt (index);
2244 owner.SelectedItems.list.RemoveAt (index);
2245 owner.SelectedIndices.list.RemoveAt (index);
2246 owner.CheckedItems.list.RemoveAt (index);
2247 owner.CheckedIndices.list.RemoveAt (index);
2248 owner.Redraw (false);
2250 #endregion // Public Methods
2252 } // ListViewItemCollection
2254 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2256 internal ArrayList list;
2257 private ListView owner;
2259 #region Public Constructor
2260 public SelectedIndexCollection (ListView owner)
2262 list = new ArrayList ();
2265 #endregion // Public Constructor
2267 #region Public Properties
2269 public virtual int Count {
2270 get { return list.Count; }
2273 public virtual bool IsReadOnly {
2274 get { return true; }
2277 public int this [int index] {
2279 if (index < 0 || index >= list.Count)
2280 throw new ArgumentOutOfRangeException ("Index out of range.");
2281 return (int) list [index];
2285 bool ICollection.IsSynchronized {
2286 get { return list.IsSynchronized; }
2289 object ICollection.SyncRoot {
2290 get { return this; }
2293 bool IList.IsFixedSize {
2294 get { return true; }
2297 object IList.this [int index] {
2298 get { return this [index]; }
2299 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2301 #endregion // Public Properties
2303 #region Public Methods
2304 public bool Contains (int selectedIndex)
2306 return list.Contains (selectedIndex);
2309 public virtual void CopyTo (Array dest, int index)
2311 list.CopyTo (dest, index);
2314 public virtual IEnumerator GetEnumerator ()
2316 return list.GetEnumerator ();
2319 int IList.Add (object value)
2321 throw new NotSupportedException ("Add operation is not supported.");
2326 throw new NotSupportedException ("Clear operation is not supported.");
2329 bool IList.Contains (object selectedIndex)
2331 return list.Contains (selectedIndex);
2334 int IList.IndexOf (object selectedIndex)
2336 return list.IndexOf (selectedIndex);
2339 void IList.Insert (int index, object value)
2341 throw new NotSupportedException ("Insert operation is not supported.");
2344 void IList.Remove (object value)
2346 throw new NotSupportedException ("Remove operation is not supported.");
2349 void IList.RemoveAt (int index)
2351 throw new NotSupportedException ("RemoveAt operation is not supported.");
2354 public int IndexOf (int selectedIndex)
2356 return list.IndexOf (selectedIndex);
2358 #endregion // Public Methods
2360 } // SelectedIndexCollection
2362 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2364 internal ArrayList list;
2365 private ListView owner;
2367 #region Public Constructor
2368 public SelectedListViewItemCollection (ListView owner)
2370 list = new ArrayList ();
2373 #endregion // Public Constructor
2375 #region Public Properties
2377 public virtual int Count {
2378 get { return list.Count; }
2381 public virtual bool IsReadOnly {
2382 get { return true; }
2385 public ListViewItem this [int index] {
2387 if (index < 0 || index >= list.Count)
2388 throw new ArgumentOutOfRangeException ("Index out of range.");
2389 return (ListViewItem) list [index];
2393 bool ICollection.IsSynchronized {
2394 get { return list.IsSynchronized; }
2397 object ICollection.SyncRoot {
2398 get { return this; }
2401 bool IList.IsFixedSize {
2402 get { return true; }
2405 object IList.this [int index] {
2406 get { return this [index]; }
2407 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2409 #endregion // Public Properties
2411 #region Public Methods
2412 public virtual void Clear ()
2414 // mark the items as unselected before clearing the list
2415 for (int i = 0; i < list.Count; i++)
2416 ((ListViewItem) list [i]).selected = false;
2421 owner.Invalidate ();
2424 public bool Contains (ListViewItem item)
2426 return list.Contains (item);
2429 public virtual void CopyTo (Array dest, int index)
2431 list.CopyTo (dest, index);
2434 public virtual IEnumerator GetEnumerator ()
2436 return list.GetEnumerator ();
2439 int IList.Add (object value)
2441 throw new NotSupportedException ("Add operation is not supported.");
2444 bool IList.Contains (object item)
2446 return list.Contains (item);
2449 int IList.IndexOf (object item)
2451 return list.IndexOf (item);
2454 void IList.Insert (int index, object value)
2456 throw new NotSupportedException ("Insert operation is not supported.");
2459 void IList.Remove (object value)
2461 throw new NotSupportedException ("Remove operation is not supported.");
2464 void IList.RemoveAt (int index)
2466 throw new NotSupportedException ("RemoveAt operation is not supported.");
2469 public int IndexOf (ListViewItem item)
2471 return list.IndexOf (item);
2473 #endregion // Public Methods
2475 } // SelectedListViewItemCollection
2477 #endregion // Subclasses