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 start = FocusedItem == null ? 0 : FocusedItem.Index;
999 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1000 CompareOptions.IgnoreCase)) {
1001 SetFocusedItem (Items [i]);
1002 items [i].Selected = true;
1006 i = (i + 1 < Items.Count) ? i+1 : 0;
1014 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1016 if (ke.Handled || Items.Count == 0)
1022 switch (ke.KeyCode) {
1025 if (focused_item != null && focused_item.Index + 1 < Items.Count) {
1026 index = focused_item.Index + 1;
1031 index = Items.Count - 1;
1039 if (focused_item != null)
1040 index = focused_item.Index;
1050 if (focused_item != null)
1051 index = focused_item.Index + 1;
1055 if (index == items.Count)
1061 if (focused_item != null)
1062 index = focused_item.Index;
1075 if (KeySearchString (ke)) {
1084 items [index].Selected = true;
1085 SetFocusedItem (items [index]);
1086 EnsureVisible (index);
1091 internal class ItemControl : Control {
1094 ListViewItem clicked_item;
1095 ListViewItem last_clicked_item;
1097 public ItemControl (ListView owner)
1100 DoubleClick += new EventHandler(ItemsDoubleClick);
1101 KeyDown += new KeyEventHandler (ItemsKeyDown);
1102 KeyUp += new KeyEventHandler (ItemsKeyUp);
1103 MouseDown += new MouseEventHandler(ItemsMouseDown);
1104 MouseHover += new EventHandler(ItemsMouseHover);
1105 MouseUp += new MouseEventHandler(ItemsMouseUp);
1106 Paint += new PaintEventHandler (ItemsPaint);
1109 void ItemsDoubleClick (object sender, EventArgs e)
1111 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1112 owner.ItemActivate (this, e);
1115 void ItemsKeyDown (object sender, KeyEventArgs args)
1117 owner.OnKeyDown (args);
1120 void ItemsKeyUp (object sender, KeyEventArgs args)
1122 owner.OnKeyUp (args);
1125 private void ItemsMouseDown (object sender, MouseEventArgs me)
1127 if (owner.items.Count == 0)
1130 Point pt = new Point (me.X, me.Y);
1131 foreach (ListViewItem item in owner.items) {
1132 if (item.CheckRectReal.Contains (pt)) {
1133 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1134 item.Checked = !item.Checked;
1136 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1138 // Raise the ItemCheck event
1139 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1140 owner.OnItemCheck (ice);
1144 if (owner.View == View.Details && !owner.FullRowSelect) {
1145 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1146 clicked_item = item;
1150 if (item.Bounds.Contains (pt)) {
1151 clicked_item = item;
1157 owner.SetFocusedItem (clicked_item);
1159 if (clicked_item != null) {
1160 bool changed = !clicked_item.Selected;
1161 clicked_item.Selected = true;;
1164 owner.OnSelectedIndexChanged (EventArgs.Empty);
1166 // Raise double click if the item was clicked. On MS the
1167 // double click is only raised if you double click an item
1168 if (me.Clicks > 1 && clicked_item != null)
1169 owner.OnDoubleClick (EventArgs.Empty);
1170 else if (me.Clicks == 1 && clicked_item != null)
1171 owner.OnClick (EventArgs.Empty);
1172 } else if (owner.selected_indices.Count > 0) {
1173 // Raise the event if there was at least one item
1174 // selected and the user click on a dead area (unselecting all)
1175 owner.SelectedItems.Clear ();
1176 owner.SelectedIndices.list.Clear ();
1177 owner.OnSelectedIndexChanged (EventArgs.Empty);
1181 private void ItemsMouseHover (object sender, EventArgs e)
1183 if (Capture || !owner.hover_selection)
1186 Point pt = PointToClient (Control.MousePosition);
1187 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1192 item.Selected = true;
1193 owner.OnSelectedIndexChanged (new EventArgs ());
1196 private void ItemsMouseUp (object sender, MouseEventArgs me)
1199 if (owner.Items.Count == 0)
1202 Point pt = new Point (me.X, me.Y);
1204 Rectangle rect = Rectangle.Empty;
1205 if (clicked_item != null) {
1206 if (owner.view == View.Details && !owner.full_row_select)
1207 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1209 rect = clicked_item.Bounds;
1211 if (rect.Contains (pt)) {
1212 switch (owner.activation) {
1213 case ItemActivation.OneClick:
1214 owner.ItemActivate (this, EventArgs.Empty);
1217 case ItemActivation.TwoClick:
1218 if (last_clicked_item == clicked_item) {
1219 owner.ItemActivate (this, EventArgs.Empty);
1220 last_clicked_item = null;
1222 last_clicked_item = clicked_item;
1225 // DoubleClick activation is handled in another handler
1231 clicked_item = null;
1234 private void ItemsPaint (object sender, PaintEventArgs pe)
1236 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1240 private void ListView_Paint (object sender, PaintEventArgs pe)
1242 if (Width <= 0 || Height <= 0 || !Visible || updating)
1245 CalculateScrollBars ();
1248 private void ListView_SizeChanged (object sender, EventArgs e)
1250 CalculateListView (alignment);
1253 private void SetFocusedItem (ListViewItem item)
1255 if (focused_item != null)
1256 focused_item.Focused = false;
1259 item.Focused = true;
1261 focused_item = item;
1264 private void HorizontalScroller (object sender, EventArgs e)
1266 // Avoid unnecessary flickering, when button is
1267 // kept pressed at the end
1268 if (h_marker != h_scroll.Value) {
1270 int pixels = h_marker - h_scroll.Value;
1272 h_marker = h_scroll.Value;
1273 if (header_control.Visible)
1274 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1276 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1280 private void VerticalScroller (object sender, EventArgs e)
1282 // Avoid unnecessary flickering, when button is
1283 // kept pressed at the end
1284 if (v_marker != v_scroll.Value) {
1285 int pixels = v_marker - v_scroll.Value;
1286 Rectangle area = item_control.ClientRectangle;
1287 v_marker = v_scroll.Value;
1288 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1291 #endregion // Internal Methods Properties
1293 #region Protected Methods
1294 protected override void CreateHandle ()
1296 base.CreateHandle ();
1299 protected override void Dispose (bool disposing)
1302 h_scroll.Dispose ();
1303 v_scroll.Dispose ();
1305 large_image_list = null;
1306 small_image_list = null;
1307 state_image_list = null;
1310 base.Dispose (disposing);
1313 protected override bool IsInputKey (Keys keyData)
1330 return base.IsInputKey (keyData);
1333 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1335 if (AfterLabelEdit != null)
1336 AfterLabelEdit (this, e);
1339 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1341 if (BeforeLabelEdit != null)
1342 BeforeLabelEdit (this, e);
1345 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1347 if (ColumnClick != null)
1348 ColumnClick (this, e);
1351 protected override void OnEnabledChanged (EventArgs e)
1353 base.OnEnabledChanged (e);
1356 protected override void OnFontChanged (EventArgs e)
1358 base.OnFontChanged (e);
1362 protected override void OnHandleCreated (EventArgs e)
1364 base.OnHandleCreated (e);
1366 Controls.AddImplicit (header_control);
1367 Controls.AddImplicit (item_control);
1368 Controls.AddImplicit (this.v_scroll);
1369 Controls.AddImplicit (this.h_scroll);
1373 protected override void OnHandleDestroyed (EventArgs e)
1375 base.OnHandleDestroyed (e);
1378 protected virtual void OnItemActivate (EventArgs e)
1380 if (ItemActivate != null)
1381 ItemActivate (this, e);
1384 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1386 if (ItemCheck != null)
1387 ItemCheck (this, ice);
1390 protected virtual void OnItemDrag (ItemDragEventArgs e)
1392 if (ItemDrag != null)
1396 protected virtual void OnSelectedIndexChanged (EventArgs e)
1398 if (SelectedIndexChanged != null)
1399 SelectedIndexChanged (this, e);
1402 protected override void OnSystemColorsChanged (EventArgs e)
1404 base.OnSystemColorsChanged (e);
1407 protected void RealizeProperties ()
1412 protected void UpdateExtendedStyles ()
1417 protected override void WndProc (ref Message m)
1419 base.WndProc (ref m);
1421 #endregion // Protected Methods
1423 #region Public Instance Methods
1424 public void ArrangeIcons ()
1426 ArrangeIcons (this.alignment);
1429 public void ArrangeIcons (ListViewAlignment alignment)
1431 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1432 if (view == View.LargeIcon || view == View.SmallIcon) {
1433 this.CalculateListView (alignment);
1434 // we have done the calculations already
1435 this.Redraw (false);
1439 public void BeginUpdate ()
1441 // flag to avoid painting
1445 public void Clear ()
1448 items.Clear (); // Redraw (true) called here
1451 public void EndUpdate ()
1453 // flag to avoid painting
1456 // probably, now we need a redraw with recalculations
1460 public void EnsureVisible (int index)
1462 if (index < 0 || index >= items.Count || scrollable == false)
1465 Rectangle view_rect = item_control.ClientRectangle;
1466 Rectangle bounds = items [index].Bounds;
1468 if (view_rect.Contains (bounds))
1471 if (bounds.Left < 0)
1472 h_scroll.Value += bounds.Left;
1473 else if (bounds.Right > view_rect.Right)
1474 h_scroll.Value += (bounds.Right - view_rect.Right);
1477 v_scroll.Value += bounds.Top;
1478 else if (bounds.Bottom > view_rect.Bottom)
1479 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1482 public ListViewItem GetItemAt (int x, int y)
1484 foreach (ListViewItem item in items) {
1485 if (item.Bounds.Contains (x, y))
1491 public Rectangle GetItemRect (int index)
1493 return GetItemRect (index, ItemBoundsPortion.Entire);
1496 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1498 if (index < 0 || index >= items.Count)
1499 throw new IndexOutOfRangeException ("Invalid Index");
1501 return items [index].GetBounds (portion);
1506 if (sort_order != SortOrder.None)
1507 items.list.Sort (item_sorter);
1509 if (sort_order == SortOrder.Descending)
1510 items.list.Reverse ();
1515 public override string ToString ()
1517 int count = this.Items.Count;
1520 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1522 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1524 #endregion // Public Instance Methods
1529 class HeaderControl : Control {
1532 bool column_resize_active = false;
1533 ColumnHeader resize_column;
1534 ColumnHeader clicked_column;
1535 ColumnHeader drag_column;
1537 int drag_to_index = -1;
1539 public HeaderControl (ListView owner)
1542 MouseDown += new MouseEventHandler (HeaderMouseDown);
1543 MouseMove += new MouseEventHandler (HeaderMouseMove);
1544 MouseUp += new MouseEventHandler (HeaderMouseUp);
1545 Paint += new PaintEventHandler (HeaderPaint);
1548 private ColumnHeader ColumnAtX (int x)
1550 Point pt = new Point (x, 0);
1551 ColumnHeader result = null;
1552 foreach (ColumnHeader col in owner.Columns) {
1553 if (col.Rect.Contains (pt)) {
1561 private int GetReorderedIndex (ColumnHeader col)
1563 if (owner.reordered_column_indices == null)
1566 for (int i = 0; i < owner.Columns.Count; i++)
1567 if (owner.reordered_column_indices [i] == col.Index)
1569 throw new Exception ("Column index missing from reordered array");
1572 private void HeaderMouseDown (object sender, MouseEventArgs me)
1574 if (resize_column != null) {
1575 column_resize_active = true;
1580 clicked_column = ColumnAtX (me.X + owner.h_marker);
1582 if (clicked_column != null) {
1584 if (owner.AllowColumnReorder) {
1586 drag_column = (ColumnHeader) clicked_column.Clone ();
1587 drag_column.column_rect = clicked_column.Rect;
1588 drag_to_index = GetReorderedIndex (clicked_column);
1590 clicked_column.pressed = true;
1591 Rectangle bounds = clicked_column.Rect;
1592 bounds.X -= owner.h_marker;
1593 Invalidate (bounds);
1598 private void HeaderMouseMove (object sender, MouseEventArgs me)
1600 Point pt = new Point (me.X + owner.h_marker, me.Y);
1602 if (column_resize_active) {
1603 resize_column.Width = pt.X - resize_column.X;
1604 if (resize_column.Width < 0)
1605 resize_column.Width = 0;
1609 resize_column = null;
1611 if (clicked_column != null) {
1612 if (owner.AllowColumnReorder) {
1615 r = drag_column.column_rect;
1616 r.X = r.X + me.X - drag_x;
1617 drag_column.column_rect = r;
1619 int x = me.X + owner.h_marker;
1620 ColumnHeader over = ColumnAtX (x);
1621 if (x < over.X + over.Width / 2)
1622 drag_to_index = GetReorderedIndex (over);
1624 drag_to_index = GetReorderedIndex (over) + 1;
1627 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1628 bool pressed = clicked_column.pressed;
1629 clicked_column.pressed = over == clicked_column;
1630 if (clicked_column.pressed ^ pressed) {
1631 Rectangle bounds = clicked_column.Rect;
1632 bounds.X -= owner.h_marker;
1633 Invalidate (bounds);
1639 for (int i = 0; i < owner.Columns.Count; i++) {
1640 Rectangle zone = owner.Columns [i].Rect;
1641 zone.X = zone.Right - 5;
1643 if (zone.Contains (pt)) {
1644 resize_column = owner.Columns [i];
1649 if (resize_column == null)
1650 Cursor = Cursors.Default;
1652 Cursor = Cursors.VSplit;
1655 void HeaderMouseUp (object sender, MouseEventArgs me)
1659 if (column_resize_active) {
1660 column_resize_active = false;
1661 resize_column = null;
1662 Cursor = Cursors.Default;
1666 if (clicked_column != null && clicked_column.pressed) {
1667 clicked_column.pressed = false;
1668 Rectangle bounds = clicked_column.Rect;
1669 bounds.X -= owner.h_marker;
1670 Invalidate (bounds);
1671 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1674 if (drag_column != null && owner.AllowColumnReorder) {
1676 if (drag_to_index > GetReorderedIndex (clicked_column))
1678 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1679 owner.ReorderColumn (clicked_column, drag_to_index);
1684 clicked_column = null;
1687 void HeaderPaint (object sender, PaintEventArgs pe)
1689 if (Width <= 0 || Height <= 0 || !Visible || owner.updating)
1692 Theme theme = ThemeEngine.Current;
1693 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1695 if (drag_column == null)
1699 if (drag_to_index == owner.Columns.Count)
1700 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1702 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1703 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1708 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1710 internal ArrayList list;
1711 private ListView owner;
1713 #region Public Constructor
1714 public CheckedIndexCollection (ListView owner)
1716 list = new ArrayList ();
1719 #endregion // Public Constructor
1721 #region Public Properties
1723 public virtual int Count {
1724 get { return list.Count; }
1727 public virtual bool IsReadOnly {
1728 get { return true; }
1731 public int this [int index] {
1733 if (index < 0 || index >= list.Count)
1734 throw new ArgumentOutOfRangeException ("Index out of range.");
1735 return (int) list [index];
1739 bool ICollection.IsSynchronized {
1740 get { return false; }
1743 object ICollection.SyncRoot {
1744 get { return this; }
1747 bool IList.IsFixedSize {
1748 get { return true; }
1751 object IList.this [int index] {
1752 get { return this [index]; }
1753 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1755 #endregion // Public Properties
1757 #region Public Methods
1758 public bool Contains (int checkedIndex)
1760 return list.Contains (checkedIndex);
1763 public virtual IEnumerator GetEnumerator ()
1765 return list.GetEnumerator ();
1768 void ICollection.CopyTo (Array dest, int index)
1770 list.CopyTo (dest, index);
1773 int IList.Add (object value)
1775 throw new NotSupportedException ("Add operation is not supported.");
1780 throw new NotSupportedException ("Clear operation is not supported.");
1783 bool IList.Contains (object checkedIndex)
1785 return list.Contains (checkedIndex);
1788 int IList.IndexOf (object checkedIndex)
1790 return list.IndexOf (checkedIndex);
1793 void IList.Insert (int index, object value)
1795 throw new NotSupportedException ("Insert operation is not supported.");
1798 void IList.Remove (object value)
1800 throw new NotSupportedException ("Remove operation is not supported.");
1803 void IList.RemoveAt (int index)
1805 throw new NotSupportedException ("RemoveAt operation is not supported.");
1808 public int IndexOf (int checkedIndex)
1810 return list.IndexOf (checkedIndex);
1812 #endregion // Public Methods
1814 } // CheckedIndexCollection
1816 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1818 internal ArrayList list;
1819 private ListView owner;
1821 #region Public Constructor
1822 public CheckedListViewItemCollection (ListView owner)
1824 list = new ArrayList ();
1827 #endregion // Public Constructor
1829 #region Public Properties
1831 public virtual int Count {
1832 get { return list.Count; }
1835 public virtual bool IsReadOnly {
1836 get { return true; }
1839 public ListViewItem this [int index] {
1841 if (index < 0 || index >= list.Count)
1842 throw new ArgumentOutOfRangeException ("Index out of range.");
1843 return (ListViewItem) list [index];
1847 bool ICollection.IsSynchronized {
1848 get { return list.IsSynchronized; }
1851 object ICollection.SyncRoot {
1852 get { return this; }
1855 bool IList.IsFixedSize {
1856 get { return true; }
1859 object IList.this [int index] {
1860 get { return this [index]; }
1861 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1863 #endregion // Public Properties
1865 #region Public Methods
1866 public bool Contains (ListViewItem item)
1868 return list.Contains (item);
1871 public virtual void CopyTo (Array dest, int index)
1873 list.CopyTo (dest, index);
1876 public virtual IEnumerator GetEnumerator ()
1878 return list.GetEnumerator ();
1881 int IList.Add (object value)
1883 throw new NotSupportedException ("Add operation is not supported.");
1888 throw new NotSupportedException ("Clear operation is not supported.");
1891 bool IList.Contains (object item)
1893 return list.Contains (item);
1896 int IList.IndexOf (object item)
1898 return list.IndexOf (item);
1901 void IList.Insert (int index, object value)
1903 throw new NotSupportedException ("Insert operation is not supported.");
1906 void IList.Remove (object value)
1908 throw new NotSupportedException ("Remove operation is not supported.");
1911 void IList.RemoveAt (int index)
1913 throw new NotSupportedException ("RemoveAt operation is not supported.");
1916 public int IndexOf (ListViewItem item)
1918 return list.IndexOf (item);
1920 #endregion // Public Methods
1922 } // CheckedListViewItemCollection
1924 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1926 internal ArrayList list;
1927 private ListView owner;
1929 #region Public Constructor
1930 public ColumnHeaderCollection (ListView owner)
1932 list = new ArrayList ();
1935 #endregion // Public Constructor
1937 #region Public Properties
1939 public virtual int Count {
1940 get { return list.Count; }
1943 public virtual bool IsReadOnly {
1944 get { return false; }
1947 public virtual ColumnHeader this [int index] {
1949 if (index < 0 || index >= list.Count)
1950 throw new ArgumentOutOfRangeException ("Index out of range.");
1951 return (ColumnHeader) list [index];
1955 bool ICollection.IsSynchronized {
1956 get { return true; }
1959 object ICollection.SyncRoot {
1960 get { return this; }
1963 bool IList.IsFixedSize {
1964 get { return list.IsFixedSize; }
1967 object IList.this [int index] {
1968 get { return this [index]; }
1969 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1971 #endregion // Public Properties
1973 #region Public Methods
1974 public virtual int Add (ColumnHeader value)
1977 value.owner = this.owner;
1978 idx = list.Add (value);
1979 owner.Redraw (true);
1983 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
1985 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
1986 this.Add (colHeader);
1990 public virtual void AddRange (ColumnHeader [] values)
1992 foreach (ColumnHeader colHeader in values) {
1993 colHeader.owner = this.owner;
1997 owner.Redraw (true);
2000 public virtual void Clear ()
2003 owner.Redraw (true);
2006 public bool Contains (ColumnHeader value)
2008 return list.Contains (value);
2011 public virtual IEnumerator GetEnumerator ()
2013 return list.GetEnumerator ();
2016 void ICollection.CopyTo (Array dest, int index)
2018 list.CopyTo (dest, index);
2021 int IList.Add (object value)
2023 if (! (value is ColumnHeader)) {
2024 throw new ArgumentException ("Not of type ColumnHeader", "value");
2027 return this.Add ((ColumnHeader) value);
2030 bool IList.Contains (object value)
2032 if (! (value is ColumnHeader)) {
2033 throw new ArgumentException ("Not of type ColumnHeader", "value");
2036 return this.Contains ((ColumnHeader) value);
2039 int IList.IndexOf (object value)
2041 if (! (value is ColumnHeader)) {
2042 throw new ArgumentException ("Not of type ColumnHeader", "value");
2045 return this.IndexOf ((ColumnHeader) value);
2048 void IList.Insert (int index, object value)
2050 if (! (value is ColumnHeader)) {
2051 throw new ArgumentException ("Not of type ColumnHeader", "value");
2054 this.Insert (index, (ColumnHeader) value);
2057 void IList.Remove (object value)
2059 if (! (value is ColumnHeader)) {
2060 throw new ArgumentException ("Not of type ColumnHeader", "value");
2063 this.Remove ((ColumnHeader) value);
2066 public int IndexOf (ColumnHeader value)
2068 return list.IndexOf (value);
2071 public void Insert (int index, ColumnHeader value)
2073 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2074 // but it's really only greater.
2075 if (index < 0 || index > list.Count)
2076 throw new ArgumentOutOfRangeException ("Index out of range.");
2078 value.owner = this.owner;
2079 list.Insert (index, value);
2080 owner.Redraw (true);
2083 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2085 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2086 this.Insert (index, colHeader);
2089 public virtual void Remove (ColumnHeader column)
2091 // TODO: Update Column internal index ?
2092 list.Remove (column);
2093 owner.Redraw (true);
2096 public virtual void RemoveAt (int index)
2098 if (index < 0 || index >= list.Count)
2099 throw new ArgumentOutOfRangeException ("Index out of range.");
2101 // TODO: Update Column internal index ?
2102 list.RemoveAt (index);
2103 owner.Redraw (true);
2105 #endregion // Public Methods
2108 } // ColumnHeaderCollection
2110 public class ListViewItemCollection : IList, ICollection, IEnumerable
2112 internal ArrayList list;
2113 private ListView owner;
2115 #region Public Constructor
2116 public ListViewItemCollection (ListView owner)
2118 list = new ArrayList ();
2121 #endregion // Public Constructor
2123 #region Public Properties
2125 public virtual int Count {
2126 get { return list.Count; }
2129 public virtual bool IsReadOnly {
2130 get { return false; }
2133 public virtual ListViewItem this [int displayIndex] {
2135 if (displayIndex < 0 || displayIndex >= list.Count)
2136 throw new ArgumentOutOfRangeException ("Index out of range.");
2137 return (ListViewItem) list [displayIndex];
2141 if (displayIndex < 0 || displayIndex >= list.Count)
2142 throw new ArgumentOutOfRangeException ("Index out of range.");
2144 if (list.Contains (value))
2145 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2147 value.Owner = owner;
2148 list [displayIndex] = value;
2150 owner.Redraw (true);
2154 bool ICollection.IsSynchronized {
2155 get { return true; }
2158 object ICollection.SyncRoot {
2159 get { return this; }
2162 bool IList.IsFixedSize {
2163 get { return list.IsFixedSize; }
2166 object IList.this [int index] {
2167 get { return this [index]; }
2169 if (value is ListViewItem)
2170 this [index] = (ListViewItem) value;
2172 this [index] = new ListViewItem (value.ToString ());
2175 #endregion // Public Properties
2177 #region Public Methods
2178 public virtual ListViewItem Add (ListViewItem value)
2180 if (list.Contains (value))
2181 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2183 value.Owner = owner;
2186 if (owner.Sorting != SortOrder.None)
2189 owner.Redraw (true);
2194 public virtual ListViewItem Add (string text)
2196 ListViewItem item = new ListViewItem (text);
2197 return this.Add (item);
2200 public virtual ListViewItem Add (string text, int imageIndex)
2202 ListViewItem item = new ListViewItem (text, imageIndex);
2203 return this.Add (item);
2206 public void AddRange (ListViewItem [] values)
2209 owner.SelectedItems.list.Clear ();
2210 owner.SelectedIndices.list.Clear ();
2211 owner.CheckedItems.list.Clear ();
2212 owner.CheckedIndices.list.Clear ();
2214 foreach (ListViewItem item in values) {
2219 if (owner.Sorting != SortOrder.None)
2222 owner.Redraw (true);
2225 public virtual void Clear ()
2227 owner.SetFocusedItem (null);
2228 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2230 owner.SelectedItems.list.Clear ();
2231 owner.SelectedIndices.list.Clear ();
2232 owner.CheckedItems.list.Clear ();
2233 owner.CheckedIndices.list.Clear ();
2234 owner.Redraw (true);
2237 public bool Contains (ListViewItem item)
2239 return list.Contains (item);
2242 public virtual void CopyTo (Array dest, int index)
2244 list.CopyTo (dest, index);
2247 public virtual IEnumerator GetEnumerator ()
2249 return list.GetEnumerator ();
2252 int IList.Add (object item)
2257 if (item is ListViewItem) {
2258 li = (ListViewItem) item;
2259 if (list.Contains (li))
2260 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2263 li = new ListViewItem (item.ToString ());
2266 result = list.Add (li);
2267 owner.Redraw (true);
2272 bool IList.Contains (object item)
2274 return list.Contains (item);
2277 int IList.IndexOf (object item)
2279 return list.IndexOf (item);
2282 void IList.Insert (int index, object item)
2284 if (item is ListViewItem)
2285 this.Insert (index, (ListViewItem) item);
2287 this.Insert (index, item.ToString ());
2290 void IList.Remove (object item)
2292 Remove ((ListViewItem) item);
2295 public int IndexOf (ListViewItem item)
2297 return list.IndexOf (item);
2300 public ListViewItem Insert (int index, ListViewItem item)
2302 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2303 // but it's really only greater.
2304 if (index < 0 || index > list.Count)
2305 throw new ArgumentOutOfRangeException ("Index out of range.");
2307 if (list.Contains (item))
2308 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2311 list.Insert (index, item);
2312 owner.Redraw (true);
2316 public ListViewItem Insert (int index, string text)
2318 return this.Insert (index, new ListViewItem (text));
2321 public ListViewItem Insert (int index, string text, int imageIndex)
2323 return this.Insert (index, new ListViewItem (text, imageIndex));
2326 public virtual void Remove (ListViewItem item)
2328 if (!list.Contains (item))
2331 owner.SelectedItems.list.Remove (item);
2332 owner.SelectedIndices.list.Remove (item.Index);
2333 owner.CheckedItems.list.Remove (item);
2334 owner.CheckedIndices.list.Remove (item.Index);
2336 owner.Redraw (true);
2339 public virtual void RemoveAt (int index)
2341 if (index < 0 || index >= list.Count)
2342 throw new ArgumentOutOfRangeException ("Index out of range.");
2344 list.RemoveAt (index);
2345 owner.SelectedItems.list.RemoveAt (index);
2346 owner.SelectedIndices.list.RemoveAt (index);
2347 owner.CheckedItems.list.RemoveAt (index);
2348 owner.CheckedIndices.list.RemoveAt (index);
2349 owner.Redraw (false);
2351 #endregion // Public Methods
2353 } // ListViewItemCollection
2355 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2357 internal ArrayList list;
2358 private ListView owner;
2360 #region Public Constructor
2361 public SelectedIndexCollection (ListView owner)
2363 list = new ArrayList ();
2366 #endregion // Public Constructor
2368 #region Public Properties
2370 public virtual int Count {
2371 get { return list.Count; }
2374 public virtual bool IsReadOnly {
2375 get { return true; }
2378 public int this [int index] {
2380 if (index < 0 || index >= list.Count)
2381 throw new ArgumentOutOfRangeException ("Index out of range.");
2382 return (int) list [index];
2386 bool ICollection.IsSynchronized {
2387 get { return list.IsSynchronized; }
2390 object ICollection.SyncRoot {
2391 get { return this; }
2394 bool IList.IsFixedSize {
2395 get { return true; }
2398 object IList.this [int index] {
2399 get { return this [index]; }
2400 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2402 #endregion // Public Properties
2404 #region Public Methods
2405 public bool Contains (int selectedIndex)
2407 return list.Contains (selectedIndex);
2410 public virtual void CopyTo (Array dest, int index)
2412 list.CopyTo (dest, index);
2415 public virtual IEnumerator GetEnumerator ()
2417 return list.GetEnumerator ();
2420 int IList.Add (object value)
2422 throw new NotSupportedException ("Add operation is not supported.");
2427 throw new NotSupportedException ("Clear operation is not supported.");
2430 bool IList.Contains (object selectedIndex)
2432 return list.Contains (selectedIndex);
2435 int IList.IndexOf (object selectedIndex)
2437 return list.IndexOf (selectedIndex);
2440 void IList.Insert (int index, object value)
2442 throw new NotSupportedException ("Insert operation is not supported.");
2445 void IList.Remove (object value)
2447 throw new NotSupportedException ("Remove operation is not supported.");
2450 void IList.RemoveAt (int index)
2452 throw new NotSupportedException ("RemoveAt operation is not supported.");
2455 public int IndexOf (int selectedIndex)
2457 return list.IndexOf (selectedIndex);
2459 #endregion // Public Methods
2461 } // SelectedIndexCollection
2463 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2465 internal ArrayList list;
2466 private ListView owner;
2468 #region Public Constructor
2469 public SelectedListViewItemCollection (ListView owner)
2471 list = new ArrayList ();
2474 #endregion // Public Constructor
2476 #region Public Properties
2478 public virtual int Count {
2479 get { return list.Count; }
2482 public virtual bool IsReadOnly {
2483 get { return true; }
2486 public ListViewItem this [int index] {
2488 if (index < 0 || index >= list.Count)
2489 throw new ArgumentOutOfRangeException ("Index out of range.");
2490 return (ListViewItem) list [index];
2494 bool ICollection.IsSynchronized {
2495 get { return list.IsSynchronized; }
2498 object ICollection.SyncRoot {
2499 get { return this; }
2502 bool IList.IsFixedSize {
2503 get { return true; }
2506 object IList.this [int index] {
2507 get { return this [index]; }
2508 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2510 #endregion // Public Properties
2512 #region Public Methods
2513 public virtual void Clear ()
2515 for (int i = 0; i < list.Count; i++)
2516 ((ListViewItem) list [i]).Selected = false;
2521 public bool Contains (ListViewItem item)
2523 return list.Contains (item);
2526 public virtual void CopyTo (Array dest, int index)
2528 list.CopyTo (dest, index);
2531 public virtual IEnumerator GetEnumerator ()
2533 return list.GetEnumerator ();
2536 int IList.Add (object value)
2538 throw new NotSupportedException ("Add operation is not supported.");
2541 bool IList.Contains (object item)
2543 return list.Contains (item);
2546 int IList.IndexOf (object item)
2548 return list.IndexOf (item);
2551 void IList.Insert (int index, object value)
2553 throw new NotSupportedException ("Insert operation is not supported.");
2556 void IList.Remove (object value)
2558 throw new NotSupportedException ("Remove operation is not supported.");
2561 void IList.RemoveAt (int index)
2563 throw new NotSupportedException ("RemoveAt operation is not supported.");
2566 public int IndexOf (ListViewItem item)
2568 return list.IndexOf (item);
2570 #endregion // Public Methods
2572 } // SelectedListViewItemCollection
2574 #endregion // Subclasses