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 KeyDown += new KeyEventHandler (ItemsKeyDown);
1101 KeyUp += new KeyEventHandler (ItemsKeyUp);
1102 MouseDown += new MouseEventHandler(ItemsMouseDown);
1103 MouseHover += new EventHandler(ItemsMouseHover);
1104 MouseUp += new MouseEventHandler(ItemsMouseUp);
1105 Paint += new PaintEventHandler (ItemsPaint);
1108 void ItemsDoubleClick (object sender, EventArgs e)
1110 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1111 owner.ItemActivate (this, e);
1114 void ItemsKeyDown (object sender, KeyEventArgs args)
1116 owner.OnKeyDown (args);
1119 void ItemsKeyUp (object sender, KeyEventArgs args)
1121 owner.OnKeyUp (args);
1124 private void ItemsMouseDown (object sender, MouseEventArgs me)
1126 if (owner.items.Count == 0)
1129 Point pt = new Point (me.X, me.Y);
1130 foreach (ListViewItem item in owner.items) {
1131 if (item.CheckRectReal.Contains (pt)) {
1132 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1133 item.Checked = !item.Checked;
1135 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1137 // Raise the ItemCheck event
1138 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1139 owner.OnItemCheck (ice);
1143 if (owner.View == View.Details && !owner.FullRowSelect) {
1144 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1145 clicked_item = item;
1149 if (item.Bounds.Contains (pt)) {
1150 clicked_item = item;
1156 owner.SetFocusedItem (clicked_item);
1158 if (clicked_item != null) {
1159 bool changed = !clicked_item.Selected;
1160 clicked_item.Selected = true;;
1163 owner.OnSelectedIndexChanged (EventArgs.Empty);
1165 // Raise double click if the item was clicked. On MS the
1166 // double click is only raised if you double click an item
1167 if (me.Clicks > 1 && clicked_item != null)
1168 owner.OnDoubleClick (EventArgs.Empty);
1169 else if (me.Clicks == 1 && clicked_item != null)
1170 owner.OnClick (EventArgs.Empty);
1171 } else if (owner.selected_indices.Count > 0) {
1172 // Raise the event if there was at least one item
1173 // selected and the user click on a dead area (unselecting all)
1174 owner.SelectedItems.Clear ();
1175 owner.SelectedIndices.list.Clear ();
1176 owner.OnSelectedIndexChanged (EventArgs.Empty);
1180 private void ItemsMouseHover (object sender, EventArgs e)
1182 if (Capture || !owner.hover_selection)
1185 Point pt = PointToClient (Control.MousePosition);
1186 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1191 item.Selected = true;
1192 owner.OnSelectedIndexChanged (new EventArgs ());
1195 private void ItemsMouseUp (object sender, MouseEventArgs me)
1198 if (owner.Items.Count == 0)
1201 Point pt = new Point (me.X, me.Y);
1203 Rectangle rect = Rectangle.Empty;
1204 if (clicked_item != null) {
1205 if (owner.view == View.Details && !owner.full_row_select)
1206 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1208 rect = clicked_item.Bounds;
1210 if (rect.Contains (pt)) {
1211 switch (owner.activation) {
1212 case ItemActivation.OneClick:
1213 owner.ItemActivate (this, EventArgs.Empty);
1216 case ItemActivation.TwoClick:
1217 if (last_clicked_item == clicked_item) {
1218 owner.ItemActivate (this, EventArgs.Empty);
1219 last_clicked_item = null;
1221 last_clicked_item = clicked_item;
1224 // DoubleClick activation is handled in another handler
1230 clicked_item = null;
1233 private void ItemsPaint (object sender, PaintEventArgs pe)
1235 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1239 private void ListView_Paint (object sender, PaintEventArgs pe)
1241 if (Width <= 0 || Height <= 0 || !Visible || updating)
1244 CalculateScrollBars ();
1247 private void ListView_SizeChanged (object sender, EventArgs e)
1249 CalculateListView (alignment);
1252 private void SetFocusedItem (ListViewItem item)
1254 if (focused_item != null)
1255 focused_item.Focused = false;
1258 item.Focused = true;
1260 focused_item = item;
1263 private void HorizontalScroller (object sender, EventArgs e)
1265 // Avoid unnecessary flickering, when button is
1266 // kept pressed at the end
1267 if (h_marker != h_scroll.Value) {
1269 int pixels = h_marker - h_scroll.Value;
1271 h_marker = h_scroll.Value;
1272 if (header_control.Visible)
1273 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1275 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1279 private void VerticalScroller (object sender, EventArgs e)
1281 // Avoid unnecessary flickering, when button is
1282 // kept pressed at the end
1283 if (v_marker != v_scroll.Value) {
1284 int pixels = v_marker - v_scroll.Value;
1285 Rectangle area = item_control.ClientRectangle;
1286 v_marker = v_scroll.Value;
1287 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1290 #endregion // Internal Methods Properties
1292 #region Protected Methods
1293 protected override void CreateHandle ()
1295 base.CreateHandle ();
1298 protected override void Dispose (bool disposing)
1301 h_scroll.Dispose ();
1302 v_scroll.Dispose ();
1304 large_image_list = null;
1305 small_image_list = null;
1306 state_image_list = null;
1309 base.Dispose (disposing);
1312 protected override bool IsInputKey (Keys keyData)
1329 return base.IsInputKey (keyData);
1332 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1334 if (AfterLabelEdit != null)
1335 AfterLabelEdit (this, e);
1338 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1340 if (BeforeLabelEdit != null)
1341 BeforeLabelEdit (this, e);
1344 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1346 if (ColumnClick != null)
1347 ColumnClick (this, e);
1350 protected override void OnEnabledChanged (EventArgs e)
1352 base.OnEnabledChanged (e);
1355 protected override void OnFontChanged (EventArgs e)
1357 base.OnFontChanged (e);
1361 protected override void OnHandleCreated (EventArgs e)
1363 base.OnHandleCreated (e);
1365 Controls.AddImplicit (header_control);
1366 Controls.AddImplicit (item_control);
1367 Controls.AddImplicit (this.v_scroll);
1368 Controls.AddImplicit (this.h_scroll);
1372 protected override void OnHandleDestroyed (EventArgs e)
1374 base.OnHandleDestroyed (e);
1377 protected virtual void OnItemActivate (EventArgs e)
1379 if (ItemActivate != null)
1380 ItemActivate (this, e);
1383 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1385 if (ItemCheck != null)
1386 ItemCheck (this, ice);
1389 protected virtual void OnItemDrag (ItemDragEventArgs e)
1391 if (ItemDrag != null)
1395 protected virtual void OnSelectedIndexChanged (EventArgs e)
1397 if (SelectedIndexChanged != null)
1398 SelectedIndexChanged (this, e);
1401 protected override void OnSystemColorsChanged (EventArgs e)
1403 base.OnSystemColorsChanged (e);
1406 protected void RealizeProperties ()
1411 protected void UpdateExtendedStyles ()
1416 protected override void WndProc (ref Message m)
1418 base.WndProc (ref m);
1420 #endregion // Protected Methods
1422 #region Public Instance Methods
1423 public void ArrangeIcons ()
1425 ArrangeIcons (this.alignment);
1428 public void ArrangeIcons (ListViewAlignment alignment)
1430 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1431 if (view == View.LargeIcon || view == View.SmallIcon) {
1432 this.CalculateListView (alignment);
1433 // we have done the calculations already
1434 this.Redraw (false);
1438 public void BeginUpdate ()
1440 // flag to avoid painting
1444 public void Clear ()
1447 items.Clear (); // Redraw (true) called here
1450 public void EndUpdate ()
1452 // flag to avoid painting
1455 // probably, now we need a redraw with recalculations
1459 public void EnsureVisible (int index)
1461 if (index < 0 || index >= items.Count || scrollable == false)
1464 Rectangle view_rect = item_control.ClientRectangle;
1465 Rectangle bounds = items [index].Bounds;
1467 if (view_rect.Contains (bounds))
1470 if (bounds.Left < 0)
1471 h_scroll.Value += bounds.Left;
1472 else if (bounds.Right > view_rect.Right)
1473 h_scroll.Value += (bounds.Right - view_rect.Right);
1476 v_scroll.Value += bounds.Top;
1477 else if (bounds.Bottom > view_rect.Bottom)
1478 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1481 public ListViewItem GetItemAt (int x, int y)
1483 foreach (ListViewItem item in items) {
1484 if (item.Bounds.Contains (x, y))
1490 public Rectangle GetItemRect (int index)
1492 return GetItemRect (index, ItemBoundsPortion.Entire);
1495 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1497 if (index < 0 || index >= items.Count)
1498 throw new IndexOutOfRangeException ("Invalid Index");
1500 return items [index].GetBounds (portion);
1505 if (sort_order != SortOrder.None)
1506 items.list.Sort (item_sorter);
1508 if (sort_order == SortOrder.Descending)
1509 items.list.Reverse ();
1514 public override string ToString ()
1516 int count = this.Items.Count;
1519 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1521 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1523 #endregion // Public Instance Methods
1528 class HeaderControl : Control {
1531 bool column_resize_active = false;
1532 ColumnHeader resize_column;
1533 ColumnHeader clicked_column;
1534 ColumnHeader drag_column;
1536 int drag_to_index = -1;
1538 public HeaderControl (ListView owner)
1541 MouseDown += new MouseEventHandler (HeaderMouseDown);
1542 MouseMove += new MouseEventHandler (HeaderMouseMove);
1543 MouseUp += new MouseEventHandler (HeaderMouseUp);
1544 Paint += new PaintEventHandler (HeaderPaint);
1547 private ColumnHeader ColumnAtX (int x)
1549 Point pt = new Point (x, 0);
1550 ColumnHeader result = null;
1551 foreach (ColumnHeader col in owner.Columns) {
1552 if (col.Rect.Contains (pt)) {
1560 private int GetReorderedIndex (ColumnHeader col)
1562 if (owner.reordered_column_indices == null)
1565 for (int i = 0; i < owner.Columns.Count; i++)
1566 if (owner.reordered_column_indices [i] == col.Index)
1568 throw new Exception ("Column index missing from reordered array");
1571 private void HeaderMouseDown (object sender, MouseEventArgs me)
1573 if (resize_column != null) {
1574 column_resize_active = true;
1579 clicked_column = ColumnAtX (me.X + owner.h_marker);
1581 if (clicked_column != null) {
1583 if (owner.AllowColumnReorder) {
1585 drag_column = (ColumnHeader) clicked_column.Clone ();
1586 drag_column.column_rect = clicked_column.Rect;
1587 drag_to_index = GetReorderedIndex (clicked_column);
1589 clicked_column.pressed = true;
1590 Rectangle bounds = clicked_column.Rect;
1591 bounds.X -= owner.h_marker;
1592 Invalidate (bounds);
1597 private void HeaderMouseMove (object sender, MouseEventArgs me)
1599 Point pt = new Point (me.X + owner.h_marker, me.Y);
1601 if (column_resize_active) {
1602 resize_column.Width = pt.X - resize_column.X;
1603 if (resize_column.Width < 0)
1604 resize_column.Width = 0;
1608 resize_column = null;
1610 if (clicked_column != null) {
1611 if (owner.AllowColumnReorder) {
1614 r = drag_column.column_rect;
1615 r.X = r.X + me.X - drag_x;
1616 drag_column.column_rect = r;
1618 int x = me.X + owner.h_marker;
1619 ColumnHeader over = ColumnAtX (x);
1620 if (x < over.X + over.Width / 2)
1621 drag_to_index = GetReorderedIndex (over);
1623 drag_to_index = GetReorderedIndex (over) + 1;
1626 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1627 bool pressed = clicked_column.pressed;
1628 clicked_column.pressed = over == clicked_column;
1629 if (clicked_column.pressed ^ pressed) {
1630 Rectangle bounds = clicked_column.Rect;
1631 bounds.X -= owner.h_marker;
1632 Invalidate (bounds);
1638 for (int i = 0; i < owner.Columns.Count; i++) {
1639 Rectangle zone = owner.Columns [i].Rect;
1640 zone.X = zone.Right - 5;
1642 if (zone.Contains (pt)) {
1643 resize_column = owner.Columns [i];
1648 if (resize_column == null)
1649 Cursor = Cursors.Default;
1651 Cursor = Cursors.VSplit;
1654 void HeaderMouseUp (object sender, MouseEventArgs me)
1658 if (column_resize_active) {
1659 column_resize_active = false;
1660 resize_column = null;
1661 Cursor = Cursors.Default;
1665 if (clicked_column != null && clicked_column.pressed) {
1666 clicked_column.pressed = false;
1667 Rectangle bounds = clicked_column.Rect;
1668 bounds.X -= owner.h_marker;
1669 Invalidate (bounds);
1670 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1673 if (drag_column != null && owner.AllowColumnReorder) {
1675 if (drag_to_index > GetReorderedIndex (clicked_column))
1677 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1678 owner.ReorderColumn (clicked_column, drag_to_index);
1683 clicked_column = null;
1686 void HeaderPaint (object sender, PaintEventArgs pe)
1688 if (Width <= 0 || Height <= 0 || !Visible || owner.updating)
1691 Theme theme = ThemeEngine.Current;
1692 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1694 if (drag_column == null)
1698 if (drag_to_index == owner.Columns.Count)
1699 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1701 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1702 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1707 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1709 internal ArrayList list;
1710 private ListView owner;
1712 #region Public Constructor
1713 public CheckedIndexCollection (ListView owner)
1715 list = new ArrayList ();
1718 #endregion // Public Constructor
1720 #region Public Properties
1722 public virtual int Count {
1723 get { return list.Count; }
1726 public virtual bool IsReadOnly {
1727 get { return true; }
1730 public int this [int index] {
1732 if (index < 0 || index >= list.Count)
1733 throw new ArgumentOutOfRangeException ("Index out of range.");
1734 return (int) list [index];
1738 bool ICollection.IsSynchronized {
1739 get { return false; }
1742 object ICollection.SyncRoot {
1743 get { return this; }
1746 bool IList.IsFixedSize {
1747 get { return true; }
1750 object IList.this [int index] {
1751 get { return this [index]; }
1752 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1754 #endregion // Public Properties
1756 #region Public Methods
1757 public bool Contains (int checkedIndex)
1759 return list.Contains (checkedIndex);
1762 public virtual IEnumerator GetEnumerator ()
1764 return list.GetEnumerator ();
1767 void ICollection.CopyTo (Array dest, int index)
1769 list.CopyTo (dest, index);
1772 int IList.Add (object value)
1774 throw new NotSupportedException ("Add operation is not supported.");
1779 throw new NotSupportedException ("Clear operation is not supported.");
1782 bool IList.Contains (object checkedIndex)
1784 return list.Contains (checkedIndex);
1787 int IList.IndexOf (object checkedIndex)
1789 return list.IndexOf (checkedIndex);
1792 void IList.Insert (int index, object value)
1794 throw new NotSupportedException ("Insert operation is not supported.");
1797 void IList.Remove (object value)
1799 throw new NotSupportedException ("Remove operation is not supported.");
1802 void IList.RemoveAt (int index)
1804 throw new NotSupportedException ("RemoveAt operation is not supported.");
1807 public int IndexOf (int checkedIndex)
1809 return list.IndexOf (checkedIndex);
1811 #endregion // Public Methods
1813 } // CheckedIndexCollection
1815 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1817 internal ArrayList list;
1818 private ListView owner;
1820 #region Public Constructor
1821 public CheckedListViewItemCollection (ListView owner)
1823 list = new ArrayList ();
1826 #endregion // Public Constructor
1828 #region Public Properties
1830 public virtual int Count {
1831 get { return list.Count; }
1834 public virtual bool IsReadOnly {
1835 get { return true; }
1838 public ListViewItem this [int index] {
1840 if (index < 0 || index >= list.Count)
1841 throw new ArgumentOutOfRangeException ("Index out of range.");
1842 return (ListViewItem) list [index];
1846 bool ICollection.IsSynchronized {
1847 get { return list.IsSynchronized; }
1850 object ICollection.SyncRoot {
1851 get { return this; }
1854 bool IList.IsFixedSize {
1855 get { return true; }
1858 object IList.this [int index] {
1859 get { return this [index]; }
1860 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1862 #endregion // Public Properties
1864 #region Public Methods
1865 public bool Contains (ListViewItem item)
1867 return list.Contains (item);
1870 public virtual void CopyTo (Array dest, int index)
1872 list.CopyTo (dest, index);
1875 public virtual IEnumerator GetEnumerator ()
1877 return list.GetEnumerator ();
1880 int IList.Add (object value)
1882 throw new NotSupportedException ("Add operation is not supported.");
1887 throw new NotSupportedException ("Clear operation is not supported.");
1890 bool IList.Contains (object item)
1892 return list.Contains (item);
1895 int IList.IndexOf (object item)
1897 return list.IndexOf (item);
1900 void IList.Insert (int index, object value)
1902 throw new NotSupportedException ("Insert operation is not supported.");
1905 void IList.Remove (object value)
1907 throw new NotSupportedException ("Remove operation is not supported.");
1910 void IList.RemoveAt (int index)
1912 throw new NotSupportedException ("RemoveAt operation is not supported.");
1915 public int IndexOf (ListViewItem item)
1917 return list.IndexOf (item);
1919 #endregion // Public Methods
1921 } // CheckedListViewItemCollection
1923 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1925 internal ArrayList list;
1926 private ListView owner;
1928 #region Public Constructor
1929 public ColumnHeaderCollection (ListView owner)
1931 list = new ArrayList ();
1934 #endregion // Public Constructor
1936 #region Public Properties
1938 public virtual int Count {
1939 get { return list.Count; }
1942 public virtual bool IsReadOnly {
1943 get { return false; }
1946 public virtual ColumnHeader this [int index] {
1948 if (index < 0 || index >= list.Count)
1949 throw new ArgumentOutOfRangeException ("Index out of range.");
1950 return (ColumnHeader) list [index];
1954 bool ICollection.IsSynchronized {
1955 get { return true; }
1958 object ICollection.SyncRoot {
1959 get { return this; }
1962 bool IList.IsFixedSize {
1963 get { return list.IsFixedSize; }
1966 object IList.this [int index] {
1967 get { return this [index]; }
1968 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1970 #endregion // Public Properties
1972 #region Public Methods
1973 public virtual int Add (ColumnHeader value)
1976 value.owner = this.owner;
1977 idx = list.Add (value);
1978 owner.Redraw (true);
1982 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1984 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1985 this.Add (colHeader);
1989 public virtual void AddRange (ColumnHeader [] values)
1991 foreach (ColumnHeader colHeader in values) {
1992 colHeader.owner = this.owner;
1996 owner.Redraw (true);
1999 public virtual void Clear ()
2002 owner.Redraw (true);
2005 public bool Contains (ColumnHeader value)
2007 return list.Contains (value);
2010 public virtual IEnumerator GetEnumerator ()
2012 return list.GetEnumerator ();
2015 void ICollection.CopyTo (Array dest, int index)
2017 list.CopyTo (dest, index);
2020 int IList.Add (object value)
2022 if (! (value is ColumnHeader)) {
2023 throw new ArgumentException ("Not of type ColumnHeader", "value");
2026 return this.Add ((ColumnHeader) value);
2029 bool IList.Contains (object value)
2031 if (! (value is ColumnHeader)) {
2032 throw new ArgumentException ("Not of type ColumnHeader", "value");
2035 return this.Contains ((ColumnHeader) value);
2038 int IList.IndexOf (object value)
2040 if (! (value is ColumnHeader)) {
2041 throw new ArgumentException ("Not of type ColumnHeader", "value");
2044 return this.IndexOf ((ColumnHeader) value);
2047 void IList.Insert (int index, object value)
2049 if (! (value is ColumnHeader)) {
2050 throw new ArgumentException ("Not of type ColumnHeader", "value");
2053 this.Insert (index, (ColumnHeader) value);
2056 void IList.Remove (object value)
2058 if (! (value is ColumnHeader)) {
2059 throw new ArgumentException ("Not of type ColumnHeader", "value");
2062 this.Remove ((ColumnHeader) value);
2065 public int IndexOf (ColumnHeader value)
2067 return list.IndexOf (value);
2070 public void Insert (int index, ColumnHeader value)
2072 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2073 // but it's really only greater.
2074 if (index < 0 || index > list.Count)
2075 throw new ArgumentOutOfRangeException ("Index out of range.");
2077 value.owner = this.owner;
2078 list.Insert (index, value);
2079 owner.Redraw (true);
2082 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2084 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2085 this.Insert (index, colHeader);
2088 public virtual void Remove (ColumnHeader column)
2090 // TODO: Update Column internal index ?
2091 list.Remove (column);
2092 owner.Redraw (true);
2095 public virtual void RemoveAt (int index)
2097 if (index < 0 || index >= list.Count)
2098 throw new ArgumentOutOfRangeException ("Index out of range.");
2100 // TODO: Update Column internal index ?
2101 list.RemoveAt (index);
2102 owner.Redraw (true);
2104 #endregion // Public Methods
2107 } // ColumnHeaderCollection
2109 public class ListViewItemCollection : IList, ICollection, IEnumerable
2111 internal ArrayList list;
2112 private ListView owner;
2114 #region Public Constructor
2115 public ListViewItemCollection (ListView owner)
2117 list = new ArrayList ();
2120 #endregion // Public Constructor
2122 #region Public Properties
2124 public virtual int Count {
2125 get { return list.Count; }
2128 public virtual bool IsReadOnly {
2129 get { return false; }
2132 public virtual ListViewItem this [int displayIndex] {
2134 if (displayIndex < 0 || displayIndex >= list.Count)
2135 throw new ArgumentOutOfRangeException ("Index out of range.");
2136 return (ListViewItem) list [displayIndex];
2140 if (displayIndex < 0 || displayIndex >= list.Count)
2141 throw new ArgumentOutOfRangeException ("Index out of range.");
2143 if (list.Contains (value))
2144 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2146 value.Owner = owner;
2147 list [displayIndex] = value;
2149 owner.Redraw (true);
2153 bool ICollection.IsSynchronized {
2154 get { return true; }
2157 object ICollection.SyncRoot {
2158 get { return this; }
2161 bool IList.IsFixedSize {
2162 get { return list.IsFixedSize; }
2165 object IList.this [int index] {
2166 get { return this [index]; }
2168 if (value is ListViewItem)
2169 this [index] = (ListViewItem) value;
2171 this [index] = new ListViewItem (value.ToString ());
2174 #endregion // Public Properties
2176 #region Public Methods
2177 public virtual ListViewItem Add (ListViewItem value)
2179 if (list.Contains (value))
2180 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2182 value.Owner = owner;
2185 if (owner.Sorting != SortOrder.None)
2188 owner.Redraw (true);
2193 public virtual ListViewItem Add (string text)
2195 ListViewItem item = new ListViewItem (text);
2196 return this.Add (item);
2199 public virtual ListViewItem Add (string text, int imageIndex)
2201 ListViewItem item = new ListViewItem (text, imageIndex);
2202 return this.Add (item);
2205 public void AddRange (ListViewItem [] values)
2208 owner.SelectedItems.list.Clear ();
2209 owner.SelectedIndices.list.Clear ();
2210 owner.CheckedItems.list.Clear ();
2211 owner.CheckedIndices.list.Clear ();
2213 foreach (ListViewItem item in values) {
2218 if (owner.Sorting != SortOrder.None)
2221 owner.Redraw (true);
2224 public virtual void Clear ()
2226 owner.SetFocusedItem (null);
2227 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2229 owner.SelectedItems.list.Clear ();
2230 owner.SelectedIndices.list.Clear ();
2231 owner.CheckedItems.list.Clear ();
2232 owner.CheckedIndices.list.Clear ();
2233 owner.Redraw (true);
2236 public bool Contains (ListViewItem item)
2238 return list.Contains (item);
2241 public virtual void CopyTo (Array dest, int index)
2243 list.CopyTo (dest, index);
2246 public virtual IEnumerator GetEnumerator ()
2248 return list.GetEnumerator ();
2251 int IList.Add (object item)
2256 if (item is ListViewItem) {
2257 li = (ListViewItem) item;
2258 if (list.Contains (li))
2259 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2262 li = new ListViewItem (item.ToString ());
2265 result = list.Add (li);
2266 owner.Redraw (true);
2271 bool IList.Contains (object item)
2273 return list.Contains (item);
2276 int IList.IndexOf (object item)
2278 return list.IndexOf (item);
2281 void IList.Insert (int index, object item)
2283 if (item is ListViewItem)
2284 this.Insert (index, (ListViewItem) item);
2286 this.Insert (index, item.ToString ());
2289 void IList.Remove (object item)
2291 Remove ((ListViewItem) item);
2294 public int IndexOf (ListViewItem item)
2296 return list.IndexOf (item);
2299 public ListViewItem Insert (int index, ListViewItem item)
2301 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2302 // but it's really only greater.
2303 if (index < 0 || index > list.Count)
2304 throw new ArgumentOutOfRangeException ("Index out of range.");
2306 if (list.Contains (item))
2307 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2310 list.Insert (index, item);
2311 owner.Redraw (true);
2315 public ListViewItem Insert (int index, string text)
2317 return this.Insert (index, new ListViewItem (text));
2320 public ListViewItem Insert (int index, string text, int imageIndex)
2322 return this.Insert (index, new ListViewItem (text, imageIndex));
2325 public virtual void Remove (ListViewItem item)
2327 if (!list.Contains (item))
2330 owner.SelectedItems.list.Remove (item);
2331 owner.SelectedIndices.list.Remove (item.Index);
2332 owner.CheckedItems.list.Remove (item);
2333 owner.CheckedIndices.list.Remove (item.Index);
2335 owner.Redraw (true);
2338 public virtual void RemoveAt (int index)
2340 if (index < 0 || index >= list.Count)
2341 throw new ArgumentOutOfRangeException ("Index out of range.");
2343 list.RemoveAt (index);
2344 owner.SelectedItems.list.RemoveAt (index);
2345 owner.SelectedIndices.list.RemoveAt (index);
2346 owner.CheckedItems.list.RemoveAt (index);
2347 owner.CheckedIndices.list.RemoveAt (index);
2348 owner.Redraw (false);
2350 #endregion // Public Methods
2352 } // ListViewItemCollection
2354 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2356 internal ArrayList list;
2357 private ListView owner;
2359 #region Public Constructor
2360 public SelectedIndexCollection (ListView owner)
2362 list = new ArrayList ();
2365 #endregion // Public Constructor
2367 #region Public Properties
2369 public virtual int Count {
2370 get { return list.Count; }
2373 public virtual bool IsReadOnly {
2374 get { return true; }
2377 public int this [int index] {
2379 if (index < 0 || index >= list.Count)
2380 throw new ArgumentOutOfRangeException ("Index out of range.");
2381 return (int) list [index];
2385 bool ICollection.IsSynchronized {
2386 get { return list.IsSynchronized; }
2389 object ICollection.SyncRoot {
2390 get { return this; }
2393 bool IList.IsFixedSize {
2394 get { return true; }
2397 object IList.this [int index] {
2398 get { return this [index]; }
2399 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2401 #endregion // Public Properties
2403 #region Public Methods
2404 public bool Contains (int selectedIndex)
2406 return list.Contains (selectedIndex);
2409 public virtual void CopyTo (Array dest, int index)
2411 list.CopyTo (dest, index);
2414 public virtual IEnumerator GetEnumerator ()
2416 return list.GetEnumerator ();
2419 int IList.Add (object value)
2421 throw new NotSupportedException ("Add operation is not supported.");
2426 throw new NotSupportedException ("Clear operation is not supported.");
2429 bool IList.Contains (object selectedIndex)
2431 return list.Contains (selectedIndex);
2434 int IList.IndexOf (object selectedIndex)
2436 return list.IndexOf (selectedIndex);
2439 void IList.Insert (int index, object value)
2441 throw new NotSupportedException ("Insert operation is not supported.");
2444 void IList.Remove (object value)
2446 throw new NotSupportedException ("Remove operation is not supported.");
2449 void IList.RemoveAt (int index)
2451 throw new NotSupportedException ("RemoveAt operation is not supported.");
2454 public int IndexOf (int selectedIndex)
2456 return list.IndexOf (selectedIndex);
2458 #endregion // Public Methods
2460 } // SelectedIndexCollection
2462 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2464 internal ArrayList list;
2465 private ListView owner;
2467 #region Public Constructor
2468 public SelectedListViewItemCollection (ListView owner)
2470 list = new ArrayList ();
2473 #endregion // Public Constructor
2475 #region Public Properties
2477 public virtual int Count {
2478 get { return list.Count; }
2481 public virtual bool IsReadOnly {
2482 get { return true; }
2485 public ListViewItem this [int index] {
2487 if (index < 0 || index >= list.Count)
2488 throw new ArgumentOutOfRangeException ("Index out of range.");
2489 return (ListViewItem) list [index];
2493 bool ICollection.IsSynchronized {
2494 get { return list.IsSynchronized; }
2497 object ICollection.SyncRoot {
2498 get { return this; }
2501 bool IList.IsFixedSize {
2502 get { return true; }
2505 object IList.this [int index] {
2506 get { return this [index]; }
2507 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2509 #endregion // Public Properties
2511 #region Public Methods
2512 public virtual void Clear ()
2514 for (int i = 0; i < list.Count; i++)
2515 ((ListViewItem) list [i]).Selected = false;
2520 public bool Contains (ListViewItem item)
2522 return list.Contains (item);
2525 public virtual void CopyTo (Array dest, int index)
2527 list.CopyTo (dest, index);
2530 public virtual IEnumerator GetEnumerator ()
2532 return list.GetEnumerator ();
2535 int IList.Add (object value)
2537 throw new NotSupportedException ("Add operation is not supported.");
2540 bool IList.Contains (object item)
2542 return list.Contains (item);
2545 int IList.IndexOf (object item)
2547 return list.IndexOf (item);
2550 void IList.Insert (int index, object value)
2552 throw new NotSupportedException ("Insert operation is not supported.");
2555 void IList.Remove (object value)
2557 throw new NotSupportedException ("Remove operation is not supported.");
2560 void IList.RemoveAt (int index)
2562 throw new NotSupportedException ("RemoveAt operation is not supported.");
2565 public int IndexOf (ListViewItem item)
2567 return list.IndexOf (item);
2569 #endregion // Public Methods
2571 } // SelectedListViewItemCollection
2573 #endregion // Subclasses