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
25 // Mike Kestner (mkestner@novell.com)
28 // - Feedback for item activation, change in cursor types as mouse moves.
37 using System.Collections;
38 using System.ComponentModel;
39 using System.ComponentModel.Design;
41 using System.Runtime.InteropServices;
42 using System.Globalization;
44 namespace System.Windows.Forms
46 [DefaultEvent ("SelectedIndexChanged")]
47 [DefaultProperty ("Items")]
48 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
49 public class ListView : Control
51 private ItemActivation activation = ItemActivation.Standard;
52 private ListViewAlignment alignment = ListViewAlignment.Top;
53 private bool allow_column_reorder = false;
54 private bool auto_arrange = true;
55 private bool check_boxes = false;
56 private CheckedIndexCollection checked_indices;
57 private CheckedListViewItemCollection checked_items;
58 private ColumnHeaderCollection columns;
59 internal ListViewItem focused_item;
60 private bool full_row_select = false;
61 private bool grid_lines = false;
62 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
63 private bool hide_selection = true;
64 private bool hover_selection = false;
65 private IComparer item_sorter;
66 private ListViewItemCollection items;
67 private bool label_edit = false;
68 private bool label_wrap = true;
69 private bool multiselect = true;
70 private bool scrollable = true;
71 private SelectedIndexCollection selected_indices;
72 private SelectedListViewItemCollection selected_items;
73 private SortOrder sort_order = SortOrder.None;
74 private ImageList state_image_list;
75 private bool updating = false;
76 private View view = View.LargeIcon;
77 private int layout_wd; // We might draw more than our client area
78 private int layout_ht; // therefore we need to have these two.
79 //private TextBox editor; // Used for editing an item text
80 HeaderControl header_control;
81 internal ItemControl item_control;
82 internal ScrollBar h_scroll; // used for scrolling horizontally
83 internal ScrollBar v_scroll; // used for scrolling vertically
84 internal int h_marker; // Position markers for scrolling
85 internal int v_marker;
86 private int keysearch_tickcnt;
87 private string keysearch_text;
88 static private readonly int keysearch_keydelay = 1000;
89 private int[] reordered_column_indices;
92 internal ImageList large_image_list;
93 internal ImageList small_image_list;
94 internal Size text_size = Size.Empty;
97 public event LabelEditEventHandler AfterLabelEdit;
100 [EditorBrowsable (EditorBrowsableState.Never)]
101 public new event EventHandler BackgroundImageChanged {
102 add { base.BackgroundImageChanged += value; }
103 remove { base.BackgroundImageChanged -= value; }
106 public event LabelEditEventHandler BeforeLabelEdit;
107 public event ColumnClickEventHandler ColumnClick;
108 public event EventHandler ItemActivate;
109 public event ItemCheckEventHandler ItemCheck;
110 public event ItemDragEventHandler ItemDrag;
113 [EditorBrowsable (EditorBrowsableState.Never)]
114 public new event PaintEventHandler Paint {
115 add { base.Paint += value; }
116 remove { base.Paint -= value; }
119 public event EventHandler SelectedIndexChanged;
122 [EditorBrowsable (EditorBrowsableState.Never)]
123 public new event EventHandler TextChanged {
124 add { base.TextChanged += value; }
125 remove { base.TextChanged -= value; }
130 #region Public Constructors
133 background_color = ThemeEngine.Current.ColorWindow;
134 checked_indices = new CheckedIndexCollection (this);
135 checked_items = new CheckedListViewItemCollection (this);
136 columns = new ColumnHeaderCollection (this);
137 foreground_color = SystemColors.WindowText;
138 items = new ListViewItemCollection (this);
139 selected_indices = new SelectedIndexCollection (this);
140 selected_items = new SelectedListViewItemCollection (this);
142 border_style = BorderStyle.Fixed3D;
144 header_control = new HeaderControl (this);
145 header_control.Visible = false;
146 item_control = new ItemControl (this);
147 item_control.Visible = true;
149 h_scroll = new HScrollBar ();
150 v_scroll = new VScrollBar ();
151 h_marker = v_marker = 0;
152 keysearch_tickcnt = 0;
154 // scroll bars are disabled initially
155 h_scroll.Visible = false;
156 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
157 v_scroll.Visible = false;
158 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
161 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
162 base.Paint += new PaintEventHandler (ListView_Paint);
163 SizeChanged += new EventHandler (ListView_SizeChanged);
165 this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
167 #endregion // Public Constructors
169 #region Private Internal Properties
170 internal Size CheckBoxSize {
172 if (this.check_boxes) {
173 if (this.state_image_list != null)
174 return this.state_image_list.ImageSize;
176 return ThemeEngine.Current.ListViewCheckBoxSize;
182 internal bool CanMultiselect {
184 if (multiselect && (XplatUI.State.ModifierKeys & (Keys.Control | Keys.Shift)) != 0)
191 #endregion // Private Internal Properties
193 #region Protected Properties
194 protected override CreateParams CreateParams {
195 get { return base.CreateParams; }
198 protected override Size DefaultSize {
199 get { return ThemeEngine.Current.ListViewDefaultSize; }
201 #endregion // Protected Properties
203 #region Public Instance Properties
204 [DefaultValue (ItemActivation.Standard)]
205 public ItemActivation Activation {
206 get { return activation; }
208 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
209 value != ItemActivation.TwoClick) {
210 throw new InvalidEnumArgumentException (string.Format
211 ("Enum argument value '{0}' is not valid for Activation", value));
218 [DefaultValue (ListViewAlignment.Top)]
220 public ListViewAlignment Alignment {
221 get { return alignment; }
223 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
224 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
225 throw new InvalidEnumArgumentException (string.Format
226 ("Enum argument value '{0}' is not valid for Alignment", value));
229 if (this.alignment != value) {
231 // alignment does not matter in Details/List views
232 if (this.view == View.LargeIcon ||
233 this.View == View.SmallIcon)
239 [DefaultValue (false)]
240 public bool AllowColumnReorder {
241 get { return allow_column_reorder; }
242 set { allow_column_reorder = value; }
245 [DefaultValue (true)]
246 public bool AutoArrange {
247 get { return auto_arrange; }
249 if (auto_arrange != value) {
250 auto_arrange = value;
251 // autoarrange does not matter in Details/List views
252 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
258 public override Color BackColor {
260 if (background_color.IsEmpty)
261 return ThemeEngine.Current.ColorWindow;
263 return background_color;
265 set { background_color = value; }
269 [EditorBrowsable (EditorBrowsableState.Never)]
270 public override Image BackgroundImage {
271 get { return background_image; }
273 if (value == background_image)
276 background_image = value;
277 OnBackgroundImageChanged (EventArgs.Empty);
281 [DefaultValue (BorderStyle.Fixed3D)]
283 public BorderStyle BorderStyle {
284 get { return InternalBorderStyle; }
285 set { InternalBorderStyle = value; }
288 [DefaultValue (false)]
289 public bool CheckBoxes {
290 get { return check_boxes; }
292 if (check_boxes != value) {
300 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
301 public CheckedIndexCollection CheckedIndices {
302 get { return checked_indices; }
306 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
307 public CheckedListViewItemCollection CheckedItems {
308 get { return checked_items; }
311 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
313 [MergableProperty (false)]
314 public ColumnHeaderCollection Columns {
315 get { return columns; }
319 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
320 public ListViewItem FocusedItem {
321 get { return focused_item; }
324 public override Color ForeColor {
326 if (foreground_color.IsEmpty)
327 return ThemeEngine.Current.ColorWindowText;
329 return foreground_color;
331 set { foreground_color = value; }
334 [DefaultValue (false)]
335 public bool FullRowSelect {
336 get { return full_row_select; }
337 set { full_row_select = value; }
340 [DefaultValue (false)]
341 public bool GridLines {
342 get { return grid_lines; }
344 if (grid_lines != value) {
351 [DefaultValue (ColumnHeaderStyle.Clickable)]
352 public ColumnHeaderStyle HeaderStyle {
353 get { return header_style; }
355 if (header_style == value)
359 case ColumnHeaderStyle.Clickable:
360 case ColumnHeaderStyle.Nonclickable:
361 case ColumnHeaderStyle.None:
364 throw new InvalidEnumArgumentException (string.Format
365 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
368 header_style = value;
369 if (view == View.Details)
374 [DefaultValue (true)]
375 public bool HideSelection {
376 get { return hide_selection; }
378 if (hide_selection != value) {
379 hide_selection = value;
385 [DefaultValue (false)]
386 public bool HoverSelection {
387 get { return hover_selection; }
388 set { hover_selection = value; }
391 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
393 [MergableProperty (false)]
394 public ListViewItemCollection Items {
395 get { return items; }
398 [DefaultValue (false)]
399 public bool LabelEdit {
400 get { return label_edit; }
401 set { label_edit = value; }
404 [DefaultValue (true)]
406 public bool LabelWrap {
407 get { return label_wrap; }
409 if (label_wrap != value) {
416 [DefaultValue (null)]
417 public ImageList LargeImageList {
418 get { return large_image_list; }
420 large_image_list = value;
426 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
427 public IComparer ListViewItemSorter {
428 get { return item_sorter; }
429 set { item_sorter = value; }
432 [DefaultValue (true)]
433 public bool MultiSelect {
434 get { return multiselect; }
435 set { multiselect = value; }
438 [DefaultValue (true)]
439 public bool Scrollable {
440 get { return scrollable; }
442 if (scrollable != value) {
450 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
451 public SelectedIndexCollection SelectedIndices {
452 get { return selected_indices; }
456 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
457 public SelectedListViewItemCollection SelectedItems {
458 get { return selected_items; }
461 [DefaultValue (null)]
462 public ImageList SmallImageList {
463 get { return small_image_list; }
465 small_image_list = value;
470 [DefaultValue (SortOrder.None)]
471 public SortOrder Sorting {
472 get { return sort_order; }
474 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
475 value != SortOrder.None) {
476 throw new InvalidEnumArgumentException (string.Format
477 ("Enum argument value '{0}' is not valid for Sorting", value));
480 if (sort_order != value) {
487 [DefaultValue (null)]
488 public ImageList StateImageList {
489 get { return state_image_list; }
491 state_image_list = value;
498 [EditorBrowsable (EditorBrowsableState.Never)]
499 public override string Text {
508 OnTextChanged (EventArgs.Empty);
513 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
514 public ListViewItem TopItem {
517 if (this.items.Count == 0)
519 // if contents are not scrolled
520 // it is the first item
521 else if (h_marker == 0 && v_marker == 0)
522 return this.items [0];
523 // do a hit test for the scrolled position
525 foreach (ListViewItem item in this.items) {
526 if (item.Bounds.X >= 0 && item.Bounds.Y >= 0)
534 [DefaultValue (View.LargeIcon)]
538 if (value != View.Details && value != View.LargeIcon &&
539 value != View.List && value != View.SmallIcon ) {
540 throw new InvalidEnumArgumentException (string.Format
541 ("Enum argument value '{0}' is not valid for View", value));
545 h_scroll.Value = v_scroll.Value = 0;
551 #endregion // Public Instance Properties
553 #region Internal Methods Properties
555 internal int FirstVisibleIndex {
558 if (this.items.Count == 0)
561 if (h_marker == 0 && v_marker == 0)
564 foreach (ListViewItem item in this.items) {
565 if (item.Bounds.Right >= 0 && item.Bounds.Bottom >= 0)
574 internal int LastVisibleIndex {
576 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
577 if (Items[i].Bounds.Y > ClientRectangle.Bottom)
581 return Items.Count - 1;
585 internal int TotalWidth {
586 get { return Math.Max (this.Width, this.layout_wd); }
589 internal int TotalHeight {
590 get { return Math.Max (this.Height, this.layout_ht); }
593 internal void Redraw (bool recalculate)
595 // Avoid calculations when control is being updated
600 CalculateListView (this.alignment);
605 internal Size GetChildColumnSize (int index)
607 Size ret_size = Size.Empty;
608 ColumnHeader col = this.columns [index];
610 if (col.Width == -2) { // autosize = max(items, columnheader)
611 Size size = Size.Ceiling (this.DeviceContext.MeasureString
612 (col.Text, this.Font));
613 ret_size = BiggestItem (index);
614 if (size.Width > ret_size.Width)
617 else { // -1 and all the values < -2 are put under one category
618 ret_size = BiggestItem (index);
619 // fall back to empty columns' width if no subitem is available for a column
620 if (ret_size.IsEmpty) {
621 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
622 if (col.Text.Length > 0)
623 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
624 (col.Text, this.Font)).Height;
626 ret_size.Height = this.Font.Height;
630 // adjust the size for icon and checkbox for 0th column
632 ret_size.Width += (this.CheckBoxSize.Width + 4);
633 if (this.small_image_list != null)
634 ret_size.Width += this.small_image_list.ImageSize.Width;
639 // Returns the size of biggest item text in a column.
640 private Size BiggestItem (int col)
642 Size temp = Size.Empty;
643 Size ret_size = Size.Empty;
645 // 0th column holds the item text, we check the size of
646 // the various subitems falling in that column and get
647 // the biggest one's size.
648 foreach (ListViewItem item in items) {
649 if (col >= item.SubItems.Count)
652 temp = Size.Ceiling (this.DeviceContext.MeasureString
653 (item.SubItems [col].Text, this.Font));
654 if (temp.Width > ret_size.Width)
658 // adjustment for space
659 if (!ret_size.IsEmpty)
665 // Sets the size of the biggest item text as per the view
666 private void CalcTextSize ()
668 // clear the old value
669 text_size = Size.Empty;
671 if (items.Count == 0)
674 text_size = BiggestItem (0);
676 if (view == View.LargeIcon && this.label_wrap) {
677 Size temp = Size.Empty;
678 if (this.check_boxes)
679 temp.Width += 2 * this.CheckBoxSize.Width;
680 if (large_image_list != null)
681 temp.Width += large_image_list.ImageSize.Width;
684 // wrapping is done for two lines only
685 if (text_size.Width > temp.Width) {
686 text_size.Width = temp.Width;
687 text_size.Height *= 2;
690 else if (view == View.List) {
691 // in list view max text shown in determined by the
692 // control width, even if scolling is enabled.
693 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
694 if (this.small_image_list != null)
695 max_wd -= this.small_image_list.ImageSize.Width;
697 if (text_size.Width > max_wd)
698 text_size.Width = max_wd;
701 // we do the default settings, if we have got 0's
702 if (text_size.Height <= 0)
703 text_size.Height = this.Font.Height;
704 if (text_size.Width <= 0)
705 text_size.Width = this.Width;
708 text_size.Width += 4;
709 text_size.Height += 2;
712 private void CalculateScrollBars ()
714 Rectangle client_area = ClientRectangle;
716 if (!this.scrollable || this.items.Count <= 0) {
717 h_scroll.Visible = false;
718 v_scroll.Visible = false;
722 // making a scroll bar visible might make
723 // other scroll bar visible
724 if (layout_wd > client_area.Right) {
725 h_scroll.Visible = true;
726 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
727 v_scroll.Visible = true;
729 v_scroll.Visible = false;
730 } else if (layout_ht > client_area.Bottom) {
731 v_scroll.Visible = true;
732 if ((layout_wd + v_scroll.Width) > client_area.Right)
733 h_scroll.Visible = true;
735 h_scroll.Visible = false;
737 h_scroll.Visible = false;
738 v_scroll.Visible = false;
741 item_control.Height = ClientRectangle.Height - header_control.Height;
743 if (h_scroll.Visible) {
744 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
745 h_scroll.Minimum = 0;
747 // if v_scroll is visible, adjust the maximum of the
748 // h_scroll to account for the width of v_scroll
749 if (v_scroll.Visible) {
750 h_scroll.Maximum = layout_wd + v_scroll.Width;
751 h_scroll.Width = client_area.Width - v_scroll.Width;
754 h_scroll.Maximum = layout_wd;
755 h_scroll.Width = client_area.Width;
758 h_scroll.LargeChange = client_area.Width;
759 h_scroll.SmallChange = Font.Height;
760 item_control.Height -= h_scroll.Height;
763 if (header_control.Visible)
764 header_control.Width = ClientRectangle.Width;
765 item_control.Width = ClientRectangle.Width;
767 if (v_scroll.Visible) {
768 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
769 v_scroll.Minimum = 0;
771 // if h_scroll is visible, adjust the maximum of the
772 // v_scroll to account for the height of h_scroll
773 if (h_scroll.Visible) {
774 v_scroll.Maximum = layout_ht + h_scroll.Height;
775 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
777 v_scroll.Maximum = layout_ht;
778 v_scroll.Height = client_area.Height;
781 v_scroll.LargeChange = client_area.Height;
782 v_scroll.SmallChange = Font.Height;
783 if (header_control.Visible)
784 header_control.Width -= v_scroll.Width;
785 item_control.Width -= v_scroll.Width;
789 ColumnHeader GetReorderedColumn (int index)
791 if (reordered_column_indices == null)
792 return Columns [index];
794 return Columns [reordered_column_indices [index]];
797 void ReorderColumn (ColumnHeader col, int index)
799 if (reordered_column_indices == null) {
800 reordered_column_indices = new int [Columns.Count];
801 for (int i = 0; i < Columns.Count; i++)
802 reordered_column_indices [i] = i;
805 if (reordered_column_indices [index] == col.Index)
808 int[] curr = reordered_column_indices;
809 int[] result = new int [Columns.Count];
811 for (int i = 0; i < Columns.Count; i++) {
812 if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
816 result [i] = col.Index;
818 result [i] = curr [curr_idx++];
821 reordered_column_indices = result;
823 header_control.Invalidate ();
824 item_control.Invalidate ();
827 Size LargeIconItemSize {
829 int w = Math.Max (text_size.Width, 2 + CheckBoxSize.Width + LargeImageList.ImageSize.Width);
830 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, LargeImageList.ImageSize.Height);
831 return new Size (w, h);
835 Size SmallIconItemSize {
837 int w = text_size.Width + 2 + CheckBoxSize.Width + SmallImageList.ImageSize.Width;
838 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, SmallImageList.ImageSize.Height));
839 return new Size (w, h);
843 void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
845 header_control.Visible = false;
846 header_control.Size = Size.Empty;
847 item_control.Location = Point.Empty;
849 if (items.Count == 0)
852 Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
856 Rectangle area = item_control.ClientRectangle;
859 rows = (int) Math.Floor ((double)area.Height / (double)(sz.Height + y_spacing));
862 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
864 cols = (int) Math.Floor ((double)area.Width / (double)(sz.Width + x_spacing));
867 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
870 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
871 layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
874 foreach (ListViewItem item in items) {
875 int x = col * (sz.Width + x_spacing);
876 int y = row * (sz.Height + y_spacing);
877 item.Location = new Point (x, y);
892 item_control.Size = new Size (layout_wd, layout_ht);
897 if (columns.Count == 0 || header_style == ColumnHeaderStyle.None) {
898 header_control.Visible = false;
899 header_control.Size = Size.Empty;
904 for (int i = 0; i < Columns.Count; i++) {
905 ColumnHeader col = GetReorderedColumn (i);
908 col.CalcColumnHeader ();
912 header_control.Width = x;
913 header_control.Height = columns [0].Ht;
914 header_control.Visible = true;
917 void LayoutDetails ()
921 item_control.Location = new Point (0, header_control.Height);
924 if (items.Count > 0) {
925 foreach (ListViewItem item in items) {
927 item.Location = new Point (0, y);
928 y += item.Bounds.Height + 2;
931 // some space for bottom gridline
936 layout_wd = Math.Max (header_control.Width, item_control.Width);
937 layout_ht = y + header_control.Height;
940 private void CalculateListView (ListViewAlignment align)
950 LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
954 LayoutIcons (true, alignment == ListViewAlignment.Left,
955 ThemeEngine.Current.ListViewHorizontalSpacing,
956 ThemeEngine.Current.ListViewVerticalSpacing);
960 LayoutIcons (false, true, 4, 2);
964 CalculateScrollBars ();
967 internal void UpdateSelection (ListViewItem item)
971 if (!CanMultiselect && SelectedItems.Count > 0) {
972 SelectedItems.Clear ();
973 SelectedIndices.list.Clear ();
976 if (!SelectedItems.Contains (item)) {
977 SelectedItems.list.Add (item);
978 SelectedIndices.list.Add (item.Index);
981 SelectedItems.list.Remove (item);
982 SelectedIndices.list.Remove (item.Index);
986 private bool KeySearchString (KeyEventArgs ke)
988 int current_tickcnt = Environment.TickCount;
989 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
990 keysearch_text = string.Empty;
993 keysearch_text += (char) ke.KeyData;
994 keysearch_tickcnt = current_tickcnt;
996 int i = FocusedItem.Index;
998 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
999 CompareOptions.IgnoreCase)) {
1000 SetFocusedItem (Items [i]);
1001 items [i].Selected = true;
1005 i = (i + 1 < Items.Count) ? i+1 : 0;
1007 if (i == FocusedItem.Index)
1013 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1015 if (ke.Handled || Items.Count == 0)
1021 switch (ke.KeyCode) {
1024 if (focused_item != null && focused_item.Index + 1 < Items.Count) {
1025 index = focused_item.Index + 1;
1030 index = Items.Count - 1;
1038 if (focused_item != null)
1039 index = focused_item.Index;
1049 if (focused_item != null)
1050 index = focused_item.Index + 1;
1054 if (index == items.Count)
1060 if (focused_item != null)
1061 index = focused_item.Index;
1074 if (KeySearchString (ke)) {
1083 items [index].Selected = true;
1084 SetFocusedItem (items [index]);
1085 EnsureVisible (index);
1090 internal class ItemControl : Control {
1093 ListViewItem clicked_item;
1094 ListViewItem last_clicked_item;
1096 public ItemControl (ListView owner)
1099 DoubleClick += new EventHandler(ItemsDoubleClick);
1100 MouseDown += new MouseEventHandler(ItemsMouseDown);
1101 MouseHover += new EventHandler(ItemsMouseHover);
1102 MouseUp += new MouseEventHandler(ItemsMouseUp);
1103 Paint += new PaintEventHandler (ItemsPaint);
1106 void ItemsDoubleClick (object sender, EventArgs e)
1108 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1109 owner.ItemActivate (this, e);
1112 private void ItemsMouseDown (object sender, MouseEventArgs me)
1114 if (owner.items.Count == 0)
1117 Point pt = new Point (me.X, me.Y);
1118 foreach (ListViewItem item in owner.items) {
1119 if (item.CheckRectReal.Contains (pt)) {
1120 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1121 item.Checked = !item.Checked;
1123 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1125 // Raise the ItemCheck event
1126 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1127 owner.OnItemCheck (ice);
1131 if (owner.View == View.Details && !owner.FullRowSelect) {
1132 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1133 clicked_item = item;
1137 if (item.Bounds.Contains (pt)) {
1138 clicked_item = item;
1144 owner.SetFocusedItem (clicked_item);
1146 if (clicked_item != null) {
1147 bool changed = !clicked_item.Selected;
1148 clicked_item.Selected = true;;
1151 owner.OnSelectedIndexChanged (EventArgs.Empty);
1153 // Raise double click if the item was clicked. On MS the
1154 // double click is only raised if you double click an item
1155 if (me.Clicks > 1 && clicked_item != null)
1156 owner.OnDoubleClick (EventArgs.Empty);
1157 else if (me.Clicks == 1 && clicked_item != null)
1158 owner.OnClick (EventArgs.Empty);
1159 } else if (owner.selected_indices.Count > 0) {
1160 // Raise the event if there was at least one item
1161 // selected and the user click on a dead area (unselecting all)
1162 owner.SelectedItems.Clear ();
1163 owner.SelectedIndices.list.Clear ();
1164 owner.OnSelectedIndexChanged (EventArgs.Empty);
1168 private void ItemsMouseHover (object sender, EventArgs e)
1170 if (Capture || !owner.hover_selection)
1173 Point pt = PointToClient (Control.MousePosition);
1174 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1179 item.Selected = true;
1180 owner.OnSelectedIndexChanged (new EventArgs ());
1183 private void ItemsMouseUp (object sender, MouseEventArgs me)
1186 if (owner.Items.Count == 0)
1189 Point pt = new Point (me.X, me.Y);
1191 Rectangle rect = Rectangle.Empty;
1192 if (clicked_item != null) {
1193 if (owner.view == View.Details && !owner.full_row_select)
1194 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1196 rect = clicked_item.Bounds;
1198 if (rect.Contains (pt)) {
1199 switch (owner.activation) {
1200 case ItemActivation.OneClick:
1201 owner.ItemActivate (this, EventArgs.Empty);
1204 case ItemActivation.TwoClick:
1205 if (last_clicked_item == clicked_item) {
1206 owner.ItemActivate (this, EventArgs.Empty);
1207 last_clicked_item = null;
1209 last_clicked_item = clicked_item;
1212 // DoubleClick activation is handled in another handler
1218 clicked_item = null;
1221 private void ItemsPaint (object sender, PaintEventArgs pe)
1223 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1227 private void ListView_Paint (object sender, PaintEventArgs pe)
1229 if (Width <= 0 || Height <= 0 || !Visible || updating)
1232 CalculateScrollBars ();
1235 private void ListView_SizeChanged (object sender, EventArgs e)
1237 CalculateListView (alignment);
1240 private void SetFocusedItem (ListViewItem item)
1242 if (focused_item != null)
1243 focused_item.Focused = false;
1246 item.Focused = true;
1248 focused_item = item;
1251 private void HorizontalScroller (object sender, EventArgs e)
1253 // Avoid unnecessary flickering, when button is
1254 // kept pressed at the end
1255 if (h_marker != h_scroll.Value) {
1257 int pixels = h_marker - h_scroll.Value;
1259 h_marker = h_scroll.Value;
1260 if (header_control.Visible)
1261 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1263 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1267 private void VerticalScroller (object sender, EventArgs e)
1269 // Avoid unnecessary flickering, when button is
1270 // kept pressed at the end
1271 if (v_marker != v_scroll.Value) {
1272 int pixels = v_marker - v_scroll.Value;
1273 Rectangle area = item_control.ClientRectangle;
1274 v_marker = v_scroll.Value;
1275 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1278 #endregion // Internal Methods Properties
1280 #region Protected Methods
1281 protected override void CreateHandle ()
1283 base.CreateHandle ();
1286 protected override void Dispose (bool disposing)
1289 h_scroll.Dispose ();
1290 v_scroll.Dispose ();
1292 large_image_list = null;
1293 small_image_list = null;
1294 state_image_list = null;
1297 base.Dispose (disposing);
1300 protected override bool IsInputKey (Keys keyData)
1317 return base.IsInputKey (keyData);
1320 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1322 if (AfterLabelEdit != null)
1323 AfterLabelEdit (this, e);
1326 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1328 if (BeforeLabelEdit != null)
1329 BeforeLabelEdit (this, e);
1332 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1334 if (ColumnClick != null)
1335 ColumnClick (this, e);
1338 protected override void OnEnabledChanged (EventArgs e)
1340 base.OnEnabledChanged (e);
1343 protected override void OnFontChanged (EventArgs e)
1345 base.OnFontChanged (e);
1349 protected override void OnHandleCreated (EventArgs e)
1351 base.OnHandleCreated (e);
1353 Controls.AddImplicit (header_control);
1354 Controls.AddImplicit (item_control);
1355 Controls.AddImplicit (this.v_scroll);
1356 Controls.AddImplicit (this.h_scroll);
1360 protected override void OnHandleDestroyed (EventArgs e)
1362 base.OnHandleDestroyed (e);
1365 protected virtual void OnItemActivate (EventArgs e)
1367 if (ItemActivate != null)
1368 ItemActivate (this, e);
1371 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1373 if (ItemCheck != null)
1374 ItemCheck (this, ice);
1377 protected virtual void OnItemDrag (ItemDragEventArgs e)
1379 if (ItemDrag != null)
1383 protected virtual void OnSelectedIndexChanged (EventArgs e)
1385 if (SelectedIndexChanged != null)
1386 SelectedIndexChanged (this, e);
1389 protected override void OnSystemColorsChanged (EventArgs e)
1391 base.OnSystemColorsChanged (e);
1394 protected void RealizeProperties ()
1399 protected void UpdateExtendedStyles ()
1404 protected override void WndProc (ref Message m)
1406 base.WndProc (ref m);
1408 #endregion // Protected Methods
1410 #region Public Instance Methods
1411 public void ArrangeIcons ()
1413 ArrangeIcons (this.alignment);
1416 public void ArrangeIcons (ListViewAlignment alignment)
1418 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1419 if (view == View.LargeIcon || view == View.SmallIcon) {
1420 this.CalculateListView (alignment);
1421 // we have done the calculations already
1422 this.Redraw (false);
1426 public void BeginUpdate ()
1428 // flag to avoid painting
1432 public void Clear ()
1435 items.Clear (); // Redraw (true) called here
1438 public void EndUpdate ()
1440 // flag to avoid painting
1443 // probably, now we need a redraw with recalculations
1447 public void EnsureVisible (int index)
1449 if (index < 0 || index >= items.Count || scrollable == false)
1452 Rectangle view_rect = item_control.ClientRectangle;
1453 Rectangle bounds = items [index].Bounds;
1455 if (view_rect.Contains (bounds))
1458 if (bounds.Left < 0)
1459 h_scroll.Value += bounds.Left;
1460 else if (bounds.Right > view_rect.Right)
1461 h_scroll.Value += (bounds.Right - view_rect.Right);
1464 v_scroll.Value += bounds.Top;
1465 else if (bounds.Bottom > view_rect.Bottom)
1466 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1469 public ListViewItem GetItemAt (int x, int y)
1471 foreach (ListViewItem item in items) {
1472 if (item.Bounds.Contains (x, y))
1478 public Rectangle GetItemRect (int index)
1480 return GetItemRect (index, ItemBoundsPortion.Entire);
1483 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1485 if (index < 0 || index >= items.Count)
1486 throw new IndexOutOfRangeException ("Invalid Index");
1488 return items [index].GetBounds (portion);
1493 if (sort_order != SortOrder.None)
1494 items.list.Sort (item_sorter);
1496 if (sort_order == SortOrder.Descending)
1497 items.list.Reverse ();
1502 public override string ToString ()
1504 int count = this.Items.Count;
1507 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1509 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1511 #endregion // Public Instance Methods
1516 class HeaderControl : Control {
1519 bool column_resize_active = false;
1520 ColumnHeader resize_column;
1521 ColumnHeader clicked_column;
1522 ColumnHeader drag_column;
1524 int drag_to_index = -1;
1526 public HeaderControl (ListView owner)
1529 MouseDown += new MouseEventHandler (HeaderMouseDown);
1530 MouseMove += new MouseEventHandler (HeaderMouseMove);
1531 MouseUp += new MouseEventHandler (HeaderMouseUp);
1532 Paint += new PaintEventHandler (HeaderPaint);
1535 private ColumnHeader ColumnAtX (int x)
1537 Point pt = new Point (x, 0);
1538 ColumnHeader result = null;
1539 foreach (ColumnHeader col in owner.Columns) {
1540 if (col.Rect.Contains (pt)) {
1548 private int GetReorderedIndex (ColumnHeader col)
1550 if (owner.reordered_column_indices == null)
1553 for (int i = 0; i < owner.Columns.Count; i++)
1554 if (owner.reordered_column_indices [i] == col.Index)
1556 throw new Exception ("Column index missing from reordered array");
1559 private void HeaderMouseDown (object sender, MouseEventArgs me)
1561 if (resize_column != null) {
1562 column_resize_active = true;
1567 clicked_column = ColumnAtX (me.X + owner.h_marker);
1569 if (clicked_column != null) {
1571 if (owner.AllowColumnReorder) {
1573 drag_column = (ColumnHeader) clicked_column.Clone ();
1574 drag_column.column_rect = clicked_column.Rect;
1575 drag_to_index = GetReorderedIndex (clicked_column);
1577 clicked_column.pressed = true;
1578 Rectangle bounds = clicked_column.Rect;
1579 bounds.X -= owner.h_marker;
1580 Invalidate (bounds);
1585 private void HeaderMouseMove (object sender, MouseEventArgs me)
1587 Point pt = new Point (me.X + owner.h_marker, me.Y);
1589 if (column_resize_active) {
1590 resize_column.Width = pt.X - resize_column.X;
1591 if (resize_column.Width < 0)
1592 resize_column.Width = 0;
1596 resize_column = null;
1598 if (clicked_column != null) {
1599 if (owner.AllowColumnReorder) {
1602 r = drag_column.column_rect;
1603 r.X = r.X + me.X - drag_x;
1604 drag_column.column_rect = r;
1606 int x = me.X + owner.h_marker;
1607 ColumnHeader over = ColumnAtX (x);
1608 if (x < over.X + over.Width / 2)
1609 drag_to_index = GetReorderedIndex (over);
1611 drag_to_index = GetReorderedIndex (over) + 1;
1614 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1615 bool pressed = clicked_column.pressed;
1616 clicked_column.pressed = over == clicked_column;
1617 if (clicked_column.pressed ^ pressed) {
1618 Rectangle bounds = clicked_column.Rect;
1619 bounds.X -= owner.h_marker;
1620 Invalidate (bounds);
1626 for (int i = 0; i < owner.Columns.Count; i++) {
1627 Rectangle zone = owner.Columns [i].Rect;
1628 zone.X = zone.Right - 5;
1630 if (zone.Contains (pt)) {
1631 resize_column = owner.Columns [i];
1636 if (resize_column == null)
1637 Cursor = Cursors.Default;
1639 Cursor = Cursors.VSplit;
1642 void HeaderMouseUp (object sender, MouseEventArgs me)
1646 if (column_resize_active) {
1647 column_resize_active = false;
1648 resize_column = null;
1649 Cursor = Cursors.Default;
1653 if (clicked_column != null && clicked_column.pressed) {
1654 clicked_column.pressed = false;
1655 Rectangle bounds = clicked_column.Rect;
1656 bounds.X -= owner.h_marker;
1657 Invalidate (bounds);
1658 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1661 if (drag_column != null && owner.AllowColumnReorder) {
1663 if (drag_to_index > GetReorderedIndex (clicked_column))
1665 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1666 owner.ReorderColumn (clicked_column, drag_to_index);
1671 clicked_column = null;
1674 void HeaderPaint (object sender, PaintEventArgs pe)
1676 if (Width <= 0 || Height <= 0 || !Visible || owner.updating)
1679 Theme theme = ThemeEngine.Current;
1680 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1682 if (drag_column == null)
1686 if (drag_to_index == owner.Columns.Count)
1687 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1689 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1690 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1695 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1697 internal ArrayList list;
1698 private ListView owner;
1700 #region Public Constructor
1701 public CheckedIndexCollection (ListView owner)
1703 list = new ArrayList ();
1706 #endregion // Public Constructor
1708 #region Public Properties
1710 public virtual int Count {
1711 get { return list.Count; }
1714 public virtual bool IsReadOnly {
1715 get { return true; }
1718 public int this [int index] {
1720 if (index < 0 || index >= list.Count)
1721 throw new ArgumentOutOfRangeException ("Index out of range.");
1722 return (int) list [index];
1726 bool ICollection.IsSynchronized {
1727 get { return false; }
1730 object ICollection.SyncRoot {
1731 get { return this; }
1734 bool IList.IsFixedSize {
1735 get { return true; }
1738 object IList.this [int index] {
1739 get { return this [index]; }
1740 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1742 #endregion // Public Properties
1744 #region Public Methods
1745 public bool Contains (int checkedIndex)
1747 return list.Contains (checkedIndex);
1750 public virtual IEnumerator GetEnumerator ()
1752 return list.GetEnumerator ();
1755 void ICollection.CopyTo (Array dest, int index)
1757 list.CopyTo (dest, index);
1760 int IList.Add (object value)
1762 throw new NotSupportedException ("Add operation is not supported.");
1767 throw new NotSupportedException ("Clear operation is not supported.");
1770 bool IList.Contains (object checkedIndex)
1772 return list.Contains (checkedIndex);
1775 int IList.IndexOf (object checkedIndex)
1777 return list.IndexOf (checkedIndex);
1780 void IList.Insert (int index, object value)
1782 throw new NotSupportedException ("Insert operation is not supported.");
1785 void IList.Remove (object value)
1787 throw new NotSupportedException ("Remove operation is not supported.");
1790 void IList.RemoveAt (int index)
1792 throw new NotSupportedException ("RemoveAt operation is not supported.");
1795 public int IndexOf (int checkedIndex)
1797 return list.IndexOf (checkedIndex);
1799 #endregion // Public Methods
1801 } // CheckedIndexCollection
1803 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1805 internal ArrayList list;
1806 private ListView owner;
1808 #region Public Constructor
1809 public CheckedListViewItemCollection (ListView owner)
1811 list = new ArrayList ();
1814 #endregion // Public Constructor
1816 #region Public Properties
1818 public virtual int Count {
1819 get { return list.Count; }
1822 public virtual bool IsReadOnly {
1823 get { return true; }
1826 public ListViewItem this [int index] {
1828 if (index < 0 || index >= list.Count)
1829 throw new ArgumentOutOfRangeException ("Index out of range.");
1830 return (ListViewItem) list [index];
1834 bool ICollection.IsSynchronized {
1835 get { return list.IsSynchronized; }
1838 object ICollection.SyncRoot {
1839 get { return this; }
1842 bool IList.IsFixedSize {
1843 get { return true; }
1846 object IList.this [int index] {
1847 get { return this [index]; }
1848 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1850 #endregion // Public Properties
1852 #region Public Methods
1853 public bool Contains (ListViewItem item)
1855 return list.Contains (item);
1858 public virtual void CopyTo (Array dest, int index)
1860 list.CopyTo (dest, index);
1863 public virtual IEnumerator GetEnumerator ()
1865 return list.GetEnumerator ();
1868 int IList.Add (object value)
1870 throw new NotSupportedException ("Add operation is not supported.");
1875 throw new NotSupportedException ("Clear operation is not supported.");
1878 bool IList.Contains (object item)
1880 return list.Contains (item);
1883 int IList.IndexOf (object item)
1885 return list.IndexOf (item);
1888 void IList.Insert (int index, object value)
1890 throw new NotSupportedException ("Insert operation is not supported.");
1893 void IList.Remove (object value)
1895 throw new NotSupportedException ("Remove operation is not supported.");
1898 void IList.RemoveAt (int index)
1900 throw new NotSupportedException ("RemoveAt operation is not supported.");
1903 public int IndexOf (ListViewItem item)
1905 return list.IndexOf (item);
1907 #endregion // Public Methods
1909 } // CheckedListViewItemCollection
1911 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1913 internal ArrayList list;
1914 private ListView owner;
1916 #region Public Constructor
1917 public ColumnHeaderCollection (ListView owner)
1919 list = new ArrayList ();
1922 #endregion // Public Constructor
1924 #region Public Properties
1926 public virtual int Count {
1927 get { return list.Count; }
1930 public virtual bool IsReadOnly {
1931 get { return false; }
1934 public virtual ColumnHeader this [int index] {
1936 if (index < 0 || index >= list.Count)
1937 throw new ArgumentOutOfRangeException ("Index out of range.");
1938 return (ColumnHeader) list [index];
1942 bool ICollection.IsSynchronized {
1943 get { return true; }
1946 object ICollection.SyncRoot {
1947 get { return this; }
1950 bool IList.IsFixedSize {
1951 get { return list.IsFixedSize; }
1954 object IList.this [int index] {
1955 get { return this [index]; }
1956 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1958 #endregion // Public Properties
1960 #region Public Methods
1961 public virtual int Add (ColumnHeader value)
1964 value.owner = this.owner;
1965 idx = list.Add (value);
1966 owner.Redraw (true);
1970 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1972 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1973 this.Add (colHeader);
1977 public virtual void AddRange (ColumnHeader [] values)
1979 foreach (ColumnHeader colHeader in values) {
1980 colHeader.owner = this.owner;
1984 owner.Redraw (true);
1987 public virtual void Clear ()
1990 owner.Redraw (true);
1993 public bool Contains (ColumnHeader value)
1995 return list.Contains (value);
1998 public virtual IEnumerator GetEnumerator ()
2000 return list.GetEnumerator ();
2003 void ICollection.CopyTo (Array dest, int index)
2005 list.CopyTo (dest, index);
2008 int IList.Add (object value)
2010 if (! (value is ColumnHeader)) {
2011 throw new ArgumentException ("Not of type ColumnHeader", "value");
2014 return this.Add ((ColumnHeader) value);
2017 bool IList.Contains (object value)
2019 if (! (value is ColumnHeader)) {
2020 throw new ArgumentException ("Not of type ColumnHeader", "value");
2023 return this.Contains ((ColumnHeader) value);
2026 int IList.IndexOf (object value)
2028 if (! (value is ColumnHeader)) {
2029 throw new ArgumentException ("Not of type ColumnHeader", "value");
2032 return this.IndexOf ((ColumnHeader) value);
2035 void IList.Insert (int index, object value)
2037 if (! (value is ColumnHeader)) {
2038 throw new ArgumentException ("Not of type ColumnHeader", "value");
2041 this.Insert (index, (ColumnHeader) value);
2044 void IList.Remove (object value)
2046 if (! (value is ColumnHeader)) {
2047 throw new ArgumentException ("Not of type ColumnHeader", "value");
2050 this.Remove ((ColumnHeader) value);
2053 public int IndexOf (ColumnHeader value)
2055 return list.IndexOf (value);
2058 public void Insert (int index, ColumnHeader value)
2060 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2061 // but it's really only greater.
2062 if (index < 0 || index > list.Count)
2063 throw new ArgumentOutOfRangeException ("Index out of range.");
2065 value.owner = this.owner;
2066 list.Insert (index, value);
2067 owner.Redraw (true);
2070 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2072 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2073 this.Insert (index, colHeader);
2076 public virtual void Remove (ColumnHeader column)
2078 // TODO: Update Column internal index ?
2079 list.Remove (column);
2080 owner.Redraw (true);
2083 public virtual void RemoveAt (int index)
2085 if (index < 0 || index >= list.Count)
2086 throw new ArgumentOutOfRangeException ("Index out of range.");
2088 // TODO: Update Column internal index ?
2089 list.RemoveAt (index);
2090 owner.Redraw (true);
2092 #endregion // Public Methods
2095 } // ColumnHeaderCollection
2097 public class ListViewItemCollection : IList, ICollection, IEnumerable
2099 internal ArrayList list;
2100 private ListView owner;
2102 #region Public Constructor
2103 public ListViewItemCollection (ListView owner)
2105 list = new ArrayList ();
2108 #endregion // Public Constructor
2110 #region Public Properties
2112 public virtual int Count {
2113 get { return list.Count; }
2116 public virtual bool IsReadOnly {
2117 get { return false; }
2120 public virtual ListViewItem this [int displayIndex] {
2122 if (displayIndex < 0 || displayIndex >= list.Count)
2123 throw new ArgumentOutOfRangeException ("Index out of range.");
2124 return (ListViewItem) list [displayIndex];
2128 if (displayIndex < 0 || displayIndex >= list.Count)
2129 throw new ArgumentOutOfRangeException ("Index out of range.");
2131 if (list.Contains (value))
2132 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2134 value.Owner = owner;
2135 list [displayIndex] = value;
2137 owner.Redraw (true);
2141 bool ICollection.IsSynchronized {
2142 get { return true; }
2145 object ICollection.SyncRoot {
2146 get { return this; }
2149 bool IList.IsFixedSize {
2150 get { return list.IsFixedSize; }
2153 object IList.this [int index] {
2154 get { return this [index]; }
2156 if (value is ListViewItem)
2157 this [index] = (ListViewItem) value;
2159 this [index] = new ListViewItem (value.ToString ());
2162 #endregion // Public Properties
2164 #region Public Methods
2165 public virtual ListViewItem Add (ListViewItem value)
2167 if (list.Contains (value))
2168 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2170 value.Owner = owner;
2173 if (owner.Sorting != SortOrder.None)
2176 owner.Redraw (true);
2181 public virtual ListViewItem Add (string text)
2183 ListViewItem item = new ListViewItem (text);
2184 return this.Add (item);
2187 public virtual ListViewItem Add (string text, int imageIndex)
2189 ListViewItem item = new ListViewItem (text, imageIndex);
2190 return this.Add (item);
2193 public void AddRange (ListViewItem [] values)
2196 owner.SelectedItems.list.Clear ();
2197 owner.SelectedIndices.list.Clear ();
2198 owner.CheckedItems.list.Clear ();
2199 owner.CheckedIndices.list.Clear ();
2201 foreach (ListViewItem item in values) {
2206 if (owner.Sorting != SortOrder.None)
2209 owner.Redraw (true);
2212 public virtual void Clear ()
2214 owner.SetFocusedItem (null);
2215 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2217 owner.SelectedItems.list.Clear ();
2218 owner.SelectedIndices.list.Clear ();
2219 owner.CheckedItems.list.Clear ();
2220 owner.CheckedIndices.list.Clear ();
2221 owner.Redraw (true);
2224 public bool Contains (ListViewItem item)
2226 return list.Contains (item);
2229 public virtual void CopyTo (Array dest, int index)
2231 list.CopyTo (dest, index);
2234 public virtual IEnumerator GetEnumerator ()
2236 return list.GetEnumerator ();
2239 int IList.Add (object item)
2244 if (item is ListViewItem) {
2245 li = (ListViewItem) item;
2246 if (list.Contains (li))
2247 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2250 li = new ListViewItem (item.ToString ());
2253 result = list.Add (li);
2254 owner.Redraw (true);
2259 bool IList.Contains (object item)
2261 return list.Contains (item);
2264 int IList.IndexOf (object item)
2266 return list.IndexOf (item);
2269 void IList.Insert (int index, object item)
2271 if (item is ListViewItem)
2272 this.Insert (index, (ListViewItem) item);
2274 this.Insert (index, item.ToString ());
2277 void IList.Remove (object item)
2279 Remove ((ListViewItem) item);
2282 public int IndexOf (ListViewItem item)
2284 return list.IndexOf (item);
2287 public ListViewItem Insert (int index, ListViewItem item)
2289 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2290 // but it's really only greater.
2291 if (index < 0 || index > list.Count)
2292 throw new ArgumentOutOfRangeException ("Index out of range.");
2294 if (list.Contains (item))
2295 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2298 list.Insert (index, item);
2299 owner.Redraw (true);
2303 public ListViewItem Insert (int index, string text)
2305 return this.Insert (index, new ListViewItem (text));
2308 public ListViewItem Insert (int index, string text, int imageIndex)
2310 return this.Insert (index, new ListViewItem (text, imageIndex));
2313 public virtual void Remove (ListViewItem item)
2315 if (!list.Contains (item))
2318 owner.SelectedItems.list.Remove (item);
2319 owner.SelectedIndices.list.Remove (item.Index);
2320 owner.CheckedItems.list.Remove (item);
2321 owner.CheckedIndices.list.Remove (item.Index);
2323 owner.Redraw (true);
2326 public virtual void RemoveAt (int index)
2328 if (index < 0 || index >= list.Count)
2329 throw new ArgumentOutOfRangeException ("Index out of range.");
2331 list.RemoveAt (index);
2332 owner.SelectedItems.list.RemoveAt (index);
2333 owner.SelectedIndices.list.RemoveAt (index);
2334 owner.CheckedItems.list.RemoveAt (index);
2335 owner.CheckedIndices.list.RemoveAt (index);
2336 owner.Redraw (false);
2338 #endregion // Public Methods
2340 } // ListViewItemCollection
2342 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2344 internal ArrayList list;
2345 private ListView owner;
2347 #region Public Constructor
2348 public SelectedIndexCollection (ListView owner)
2350 list = new ArrayList ();
2353 #endregion // Public Constructor
2355 #region Public Properties
2357 public virtual int Count {
2358 get { return list.Count; }
2361 public virtual bool IsReadOnly {
2362 get { return true; }
2365 public int this [int index] {
2367 if (index < 0 || index >= list.Count)
2368 throw new ArgumentOutOfRangeException ("Index out of range.");
2369 return (int) list [index];
2373 bool ICollection.IsSynchronized {
2374 get { return list.IsSynchronized; }
2377 object ICollection.SyncRoot {
2378 get { return this; }
2381 bool IList.IsFixedSize {
2382 get { return true; }
2385 object IList.this [int index] {
2386 get { return this [index]; }
2387 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2389 #endregion // Public Properties
2391 #region Public Methods
2392 public bool Contains (int selectedIndex)
2394 return list.Contains (selectedIndex);
2397 public virtual void CopyTo (Array dest, int index)
2399 list.CopyTo (dest, index);
2402 public virtual IEnumerator GetEnumerator ()
2404 return list.GetEnumerator ();
2407 int IList.Add (object value)
2409 throw new NotSupportedException ("Add operation is not supported.");
2414 throw new NotSupportedException ("Clear operation is not supported.");
2417 bool IList.Contains (object selectedIndex)
2419 return list.Contains (selectedIndex);
2422 int IList.IndexOf (object selectedIndex)
2424 return list.IndexOf (selectedIndex);
2427 void IList.Insert (int index, object value)
2429 throw new NotSupportedException ("Insert operation is not supported.");
2432 void IList.Remove (object value)
2434 throw new NotSupportedException ("Remove operation is not supported.");
2437 void IList.RemoveAt (int index)
2439 throw new NotSupportedException ("RemoveAt operation is not supported.");
2442 public int IndexOf (int selectedIndex)
2444 return list.IndexOf (selectedIndex);
2446 #endregion // Public Methods
2448 } // SelectedIndexCollection
2450 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2452 internal ArrayList list;
2453 private ListView owner;
2455 #region Public Constructor
2456 public SelectedListViewItemCollection (ListView owner)
2458 list = new ArrayList ();
2461 #endregion // Public Constructor
2463 #region Public Properties
2465 public virtual int Count {
2466 get { return list.Count; }
2469 public virtual bool IsReadOnly {
2470 get { return true; }
2473 public ListViewItem this [int index] {
2475 if (index < 0 || index >= list.Count)
2476 throw new ArgumentOutOfRangeException ("Index out of range.");
2477 return (ListViewItem) list [index];
2481 bool ICollection.IsSynchronized {
2482 get { return list.IsSynchronized; }
2485 object ICollection.SyncRoot {
2486 get { return this; }
2489 bool IList.IsFixedSize {
2490 get { return true; }
2493 object IList.this [int index] {
2494 get { return this [index]; }
2495 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2497 #endregion // Public Properties
2499 #region Public Methods
2500 public virtual void Clear ()
2502 for (int i = 0; i < list.Count; i++)
2503 ((ListViewItem) list [i]).Selected = false;
2508 public bool Contains (ListViewItem item)
2510 return list.Contains (item);
2513 public virtual void CopyTo (Array dest, int index)
2515 list.CopyTo (dest, index);
2518 public virtual IEnumerator GetEnumerator ()
2520 return list.GetEnumerator ();
2523 int IList.Add (object value)
2525 throw new NotSupportedException ("Add operation is not supported.");
2528 bool IList.Contains (object item)
2530 return list.Contains (item);
2533 int IList.IndexOf (object item)
2535 return list.IndexOf (item);
2538 void IList.Insert (int index, object value)
2540 throw new NotSupportedException ("Insert operation is not supported.");
2543 void IList.Remove (object value)
2545 throw new NotSupportedException ("Remove operation is not supported.");
2548 void IList.RemoveAt (int index)
2550 throw new NotSupportedException ("RemoveAt operation is not supported.");
2553 public int IndexOf (ListViewItem item)
2555 return list.IndexOf (item);
2557 #endregion // Public Methods
2559 } // SelectedListViewItemCollection
2561 #endregion // Subclasses