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);
1185 this.Redraw (false);
1186 } else if (selected_indices.Count > 0) {
1187 // NOTE: selected_indices isn't computed properly so
1188 // this doesn't actually work
1190 // Raise the event if there was at least one item
1191 // selected and the user click on a dead area (unselecting all)
1192 OnSelectedIndexChanged (EventArgs.Empty);
1197 private void ListView_MouseHover (object sender, EventArgs e)
1199 // handle the hover events only when the mouse
1201 if (this.hover_selection == false || this.Capture)
1204 // hit test for the items
1205 Point hit = this.PointToClient (Control.MousePosition);
1206 ListViewItem item = this.GetItemAt (hit.X, hit.Y);
1209 item.Selected = true;
1211 this.OnSelectedIndexChanged (new EventArgs ());
1213 this.Redraw (false);
1217 private void ListView_MouseMove (object sender, MouseEventArgs me)
1219 // Column header is always at the top. It can
1220 // scroll only horizontally. So, we have to take
1221 // only horizontal scrolling into account
1222 Point hit = new Point (me.X + h_marker, me.Y);
1224 // non-null clicked_col means mouse down has happened
1226 if (this.clicked_column != null) {
1227 if (this.clicked_column.pressed == false &&
1228 this.clicked_column.Rect.Contains (hit)) {
1229 this.clicked_column.pressed = true;
1230 this.Redraw (false);
1232 else if (this.clicked_column.pressed &&
1233 ! this.clicked_column.Rect.Contains (hit)) {
1234 this.clicked_column.pressed = false;
1235 this.Redraw (false);
1240 private void ListView_MouseUp (object sender, MouseEventArgs me)
1242 this.Capture = false;
1243 if (items.Count == 0)
1246 Point hit = new Point (me.X, me.Y);
1248 if (this.clicked_column != null) {
1249 if (this.clicked_column.pressed) {
1250 this.clicked_column.pressed = false;
1251 this.Redraw (false);
1253 // Raise the ColumnClick event
1254 this.OnColumnClick (new ColumnClickEventArgs
1255 (this.clicked_column.Index));
1259 // Raise the ItemActivate event
1260 Rectangle rect = Rectangle.Empty;
1261 if (this.clicked_item != null) {
1262 if (this.view == View.Details && !this.full_row_select)
1263 rect = this.clicked_item.LabelRect;
1265 rect = this.clicked_item.EntireRect;
1267 // We handle double click in a separate handler
1268 if (this.activation != ItemActivation.Standard &&
1269 rect.Contains (hit)) {
1270 if (this.activation == ItemActivation.OneClick)
1271 this.ItemActivate (this, EventArgs.Empty);
1273 // ItemActivate is raised on the second click on the same item
1274 else if (this.activation == ItemActivation.TwoClick) {
1275 if (this.last_clicked_item == this.clicked_item) {
1276 this.ItemActivate (this, EventArgs.Empty);
1277 this.last_clicked_item = null;
1280 this.last_clicked_item = this.clicked_item;
1285 this.clicked_column = null;
1286 this.clicked_item = null;
1289 private void ListView_Paint (object sender, PaintEventArgs pe)
1291 if (this.Width <= 0 || this.Height <= 0 ||
1292 this.Visible == false || this.updating == true)
1295 CalculateScrollBars ();
1297 ThemeEngine.Current.DrawListView (pe.Graphics,
1298 pe.ClipRectangle, this);
1300 // Raise the Paint event
1305 private void ListView_SizeChanged (object sender, EventArgs e)
1307 CalculateListView (alignment);
1310 private void SetFocusedItem (ListViewItem item)
1312 if (focused_item != null)
1313 focused_item.Focused = false;
1316 item.Focused = true;
1318 focused_item = item;
1321 private void HorizontalScroller (object sender, EventArgs e)
1323 // Avoid unnecessary flickering, when button is
1324 // kept pressed at the end
1325 if (h_marker != h_scroll.Value) {
1327 int pixels = h_marker - h_scroll.Value;
1328 Rectangle area = client_area;
1330 if (View == View.Details && Columns.Count > 0) {
1331 area.Y += Columns[0].Ht;
1332 area.Height -= Columns[0].Ht;
1335 h_marker = h_scroll.Value;
1336 XplatUI.ScrollWindow (Handle, area, pixels, 0, false);
1340 private void VerticalScroller (object sender, EventArgs e)
1342 // Avoid unnecessary flickering, when button is
1343 // kept pressed at the end
1344 if (v_marker != v_scroll.Value) {
1345 int pixels = v_marker - v_scroll.Value;
1346 Rectangle area = client_area;
1348 if (View == View.Details && Columns.Count > 0) {
1349 area.Y += Columns[0].Ht;
1350 area.Height -= Columns[0].Ht;
1353 v_marker = v_scroll.Value;
1354 XplatUI.ScrollWindow (Handle, area, 0, pixels, false);
1357 #endregion // Internal Methods Properties
1359 #region Protected Methods
1360 protected override void CreateHandle ()
1362 base.CreateHandle ();
1365 protected override void Dispose (bool disposing)
1368 h_scroll.Dispose ();
1369 v_scroll.Dispose ();
1371 large_image_list = null;
1372 small_image_list = null;
1373 state_image_list = null;
1376 base.Dispose (disposing);
1379 protected override bool IsInputKey (Keys keyData)
1396 return base.IsInputKey (keyData);
1399 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1401 if (AfterLabelEdit != null)
1402 AfterLabelEdit (this, e);
1405 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1407 if (BeforeLabelEdit != null)
1408 BeforeLabelEdit (this, e);
1411 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1413 if (ColumnClick != null)
1414 ColumnClick (this, e);
1417 protected override void OnEnabledChanged (EventArgs e)
1419 base.OnEnabledChanged (e);
1422 protected override void OnFontChanged (EventArgs e)
1424 base.OnFontChanged (e);
1428 protected override void OnHandleCreated (EventArgs e)
1430 base.OnHandleCreated (e);
1432 Controls.AddImplicit (this.v_scroll);
1433 Controls.AddImplicit (this.h_scroll);
1437 protected override void OnHandleDestroyed (EventArgs e)
1439 base.OnHandleDestroyed (e);
1442 protected virtual void OnItemActivate (EventArgs e)
1444 if (ItemActivate != null)
1445 ItemActivate (this, e);
1448 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1450 if (ItemCheck != null)
1451 ItemCheck (this, ice);
1454 protected virtual void OnItemDrag (ItemDragEventArgs e)
1456 if (ItemDrag != null)
1460 protected virtual void OnSelectedIndexChanged (EventArgs e)
1462 if (SelectedIndexChanged != null)
1463 SelectedIndexChanged (this, e);
1466 protected override void OnSystemColorsChanged (EventArgs e)
1468 base.OnSystemColorsChanged (e);
1471 protected void RealizeProperties ()
1476 protected void UpdateExtendedStyles ()
1481 protected override void WndProc (ref Message m)
1483 base.WndProc (ref m);
1485 #endregion // Protected Methods
1487 #region Public Instance Methods
1488 public void ArrangeIcons ()
1490 ArrangeIcons (this.alignment);
1493 public void ArrangeIcons (ListViewAlignment alignment)
1495 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1496 if (view == View.LargeIcon || view == View.SmallIcon) {
1497 this.CalculateListView (alignment);
1498 // we have done the calculations already
1499 this.Redraw (false);
1503 public void BeginUpdate ()
1505 // flag to avoid painting
1509 public void Clear ()
1512 items.Clear (); // Redraw (true) called here
1515 public void EndUpdate ()
1517 // flag to avoid painting
1520 // probably, now we need a redraw with recalculations
1524 public void EnsureVisible (int index)
1526 if (index < 0 || index >= this.items.Count || this.scrollable == false)
1529 // dimensions of visible area
1530 int view_wd = client_area.Width;
1531 int view_ht = client_area.Height;
1532 // visible area is decided by the h_marker and v_marker
1533 Rectangle view_rect = new Rectangle (h_marker, v_marker, view_wd, view_ht);
1535 // an item's bounding rect
1536 Rectangle rect = this.items [index].EntireRect;
1538 // we don't need to do anything if item is visible.
1539 // visible area is represented by (0,0,view_wd,view_ht)
1540 if (view_rect.Contains (rect))
1543 // Scroll Left or Up
1544 if ((rect.Left < view_rect.Left) || (rect.Top < view_rect.Top)) {
1545 if (rect.Left < view_rect.Left)
1546 this.h_scroll.Value -= (view_rect.Left - rect.Left);
1547 if (rect.Top < view_rect.Top)
1548 this.v_scroll.Value -= (view_rect.Top - rect.Top);
1550 // Scroll Right or Down
1552 if (rect.Right > view_rect.Right)
1553 this.h_scroll.Value += (rect.Right - view_rect.Right);
1554 if (rect.Bottom > view_rect.Bottom)
1555 this.v_scroll.Value += (rect.Bottom - view_rect.Bottom);
1559 public ListViewItem GetItemAt (int x, int y)
1561 foreach (ListViewItem item in items) {
1562 if (item.Bounds.Contains (x, y))
1568 public Rectangle GetItemRect (int index)
1570 return GetItemRect (index, ItemBoundsPortion.Entire);
1573 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1575 if (index < 0 || index >= items.Count)
1576 throw new IndexOutOfRangeException ("Invalid Index");
1578 return items [index].GetBounds (portion);
1583 if (sort_order != SortOrder.None)
1584 items.list.Sort (item_sorter);
1586 if (sort_order == SortOrder.Descending)
1587 items.list.Reverse ();
1592 public override string ToString ()
1594 int count = this.Items.Count;
1597 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1599 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1601 #endregion // Public Instance Methods
1605 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1607 internal ArrayList list;
1608 private ListView owner;
1610 #region Public Constructor
1611 public CheckedIndexCollection (ListView owner)
1613 list = new ArrayList ();
1616 #endregion // Public Constructor
1618 #region Public Properties
1620 public virtual int Count {
1621 get { return list.Count; }
1624 public virtual bool IsReadOnly {
1625 get { return true; }
1628 public int this [int index] {
1630 if (index < 0 || index >= list.Count)
1631 throw new ArgumentOutOfRangeException ("Index out of range.");
1632 return (int) list [index];
1636 bool ICollection.IsSynchronized {
1637 get { return false; }
1640 object ICollection.SyncRoot {
1641 get { return this; }
1644 bool IList.IsFixedSize {
1645 get { return true; }
1648 object IList.this [int index] {
1649 get { return this [index]; }
1650 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1652 #endregion // Public Properties
1654 #region Public Methods
1655 public bool Contains (int checkedIndex)
1657 return list.Contains (checkedIndex);
1660 public virtual IEnumerator GetEnumerator ()
1662 return list.GetEnumerator ();
1665 void ICollection.CopyTo (Array dest, int index)
1667 list.CopyTo (dest, index);
1670 int IList.Add (object value)
1672 throw new NotSupportedException ("Add operation is not supported.");
1677 throw new NotSupportedException ("Clear operation is not supported.");
1680 bool IList.Contains (object checkedIndex)
1682 return list.Contains (checkedIndex);
1685 int IList.IndexOf (object checkedIndex)
1687 return list.IndexOf (checkedIndex);
1690 void IList.Insert (int index, object value)
1692 throw new NotSupportedException ("Insert operation is not supported.");
1695 void IList.Remove (object value)
1697 throw new NotSupportedException ("Remove operation is not supported.");
1700 void IList.RemoveAt (int index)
1702 throw new NotSupportedException ("RemoveAt operation is not supported.");
1705 public int IndexOf (int checkedIndex)
1707 return list.IndexOf (checkedIndex);
1709 #endregion // Public Methods
1711 } // CheckedIndexCollection
1713 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1715 internal ArrayList list;
1716 private ListView owner;
1718 #region Public Constructor
1719 public CheckedListViewItemCollection (ListView owner)
1721 list = new ArrayList ();
1724 #endregion // Public Constructor
1726 #region Public Properties
1728 public virtual int Count {
1729 get { return list.Count; }
1732 public virtual bool IsReadOnly {
1733 get { return true; }
1736 public ListViewItem this [int index] {
1738 if (index < 0 || index >= list.Count)
1739 throw new ArgumentOutOfRangeException ("Index out of range.");
1740 return (ListViewItem) list [index];
1744 bool ICollection.IsSynchronized {
1745 get { return list.IsSynchronized; }
1748 object ICollection.SyncRoot {
1749 get { return this; }
1752 bool IList.IsFixedSize {
1753 get { return true; }
1756 object IList.this [int index] {
1757 get { return this [index]; }
1758 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1760 #endregion // Public Properties
1762 #region Public Methods
1763 public bool Contains (ListViewItem item)
1765 return list.Contains (item);
1768 public virtual void CopyTo (Array dest, int index)
1770 list.CopyTo (dest, index);
1773 public virtual IEnumerator GetEnumerator ()
1775 return list.GetEnumerator ();
1778 int IList.Add (object value)
1780 throw new NotSupportedException ("Add operation is not supported.");
1785 throw new NotSupportedException ("Clear operation is not supported.");
1788 bool IList.Contains (object item)
1790 return list.Contains (item);
1793 int IList.IndexOf (object item)
1795 return list.IndexOf (item);
1798 void IList.Insert (int index, object value)
1800 throw new NotSupportedException ("Insert operation is not supported.");
1803 void IList.Remove (object value)
1805 throw new NotSupportedException ("Remove operation is not supported.");
1808 void IList.RemoveAt (int index)
1810 throw new NotSupportedException ("RemoveAt operation is not supported.");
1813 public int IndexOf (ListViewItem item)
1815 return list.IndexOf (item);
1817 #endregion // Public Methods
1819 } // CheckedListViewItemCollection
1821 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1823 internal ArrayList list;
1824 private ListView owner;
1826 #region Public Constructor
1827 public ColumnHeaderCollection (ListView owner)
1829 list = new ArrayList ();
1832 #endregion // Public Constructor
1834 #region Public Properties
1836 public virtual int Count {
1837 get { return list.Count; }
1840 public virtual bool IsReadOnly {
1841 get { return false; }
1844 public virtual ColumnHeader this [int index] {
1846 if (index < 0 || index >= list.Count)
1847 throw new ArgumentOutOfRangeException ("Index out of range.");
1848 return (ColumnHeader) list [index];
1852 bool ICollection.IsSynchronized {
1853 get { return true; }
1856 object ICollection.SyncRoot {
1857 get { return this; }
1860 bool IList.IsFixedSize {
1861 get { return list.IsFixedSize; }
1864 object IList.this [int index] {
1865 get { return this [index]; }
1866 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1868 #endregion // Public Properties
1870 #region Public Methods
1871 public virtual int Add (ColumnHeader value)
1874 value.owner = this.owner;
1875 idx = list.Add (value);
1876 owner.Redraw (true);
1880 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1882 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1883 this.Add (colHeader);
1887 public virtual void AddRange (ColumnHeader [] values)
1889 foreach (ColumnHeader colHeader in values) {
1890 colHeader.owner = this.owner;
1894 owner.Redraw (true);
1897 public virtual void Clear ()
1900 owner.Redraw (true);
1903 public bool Contains (ColumnHeader value)
1905 return list.Contains (value);
1908 public virtual IEnumerator GetEnumerator ()
1910 return list.GetEnumerator ();
1913 void ICollection.CopyTo (Array dest, int index)
1915 list.CopyTo (dest, index);
1918 int IList.Add (object value)
1920 if (! (value is ColumnHeader)) {
1921 throw new ArgumentException ("Not of type ColumnHeader", "value");
1924 return this.Add ((ColumnHeader) value);
1927 bool IList.Contains (object value)
1929 if (! (value is ColumnHeader)) {
1930 throw new ArgumentException ("Not of type ColumnHeader", "value");
1933 return this.Contains ((ColumnHeader) value);
1936 int IList.IndexOf (object value)
1938 if (! (value is ColumnHeader)) {
1939 throw new ArgumentException ("Not of type ColumnHeader", "value");
1942 return this.IndexOf ((ColumnHeader) value);
1945 void IList.Insert (int index, object value)
1947 if (! (value is ColumnHeader)) {
1948 throw new ArgumentException ("Not of type ColumnHeader", "value");
1951 this.Insert (index, (ColumnHeader) value);
1954 void IList.Remove (object value)
1956 if (! (value is ColumnHeader)) {
1957 throw new ArgumentException ("Not of type ColumnHeader", "value");
1960 this.Remove ((ColumnHeader) value);
1963 public int IndexOf (ColumnHeader value)
1965 return list.IndexOf (value);
1968 public void Insert (int index, ColumnHeader value)
1970 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
1971 // but it's really only greater.
1972 if (index < 0 || index > list.Count)
1973 throw new ArgumentOutOfRangeException ("Index out of range.");
1975 value.owner = this.owner;
1976 list.Insert (index, value);
1977 owner.Redraw (true);
1980 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
1982 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1983 this.Insert (index, colHeader);
1986 public virtual void Remove (ColumnHeader column)
1988 // TODO: Update Column internal index ?
1989 list.Remove (column);
1990 owner.Redraw (true);
1993 public virtual void RemoveAt (int index)
1995 if (index < 0 || index >= list.Count)
1996 throw new ArgumentOutOfRangeException ("Index out of range.");
1998 // TODO: Update Column internal index ?
1999 list.RemoveAt (index);
2000 owner.Redraw (true);
2002 #endregion // Public Methods
2005 } // ColumnHeaderCollection
2007 public class ListViewItemCollection : IList, ICollection, IEnumerable
2009 internal ArrayList list;
2010 private ListView owner;
2012 #region Public Constructor
2013 public ListViewItemCollection (ListView owner)
2015 list = new ArrayList ();
2018 #endregion // Public Constructor
2020 #region Public Properties
2022 public virtual int Count {
2023 get { return list.Count; }
2026 public virtual bool IsReadOnly {
2027 get { return false; }
2030 public virtual ListViewItem this [int displayIndex] {
2032 if (displayIndex < 0 || displayIndex >= list.Count)
2033 throw new ArgumentOutOfRangeException ("Index out of range.");
2034 return (ListViewItem) list [displayIndex];
2038 if (displayIndex < 0 || displayIndex >= list.Count)
2039 throw new ArgumentOutOfRangeException ("Index out of range.");
2041 if (list.Contains (value))
2042 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2044 value.owner = this.owner;
2045 list [displayIndex] = value;
2047 owner.Redraw (true);
2051 bool ICollection.IsSynchronized {
2052 get { return true; }
2055 object ICollection.SyncRoot {
2056 get { return this; }
2059 bool IList.IsFixedSize {
2060 get { return list.IsFixedSize; }
2063 object IList.this [int index] {
2064 get { return this [index]; }
2066 if (value is ListViewItem)
2067 this [index] = (ListViewItem) value;
2069 this [index] = new ListViewItem (value.ToString ());
2072 #endregion // Public Properties
2074 #region Public Methods
2075 public virtual ListViewItem Add (ListViewItem value)
2077 if (list.Contains (value))
2078 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2080 value.owner = this.owner;
2083 if (owner.Sorting != SortOrder.None)
2086 owner.Redraw (true);
2091 public virtual ListViewItem Add (string text)
2093 ListViewItem item = new ListViewItem (text);
2094 return this.Add (item);
2097 public virtual ListViewItem Add (string text, int imageIndex)
2099 ListViewItem item = new ListViewItem (text, imageIndex);
2100 return this.Add (item);
2103 public void AddRange (ListViewItem [] values)
2106 owner.SelectedItems.list.Clear ();
2107 owner.SelectedIndices.list.Clear ();
2108 owner.CheckedItems.list.Clear ();
2109 owner.CheckedIndices.list.Clear ();
2111 foreach (ListViewItem item in values) {
2112 item.owner = this.owner;
2116 if (owner.Sorting != SortOrder.None)
2119 owner.Redraw (true);
2122 public virtual void Clear ()
2124 owner.SetFocusedItem (null);
2125 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2127 owner.SelectedItems.list.Clear ();
2128 owner.SelectedIndices.list.Clear ();
2129 owner.CheckedItems.list.Clear ();
2130 owner.CheckedIndices.list.Clear ();
2131 owner.Redraw (true);
2134 public bool Contains (ListViewItem item)
2136 return list.Contains (item);
2139 public virtual void CopyTo (Array dest, int index)
2141 list.CopyTo (dest, index);
2144 public virtual IEnumerator GetEnumerator ()
2146 return list.GetEnumerator ();
2149 int IList.Add (object item)
2154 if (item is ListViewItem) {
2155 li = (ListViewItem) item;
2156 if (list.Contains (li))
2157 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2160 li = new ListViewItem (item.ToString ());
2162 li.owner = this.owner;
2163 result = list.Add (li);
2164 owner.Redraw (true);
2169 bool IList.Contains (object item)
2171 return list.Contains (item);
2174 int IList.IndexOf (object item)
2176 return list.IndexOf (item);
2179 void IList.Insert (int index, object item)
2181 if (item is ListViewItem)
2182 this.Insert (index, (ListViewItem) item);
2184 this.Insert (index, item.ToString ());
2187 void IList.Remove (object item)
2189 Remove ((ListViewItem) item);
2192 public int IndexOf (ListViewItem item)
2194 return list.IndexOf (item);
2197 public ListViewItem Insert (int index, ListViewItem item)
2199 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2200 // but it's really only greater.
2201 if (index < 0 || index > list.Count)
2202 throw new ArgumentOutOfRangeException ("Index out of range.");
2204 if (list.Contains (item))
2205 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2207 item.owner = this.owner;
2208 list.Insert (index, item);
2209 owner.Redraw (true);
2213 public ListViewItem Insert (int index, string text)
2215 return this.Insert (index, new ListViewItem (text));
2218 public ListViewItem Insert (int index, string text, int imageIndex)
2220 return this.Insert (index, new ListViewItem (text, imageIndex));
2223 public virtual void Remove (ListViewItem item)
2225 if (!list.Contains (item))
2228 owner.SelectedItems.list.Remove (item);
2229 owner.SelectedIndices.list.Remove (item.Index);
2230 owner.CheckedItems.list.Remove (item);
2231 owner.CheckedIndices.list.Remove (item.Index);
2233 owner.Redraw (true);
2236 public virtual void RemoveAt (int index)
2238 if (index < 0 || index >= list.Count)
2239 throw new ArgumentOutOfRangeException ("Index out of range.");
2241 list.RemoveAt (index);
2242 owner.SelectedItems.list.RemoveAt (index);
2243 owner.SelectedIndices.list.RemoveAt (index);
2244 owner.CheckedItems.list.RemoveAt (index);
2245 owner.CheckedIndices.list.RemoveAt (index);
2246 owner.Redraw (false);
2248 #endregion // Public Methods
2250 } // ListViewItemCollection
2252 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2254 internal ArrayList list;
2255 private ListView owner;
2257 #region Public Constructor
2258 public SelectedIndexCollection (ListView owner)
2260 list = new ArrayList ();
2263 #endregion // Public Constructor
2265 #region Public Properties
2267 public virtual int Count {
2268 get { return list.Count; }
2271 public virtual bool IsReadOnly {
2272 get { return true; }
2275 public int this [int index] {
2277 if (index < 0 || index >= list.Count)
2278 throw new ArgumentOutOfRangeException ("Index out of range.");
2279 return (int) list [index];
2283 bool ICollection.IsSynchronized {
2284 get { return list.IsSynchronized; }
2287 object ICollection.SyncRoot {
2288 get { return this; }
2291 bool IList.IsFixedSize {
2292 get { return true; }
2295 object IList.this [int index] {
2296 get { return this [index]; }
2297 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2299 #endregion // Public Properties
2301 #region Public Methods
2302 public bool Contains (int selectedIndex)
2304 return list.Contains (selectedIndex);
2307 public virtual void CopyTo (Array dest, int index)
2309 list.CopyTo (dest, index);
2312 public virtual IEnumerator GetEnumerator ()
2314 return list.GetEnumerator ();
2317 int IList.Add (object value)
2319 throw new NotSupportedException ("Add operation is not supported.");
2324 throw new NotSupportedException ("Clear operation is not supported.");
2327 bool IList.Contains (object selectedIndex)
2329 return list.Contains (selectedIndex);
2332 int IList.IndexOf (object selectedIndex)
2334 return list.IndexOf (selectedIndex);
2337 void IList.Insert (int index, object value)
2339 throw new NotSupportedException ("Insert operation is not supported.");
2342 void IList.Remove (object value)
2344 throw new NotSupportedException ("Remove operation is not supported.");
2347 void IList.RemoveAt (int index)
2349 throw new NotSupportedException ("RemoveAt operation is not supported.");
2352 public int IndexOf (int selectedIndex)
2354 return list.IndexOf (selectedIndex);
2356 #endregion // Public Methods
2358 } // SelectedIndexCollection
2360 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2362 internal ArrayList list;
2363 private ListView owner;
2365 #region Public Constructor
2366 public SelectedListViewItemCollection (ListView owner)
2368 list = new ArrayList ();
2371 #endregion // Public Constructor
2373 #region Public Properties
2375 public virtual int Count {
2376 get { return list.Count; }
2379 public virtual bool IsReadOnly {
2380 get { return true; }
2383 public ListViewItem this [int index] {
2385 if (index < 0 || index >= list.Count)
2386 throw new ArgumentOutOfRangeException ("Index out of range.");
2387 return (ListViewItem) list [index];
2391 bool ICollection.IsSynchronized {
2392 get { return list.IsSynchronized; }
2395 object ICollection.SyncRoot {
2396 get { return this; }
2399 bool IList.IsFixedSize {
2400 get { return true; }
2403 object IList.this [int index] {
2404 get { return this [index]; }
2405 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2407 #endregion // Public Properties
2409 #region Public Methods
2410 public virtual void Clear ()
2412 // mark the items as unselected before clearing the list
2413 for (int i = 0; i < list.Count; i++)
2414 ((ListViewItem) list [i]).selected = false;
2419 owner.Invalidate ();
2422 public bool Contains (ListViewItem item)
2424 return list.Contains (item);
2427 public virtual void CopyTo (Array dest, int index)
2429 list.CopyTo (dest, index);
2432 public virtual IEnumerator GetEnumerator ()
2434 return list.GetEnumerator ();
2437 int IList.Add (object value)
2439 throw new NotSupportedException ("Add operation is not supported.");
2442 bool IList.Contains (object item)
2444 return list.Contains (item);
2447 int IList.IndexOf (object item)
2449 return list.IndexOf (item);
2452 void IList.Insert (int index, object value)
2454 throw new NotSupportedException ("Insert operation is not supported.");
2457 void IList.Remove (object value)
2459 throw new NotSupportedException ("Remove operation is not supported.");
2462 void IList.RemoveAt (int index)
2464 throw new NotSupportedException ("RemoveAt operation is not supported.");
2467 public int IndexOf (ListViewItem item)
2469 return list.IndexOf (item);
2471 #endregion // Public Methods
2473 } // SelectedListViewItemCollection
2475 #endregion // Subclasses