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)
26 // Daniel Nauck (dna(at)mono-project(dot)de)
35 using System.Collections;
36 using System.ComponentModel;
37 using System.ComponentModel.Design;
39 using System.Runtime.InteropServices;
40 using System.Globalization;
42 using System.Collections.Generic;
45 namespace System.Windows.Forms
47 [DefaultEvent ("SelectedIndexChanged")]
48 [DefaultProperty ("Items")]
49 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
51 [ClassInterface (ClassInterfaceType.AutoDispatch)]
53 [Docking (DockingBehavior.Ask)]
55 public class ListView : Control
57 private ItemActivation activation = ItemActivation.Standard;
58 private ListViewAlignment alignment = ListViewAlignment.Top;
59 private bool allow_column_reorder;
60 private bool auto_arrange = true;
61 private bool check_boxes;
62 private readonly CheckedIndexCollection checked_indices;
63 private readonly CheckedListViewItemCollection checked_items;
64 private readonly ColumnHeaderCollection columns;
65 internal int focused_item_index = -1;
66 private bool full_row_select;
67 private bool grid_lines;
68 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
69 private bool hide_selection = true;
70 private bool hover_selection;
71 private IComparer item_sorter;
72 private readonly ListViewItemCollection items;
74 private readonly ListViewGroupCollection groups;
75 private bool owner_draw;
76 private bool show_groups = true;
78 private bool label_edit;
79 private bool label_wrap = true;
80 private bool multiselect = true;
81 private bool scrollable = true;
82 private bool hover_pending;
83 private readonly SelectedIndexCollection selected_indices;
84 private readonly SelectedListViewItemCollection selected_items;
85 private SortOrder sort_order = SortOrder.None;
86 private ImageList state_image_list;
87 private bool updating;
88 private View view = View.LargeIcon;
89 private int layout_wd; // We might draw more than our client area
90 private int layout_ht; // therefore we need to have these two.
91 HeaderControl header_control;
92 internal ItemControl item_control;
93 internal ScrollBar h_scroll; // used for scrolling horizontally
94 internal ScrollBar v_scroll; // used for scrolling vertically
95 internal int h_marker; // Position markers for scrolling
96 internal int v_marker;
97 private int keysearch_tickcnt;
98 private string keysearch_text;
99 static private readonly int keysearch_keydelay = 1000;
100 private int[] reordered_column_indices;
101 private Point [] items_location;
102 private ItemMatrixLocation [] items_matrix_location;
103 private Size item_size; // used for caching item size
104 private int hot_item_index = -1;
106 private bool hot_tracking;
107 private bool show_item_tooltips;
108 private ToolTip item_tooltip;
109 private Size tile_size;
110 private bool virtual_mode;
111 private int virtual_list_size;
114 // internal variables
115 internal ImageList large_image_list;
116 internal ImageList small_image_list;
117 internal Size text_size = Size.Empty;
120 static object AfterLabelEditEvent = new object ();
121 static object BeforeLabelEditEvent = new object ();
122 static object ColumnClickEvent = new object ();
123 static object ItemActivateEvent = new object ();
124 static object ItemCheckEvent = new object ();
125 static object ItemDragEvent = new object ();
126 static object SelectedIndexChangedEvent = new object ();
128 static object DrawColumnHeaderEvent = new object();
129 static object DrawItemEvent = new object();
130 static object DrawSubItemEvent = new object();
131 static object ItemCheckedEvent = new object ();
132 static object ItemMouseHoverEvent = new object ();
133 static object ItemSelectionChangedEvent = new object ();
134 static object CacheVirtualItemsEvent = new object ();
135 static object RetrieveVirtualItemEvent = new object ();
136 static object VirtualItemsSelectionRangeChangedEvent = new object ();
139 public event LabelEditEventHandler AfterLabelEdit {
140 add { Events.AddHandler (AfterLabelEditEvent, value); }
141 remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
145 [EditorBrowsable (EditorBrowsableState.Never)]
146 public new event EventHandler BackgroundImageChanged {
147 add { base.BackgroundImageChanged += value; }
148 remove { base.BackgroundImageChanged -= value; }
151 public event LabelEditEventHandler BeforeLabelEdit {
152 add { Events.AddHandler (BeforeLabelEditEvent, value); }
153 remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
156 public event ColumnClickEventHandler ColumnClick {
157 add { Events.AddHandler (ColumnClickEvent, value); }
158 remove { Events.RemoveHandler (ColumnClickEvent, value); }
162 public event DrawListViewColumnHeaderEventHandler DrawColumnHeader {
163 add { Events.AddHandler(DrawColumnHeaderEvent, value); }
164 remove { Events.RemoveHandler(DrawColumnHeaderEvent, value); }
167 public event DrawListViewItemEventHandler DrawItem {
168 add { Events.AddHandler(DrawItemEvent, value); }
169 remove { Events.RemoveHandler(DrawItemEvent, value); }
172 public event DrawListViewSubItemEventHandler DrawSubItem {
173 add { Events.AddHandler(DrawSubItemEvent, value); }
174 remove { Events.RemoveHandler(DrawSubItemEvent, value); }
178 public event EventHandler ItemActivate {
179 add { Events.AddHandler (ItemActivateEvent, value); }
180 remove { Events.RemoveHandler (ItemActivateEvent, value); }
183 public event ItemCheckEventHandler ItemCheck {
184 add { Events.AddHandler (ItemCheckEvent, value); }
185 remove { Events.RemoveHandler (ItemCheckEvent, value); }
189 public event ItemCheckedEventHandler ItemChecked {
190 add { Events.AddHandler (ItemCheckedEvent, value); }
191 remove { Events.RemoveHandler (ItemCheckedEvent, value); }
195 public event ItemDragEventHandler ItemDrag {
196 add { Events.AddHandler (ItemDragEvent, value); }
197 remove { Events.RemoveHandler (ItemDragEvent, value); }
201 public event ListViewItemMouseHoverEventHandler ItemMouseHover {
202 add { Events.AddHandler (ItemMouseHoverEvent, value); }
203 remove { Events.RemoveHandler (ItemMouseHoverEvent, value); }
206 public event ListViewItemSelectionChangedEventHandler ItemSelectionChanged {
207 add { Events.AddHandler (ItemSelectionChangedEvent, value); }
208 remove { Events.RemoveHandler (ItemSelectionChangedEvent, value); }
213 [EditorBrowsable (EditorBrowsableState.Never)]
214 public new event PaintEventHandler Paint {
215 add { base.Paint += value; }
216 remove { base.Paint -= value; }
219 public event EventHandler SelectedIndexChanged {
220 add { Events.AddHandler (SelectedIndexChangedEvent, value); }
221 remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
225 [EditorBrowsable (EditorBrowsableState.Never)]
226 public new event EventHandler TextChanged {
227 add { base.TextChanged += value; }
228 remove { base.TextChanged -= value; }
232 public event CacheVirtualItemsEventHandler CacheVirtualItems {
233 add { Events.AddHandler (CacheVirtualItemsEvent, value); }
234 remove { Events.RemoveHandler (CacheVirtualItemsEvent, value); }
237 public event RetrieveVirtualItemEventHandler RetrieveVirtualItem {
238 add { Events.AddHandler (RetrieveVirtualItemEvent, value); }
239 remove { Events.RemoveHandler (RetrieveVirtualItemEvent, value); }
242 public event ListViewVirtualItemsSelectionRangeChangedEventHandler VirtualItemsSelectionRangeChanged {
243 add { Events.AddHandler (VirtualItemsSelectionRangeChangedEvent, value); }
244 remove { Events.RemoveHandler (VirtualItemsSelectionRangeChangedEvent, value); }
250 #region Public Constructors
253 background_color = ThemeEngine.Current.ColorWindow;
254 items = new ListViewItemCollection (this);
256 groups = new ListViewGroupCollection (this);
258 checked_indices = new CheckedIndexCollection (this);
259 checked_items = new CheckedListViewItemCollection (this);
260 columns = new ColumnHeaderCollection (this);
261 foreground_color = SystemColors.WindowText;
262 selected_indices = new SelectedIndexCollection (this);
263 selected_items = new SelectedListViewItemCollection (this);
264 items_location = new Point [16];
265 items_matrix_location = new ItemMatrixLocation [16];
267 item_tooltip = new ToolTip ();
268 item_tooltip.Active = false;
271 InternalBorderStyle = BorderStyle.Fixed3D;
273 header_control = new HeaderControl (this);
274 header_control.Visible = false;
275 Controls.AddImplicit (header_control);
277 item_control = new ItemControl (this);
278 Controls.AddImplicit (item_control);
280 h_scroll = new ImplicitHScrollBar ();
281 Controls.AddImplicit (this.h_scroll);
283 v_scroll = new ImplicitVScrollBar ();
284 Controls.AddImplicit (this.v_scroll);
286 h_marker = v_marker = 0;
287 keysearch_tickcnt = 0;
289 // scroll bars are disabled initially
290 h_scroll.Visible = false;
291 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
292 v_scroll.Visible = false;
293 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
296 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
297 SizeChanged += new EventHandler (ListView_SizeChanged);
298 GotFocus += new EventHandler (FocusChanged);
299 LostFocus += new EventHandler (FocusChanged);
300 MouseWheel += new MouseEventHandler(ListView_MouseWheel);
301 MouseEnter += new EventHandler (ListView_MouseEnter);
303 this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
305 | ControlStyles.UseTextForAccessibility
309 #endregion // Public Constructors
311 #region Private Internal Properties
312 internal Size CheckBoxSize {
314 if (this.check_boxes) {
315 if (this.state_image_list != null)
316 return this.state_image_list.ImageSize;
318 return ThemeEngine.Current.ListViewCheckBoxSize;
324 internal Size ItemSize {
326 if (view != View.Details)
329 Size size = new Size ();
330 size.Height = item_size.Height;
331 for (int i = 0; i < columns.Count; i++)
332 size.Width += columns [i].Wd;
341 internal int HotItemIndex {
343 return hot_item_index;
346 hot_item_index = value;
350 #endregion // Private Internal Properties
352 #region Protected Properties
353 protected override CreateParams CreateParams {
354 get { return base.CreateParams; }
357 protected override Size DefaultSize {
358 get { return ThemeEngine.Current.ListViewDefaultSize; }
361 protected override bool DoubleBuffered {
363 return base.DoubleBuffered;
366 base.DoubleBuffered = value;
370 #endregion // Protected Properties
372 #region Public Instance Properties
373 [DefaultValue (ItemActivation.Standard)]
374 public ItemActivation Activation {
375 get { return activation; }
377 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
378 value != ItemActivation.TwoClick) {
379 throw new InvalidEnumArgumentException (string.Format
380 ("Enum argument value '{0}' is not valid for Activation", value));
383 if (hot_tracking && value != ItemActivation.OneClick)
384 throw new ArgumentException ("When HotTracking is on, activation must be ItemActivation.OneClick");
391 [DefaultValue (ListViewAlignment.Top)]
393 public ListViewAlignment Alignment {
394 get { return alignment; }
396 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
397 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
398 throw new InvalidEnumArgumentException (string.Format
399 ("Enum argument value '{0}' is not valid for Alignment", value));
402 if (this.alignment != value) {
404 // alignment does not matter in Details/List views
405 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
411 [DefaultValue (false)]
412 public bool AllowColumnReorder {
413 get { return allow_column_reorder; }
414 set { allow_column_reorder = value; }
417 [DefaultValue (true)]
418 public bool AutoArrange {
419 get { return auto_arrange; }
421 if (auto_arrange != value) {
422 auto_arrange = value;
423 // autoarrange does not matter in Details/List views
424 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
430 public override Color BackColor {
432 if (background_color.IsEmpty)
433 return ThemeEngine.Current.ColorWindow;
435 return background_color;
437 set { background_color = value; }
441 [EditorBrowsable (EditorBrowsableState.Never)]
442 public override Image BackgroundImage {
443 get { return base.BackgroundImage; }
444 set { base.BackgroundImage = value; }
447 [DefaultValue (BorderStyle.Fixed3D)]
449 public BorderStyle BorderStyle {
450 get { return InternalBorderStyle; }
451 set { InternalBorderStyle = value; }
454 [DefaultValue (false)]
455 public bool CheckBoxes {
456 get { return check_boxes; }
458 if (check_boxes != value) {
460 if (value && View == View.Tile)
461 throw new NotSupportedException ("CheckBoxes are not"
462 + " supported in Tile view. Choose a different"
463 + " view or set CheckBoxes to false.");
473 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
474 public CheckedIndexCollection CheckedIndices {
475 get { return checked_indices; }
479 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
480 public CheckedListViewItemCollection CheckedItems {
481 get { return checked_items; }
484 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
486 [MergableProperty (false)]
487 public ColumnHeaderCollection Columns {
488 get { return columns; }
492 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
493 public ListViewItem FocusedItem {
495 if (focused_item_index == -1)
498 return items [focused_item_index];
502 if (value == null || value.ListView != this ||
506 SetFocusedItem (value.Index);
511 public override Color ForeColor {
513 if (foreground_color.IsEmpty)
514 return ThemeEngine.Current.ColorWindowText;
516 return foreground_color;
518 set { foreground_color = value; }
521 [DefaultValue (false)]
522 public bool FullRowSelect {
523 get { return full_row_select; }
525 if (full_row_select != value) {
526 full_row_select = value;
527 InvalidateSelection ();
532 [DefaultValue (false)]
533 public bool GridLines {
534 get { return grid_lines; }
536 if (grid_lines != value) {
543 [DefaultValue (ColumnHeaderStyle.Clickable)]
544 public ColumnHeaderStyle HeaderStyle {
545 get { return header_style; }
547 if (header_style == value)
551 case ColumnHeaderStyle.Clickable:
552 case ColumnHeaderStyle.Nonclickable:
553 case ColumnHeaderStyle.None:
556 throw new InvalidEnumArgumentException (string.Format
557 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
560 header_style = value;
561 if (view == View.Details)
566 [DefaultValue (true)]
567 public bool HideSelection {
568 get { return hide_selection; }
570 if (hide_selection != value) {
571 hide_selection = value;
572 InvalidateSelection ();
578 [DefaultValue (false)]
579 public bool HotTracking {
584 if (hot_tracking == value)
587 hot_tracking = value;
589 hover_selection = true;
590 activation = ItemActivation.OneClick;
596 [DefaultValue (false)]
597 public bool HoverSelection {
598 get { return hover_selection; }
601 if (hot_tracking && value == false)
602 throw new ArgumentException ("When HotTracking is on, hover selection must be true");
604 hover_selection = value;
608 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
610 [MergableProperty (false)]
611 public ListViewItemCollection Items {
612 get { return items; }
615 [DefaultValue (false)]
616 public bool LabelEdit {
617 get { return label_edit; }
618 set { label_edit = value; }
621 [DefaultValue (true)]
623 public bool LabelWrap {
624 get { return label_wrap; }
626 if (label_wrap != value) {
633 [DefaultValue (null)]
634 public ImageList LargeImageList {
635 get { return large_image_list; }
637 large_image_list = value;
643 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
644 public IComparer ListViewItemSorter {
646 if (View != View.SmallIcon && View != View.LargeIcon && item_sorter is ItemComparer)
651 if (item_sorter != value) {
658 [DefaultValue (true)]
659 public bool MultiSelect {
660 get { return multiselect; }
661 set { multiselect = value; }
666 [DefaultValue(false)]
667 public bool OwnerDraw {
668 get { return owner_draw; }
676 [DefaultValue (true)]
677 public bool Scrollable {
678 get { return scrollable; }
680 if (scrollable != value) {
688 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
689 public SelectedIndexCollection SelectedIndices {
690 get { return selected_indices; }
694 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
695 public SelectedListViewItemCollection SelectedItems {
696 get { return selected_items; }
701 public bool ShowGroups {
702 get { return show_groups; }
704 if (show_groups != value) {
711 [LocalizableAttribute (true)]
712 [MergableProperty (false)]
713 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
714 public ListViewGroupCollection Groups {
715 get { return groups; }
718 [DefaultValue (false)]
719 public bool ShowItemToolTips {
721 return show_item_tooltips;
724 show_item_tooltips = value;
725 item_tooltip.Active = false;
730 [DefaultValue (null)]
731 public ImageList SmallImageList {
732 get { return small_image_list; }
734 small_image_list = value;
739 [DefaultValue (SortOrder.None)]
740 public SortOrder Sorting {
741 get { return sort_order; }
743 if (!Enum.IsDefined (typeof (SortOrder), value)) {
744 throw new InvalidEnumArgumentException ("value", (int) value,
748 if (sort_order == value)
754 if (virtual_mode) // Sorting is not allowed in virtual mode
758 if (value == SortOrder.None) {
759 if (item_sorter != null) {
760 // ListViewItemSorter should never be reset for SmallIcon
761 // and LargeIcon view
762 if (View != View.SmallIcon && View != View.LargeIcon)
766 // in .NET 1.1, only internal IComparer would be
768 if (item_sorter is ItemComparer)
774 if (item_sorter == null)
775 item_sorter = new ItemComparer (value);
776 if (item_sorter is ItemComparer) {
778 item_sorter = new ItemComparer (value);
780 // in .NET 1.1, the sort order is not updated for
781 // SmallIcon and LargeIcon views if no custom IComparer
783 if (View != View.SmallIcon && View != View.LargeIcon)
784 item_sorter = new ItemComparer (value);
792 private void OnImageListChanged (object sender, EventArgs args)
794 item_control.Invalidate ();
797 [DefaultValue (null)]
798 public ImageList StateImageList {
799 get { return state_image_list; }
801 if (state_image_list == value)
804 if (state_image_list != null)
805 state_image_list.Images.Changed -= new EventHandler (OnImageListChanged);
807 state_image_list = value;
809 if (state_image_list != null)
810 state_image_list.Images.Changed += new EventHandler (OnImageListChanged);
818 [EditorBrowsable (EditorBrowsableState.Never)]
819 public override string Text {
820 get { return base.Text; }
822 if (value == base.Text)
832 public Size TileSize {
837 if (value.Width <= 0 || value.Height <= 0)
838 throw new ArgumentOutOfRangeException ("value");
847 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
848 public ListViewItem TopItem {
851 if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
852 throw new InvalidOperationException ("Cannot get the top item in LargeIcon, SmallIcon or Tile view.");
855 if (this.items.Count == 0)
857 // if contents are not scrolled
858 // it is the first item
859 else if (h_marker == 0 && v_marker == 0)
860 return this.items [0];
861 // do a hit test for the scrolled position
863 for (int i = 0; i < items.Count; i++) {
864 Point item_loc = GetItemLocation (i);
865 if (item_loc.X >= 0 && item_loc.Y >= 0)
873 if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
874 throw new InvalidOperationException ("Cannot set the top item in LargeIcon, SmallIcon or Tile view.");
876 // .Net doesn't throw any exception in the cases below
877 if (value == null || value.ListView != this)
880 EnsureVisible (value.Index);
886 [EditorBrowsable (EditorBrowsableState.Advanced)]
887 [DefaultValue (true)]
889 [MonoInternalNote ("Stub, not implemented")]
890 public bool UseCompatibleStateImageBehavior {
899 [DefaultValue (View.LargeIcon)]
903 if (!Enum.IsDefined (typeof (View), value))
904 throw new InvalidEnumArgumentException ("value", (int) value,
909 if (CheckBoxes && value == View.Tile)
910 throw new NotSupportedException ("CheckBoxes are not"
911 + " supported in Tile view. Choose a different"
912 + " view or set CheckBoxes to false.");
915 h_scroll.Value = v_scroll.Value = 0;
923 [DefaultValue (false)]
924 [RefreshProperties (RefreshProperties.Repaint)]
925 public bool VirtualMode {
930 if (virtual_mode == value)
933 if (!virtual_mode && items.Count > 0)
934 throw new InvalidOperationException ();
936 virtual_mode = value;
942 [RefreshProperties (RefreshProperties.Repaint)]
943 public int VirtualListSize {
945 return virtual_list_size;
949 throw new ArgumentException ("value");
951 if (virtual_list_size == value)
954 virtual_list_size = value;
960 #endregion // Public Instance Properties
962 #region Internal Methods Properties
964 internal int FirstVisibleIndex {
967 if (this.items.Count == 0)
970 if (h_marker == 0 && v_marker == 0)
973 Size item_size = ItemSize;
974 for (int i = 0; i < items.Count; i++) {
975 Rectangle item_rect = new Rectangle (GetItemLocation (i), item_size);
976 if (item_rect.Right >= 0 && item_rect.Bottom >= 0)
985 internal int LastVisibleIndex {
987 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
988 if (View == View.List || Alignment == ListViewAlignment.Left) {
989 if (GetItemLocation (i).X > item_control.ClientRectangle.Right)
992 if (GetItemLocation (i).Y > item_control.ClientRectangle.Bottom)
997 return Items.Count - 1;
1001 internal void OnSelectedIndexChanged ()
1003 if (IsHandleCreated)
1004 OnSelectedIndexChanged (EventArgs.Empty);
1007 internal int TotalWidth {
1008 get { return Math.Max (this.Width, this.layout_wd); }
1011 internal int TotalHeight {
1012 get { return Math.Max (this.Height, this.layout_ht); }
1015 internal void Redraw (bool recalculate)
1017 // Avoid calculations when control is being updated
1021 // VirtualMode doesn't do any calculations until handle is created
1022 if (virtual_mode && !IsHandleCreated)
1028 CalculateListView (this.alignment);
1033 void InvalidateSelection ()
1035 foreach (int selected_index in SelectedIndices)
1036 items [selected_index].Invalidate ();
1039 const int text_padding = 15;
1041 internal Size GetChildColumnSize (int index)
1043 Size ret_size = Size.Empty;
1044 ColumnHeader col = this.columns [index];
1046 if (col.Width == -2) { // autosize = max(items, columnheader)
1047 Size size = Size.Ceiling (TextRenderer.MeasureString
1048 (col.Text, this.Font));
1049 size.Width += text_padding;
1050 ret_size = BiggestItem (index);
1051 if (size.Width > ret_size.Width)
1054 else { // -1 and all the values < -2 are put under one category
1055 ret_size = BiggestItem (index);
1056 // fall back to empty columns' width if no subitem is available for a column
1057 if (ret_size.IsEmpty) {
1058 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
1059 if (col.Text.Length > 0)
1060 ret_size.Height = Size.Ceiling (TextRenderer.MeasureString
1061 (col.Text, this.Font)).Height;
1063 ret_size.Height = this.Font.Height;
1067 ret_size.Height += text_padding;
1069 // adjust the size for icon and checkbox for 0th column
1071 ret_size.Width += (this.CheckBoxSize.Width + 4);
1072 if (this.small_image_list != null)
1073 ret_size.Width += this.small_image_list.ImageSize.Width;
1078 // Returns the size of biggest item text in a column.
1079 private Size BiggestItem (int col)
1081 Size temp = Size.Empty;
1082 Size ret_size = Size.Empty;
1085 // VirtualMode uses the first item text size
1086 if (virtual_mode && items.Count > 0) {
1087 ListViewItem item = items [0];
1088 ret_size = Size.Ceiling (TextRenderer.MeasureString (item.SubItems[col].Text,
1092 // 0th column holds the item text, we check the size of
1093 // the various subitems falling in that column and get
1094 // the biggest one's size.
1095 foreach (ListViewItem item in items) {
1096 if (col >= item.SubItems.Count)
1099 temp = Size.Ceiling (TextRenderer.MeasureString
1100 (item.SubItems [col].Text, Font));
1101 if (temp.Width > ret_size.Width)
1108 // adjustment for space
1109 if (!ret_size.IsEmpty)
1110 ret_size.Width += 4;
1115 const int max_wrap_padding = 38;
1117 // Sets the size of the biggest item text as per the view
1118 private void CalcTextSize ()
1120 // clear the old value
1121 text_size = Size.Empty;
1123 if (items.Count == 0)
1126 text_size = BiggestItem (0);
1128 if (view == View.LargeIcon && this.label_wrap) {
1129 Size temp = Size.Empty;
1130 if (this.check_boxes)
1131 temp.Width += 2 * this.CheckBoxSize.Width;
1132 int icon_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1133 temp.Width += icon_w + max_wrap_padding;
1134 // wrapping is done for two lines only
1135 if (text_size.Width > temp.Width) {
1136 text_size.Width = temp.Width;
1137 text_size.Height *= 2;
1140 else if (view == View.List) {
1141 // in list view max text shown in determined by the
1142 // control width, even if scolling is enabled.
1143 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
1144 if (this.small_image_list != null)
1145 max_wd -= this.small_image_list.ImageSize.Width;
1147 if (text_size.Width > max_wd)
1148 text_size.Width = max_wd;
1151 // we do the default settings, if we have got 0's
1152 if (text_size.Height <= 0)
1153 text_size.Height = this.Font.Height;
1154 if (text_size.Width <= 0)
1155 text_size.Width = this.Width;
1157 // little adjustment
1158 text_size.Width += 4;
1159 text_size.Height += 2;
1162 private void Scroll (ScrollBar scrollbar, int delta)
1164 if (delta == 0 || !scrollbar.Visible)
1168 if (scrollbar == h_scroll)
1169 max = h_scroll.Maximum - item_control.Width;
1171 max = v_scroll.Maximum - item_control.Height;
1173 int val = scrollbar.Value + delta;
1176 else if (val < scrollbar.Minimum)
1177 val = scrollbar.Minimum;
1178 scrollbar.Value = val;
1181 private void CalculateScrollBars ()
1183 if (!IsHandleCreated)
1186 Rectangle client_area = ClientRectangle;
1189 h_scroll.Visible = false;
1190 v_scroll.Visible = false;
1191 item_control.Height = client_area.Height;
1192 item_control.Width = client_area.Width;
1193 header_control.Width = client_area.Width;
1197 // Don't calculate if the view is not displayable
1198 if (client_area.Height < 0 || client_area.Width < 0)
1201 // making a scroll bar visible might make
1202 // other scroll bar visible
1203 if (layout_wd > client_area.Right) {
1204 h_scroll.Visible = true;
1205 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
1206 v_scroll.Visible = true;
1208 v_scroll.Visible = false;
1209 } else if (layout_ht > client_area.Bottom) {
1210 v_scroll.Visible = true;
1211 if ((layout_wd + v_scroll.Width) > client_area.Right)
1212 h_scroll.Visible = true;
1214 h_scroll.Visible = false;
1216 h_scroll.Visible = false;
1217 v_scroll.Visible = false;
1220 item_control.Height = client_area.Height;
1222 if (h_scroll.is_visible) {
1223 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
1224 h_scroll.Minimum = 0;
1226 // if v_scroll is visible, adjust the maximum of the
1227 // h_scroll to account for the width of v_scroll
1228 if (v_scroll.Visible) {
1229 h_scroll.Maximum = layout_wd + v_scroll.Width;
1230 h_scroll.Width = client_area.Width - v_scroll.Width;
1233 h_scroll.Maximum = layout_wd;
1234 h_scroll.Width = client_area.Width;
1237 h_scroll.LargeChange = client_area.Width;
1238 h_scroll.SmallChange = Font.Height;
1239 item_control.Height -= h_scroll.Height;
1242 if (header_control.is_visible)
1243 header_control.Width = client_area.Width;
1244 item_control.Width = client_area.Width;
1246 if (v_scroll.is_visible) {
1247 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
1248 v_scroll.Minimum = 0;
1250 // if h_scroll is visible, adjust the maximum of the
1251 // v_scroll to account for the height of h_scroll
1252 if (h_scroll.Visible) {
1253 v_scroll.Maximum = layout_ht + h_scroll.Height;
1254 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
1256 v_scroll.Maximum = layout_ht;
1257 v_scroll.Height = client_area.Height;
1260 v_scroll.LargeChange = client_area.Height;
1261 v_scroll.SmallChange = Font.Height;
1262 if (header_control.Visible)
1263 header_control.Width -= v_scroll.Width;
1264 item_control.Width -= v_scroll.Width;
1269 internal int GetReorderedColumnIndex (ColumnHeader column)
1271 if (reordered_column_indices == null)
1272 return column.Index;
1274 for (int i = 0; i < Columns.Count; i++)
1275 if (reordered_column_indices [i] == column.Index)
1282 internal ColumnHeader GetReorderedColumn (int index)
1284 if (reordered_column_indices == null)
1285 return Columns [index];
1287 return Columns [reordered_column_indices [index]];
1290 internal void ReorderColumn (ColumnHeader col, int index, bool fireEvent)
1294 ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
1296 ColumnReorderedEventArgs args = new ColumnReorderedEventArgs (col.Index, index, col);
1300 header_control.Invalidate ();
1301 item_control.Invalidate ();
1307 int column_count = Columns.Count;
1309 if (reordered_column_indices == null) {
1310 reordered_column_indices = new int [column_count];
1311 for (int i = 0; i < column_count; i++)
1312 reordered_column_indices [i] = i;
1315 if (reordered_column_indices [index] == col.Index)
1318 int[] curr = reordered_column_indices;
1319 int [] result = new int [column_count];
1321 for (int i = 0; i < column_count; i++) {
1322 if (curr_idx < column_count && curr [curr_idx] == col.Index)
1326 result [i] = col.Index;
1328 result [i] = curr [curr_idx++];
1331 ReorderColumns (result, true);
1334 internal void ReorderColumns (int [] display_indices, bool redraw)
1336 reordered_column_indices = display_indices;
1337 for (int i = 0; i < Columns.Count; i++) {
1338 ColumnHeader col = Columns [i];
1339 col.InternalDisplayIndex = reordered_column_indices [i];
1341 if (redraw && view == View.Details && IsHandleCreated) {
1343 header_control.Invalidate ();
1344 item_control.Invalidate ();
1348 internal void AddColumn (ColumnHeader newCol, int index, bool redraw)
1350 int column_count = Columns.Count;
1351 newCol.SetListView (this);
1353 int [] display_indices = new int [column_count];
1354 for (int i = 0; i < column_count; i++) {
1355 ColumnHeader col = Columns [i];
1357 display_indices [i] = index;
1359 int display_index = col.InternalDisplayIndex;
1360 if (display_index < index) {
1361 display_indices [i] = display_index;
1363 display_indices [i] = (display_index + 1);
1368 ReorderColumns (display_indices, redraw);
1372 Size LargeIconItemSize
1375 int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1376 int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
1377 int w = CheckBoxSize.Width + 2 + Math.Max (text_size.Width, image_w);
1378 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
1379 return new Size (w, h);
1383 Size SmallIconItemSize {
1385 int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
1386 int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1387 int w = text_size.Width + 2 + CheckBoxSize.Width + image_w;
1388 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
1389 return new Size (w, h);
1396 // Calculate tile size if needed
1397 // It appears that using Font.Size instead of a SizeF value can give us
1398 // a slightly better approach to the proportions defined in .Net
1399 if (tile_size == Size.Empty) {
1400 int image_w = LargeImageList == null ? 0 : LargeImageList.ImageSize.Width;
1401 int image_h = LargeImageList == null ? 0 : LargeImageList.ImageSize.Height;
1402 int w = (int)Font.Size * ThemeEngine.Current.ListViewTileWidthFactor + image_w + 4;
1403 int h = Math.Max ((int)Font.Size * ThemeEngine.Current.ListViewTileHeightFactor, image_h);
1405 tile_size = new Size (w, h);
1413 int GetDetailsItemHeight ()
1416 int checkbox_height = CheckBoxes ? CheckBoxSize.Height : 0;
1417 int small_image_height = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1418 item_height = Math.Max (checkbox_height, text_size.Height);
1419 item_height = Math.Max (item_height, small_image_height);
1424 void SetItemLocation (int index, int x, int y, int row, int col)
1426 Point old_location = items_location [index];
1427 if (old_location.X == x && old_location.Y == y)
1430 Size item_size = ItemSize;
1431 Rectangle old_rect = new Rectangle (GetItemLocation (index), item_size);
1433 items_location [index] = new Point (x, y);
1434 items_matrix_location [index] = new ItemMatrixLocation (row, col);
1436 // Invalidate both previous and new bounds
1437 item_control.Invalidate (old_rect);
1438 item_control.Invalidate (new Rectangle (GetItemLocation (index), item_size));
1442 // When using groups, the items with no group assigned
1443 // belong to the DefaultGroup
1444 int GetDefaultGroupItems ()
1447 foreach (ListViewItem item in items)
1448 if (item.Group == null)
1457 int[,] item_index_matrix;
1459 void CalculateRowsAndCols (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1461 Rectangle area = ClientRectangle;
1463 if (show_groups && groups.Count > 0 && view != View.List) {
1464 // When groups are used the alignment is always top-aligned
1468 groups.DefaultGroup.ItemCount = GetDefaultGroupItems ();
1469 for (int i = 0; i < groups.InternalCount; i++) {
1470 ListViewGroup group = groups.GetInternalGroup (i);
1471 int items_in_group = group.ItemCount;
1473 if (items_in_group == 0)
1476 int group_cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
1477 if (group_cols <= 0)
1479 int group_rows = (int) Math.Ceiling ((double)items_in_group / (double)group_cols);
1481 group.starting_row = rows;
1482 group.rows = group_rows;
1484 cols = Math.Max (group_cols, cols);
1490 // Simple matrix if no groups are used
1492 rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(item_size.Height + y_spacing));
1495 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
1497 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
1500 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
1504 item_index_matrix = new int [rows, cols];
1507 void LayoutIcons (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1509 header_control.Visible = false;
1510 header_control.Size = Size.Empty;
1511 item_control.Visible = true;
1512 item_control.Location = Point.Empty;
1513 ItemSize = item_size; // Cache item size
1515 if (items.Count == 0)
1518 Size sz = item_size;
1520 bool using_groups = show_groups && groups.Count > 0 && view != View.List;
1523 CalculateRowsAndCols (sz, left_aligned, x_spacing, y_spacing);
1525 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
1526 layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
1530 CalculateGroupsLayout (sz, y_spacing, 0);
1533 int row = 0, col = 0;
1536 for (int i = 0; i < items.Count; i++) {
1537 ListViewItem item = items [i];
1545 ListViewGroup group = item.Group;
1547 group = groups.DefaultGroup;
1549 Point group_items_loc = group.items_area_location;
1550 int current_item = group.current_item++;
1551 int starting_row = group.starting_row;
1553 row = (current_item / cols);
1554 col = current_item % cols;
1556 x = col * (item_size.Width + x_spacing);
1557 y = row * (item_size.Height + y_spacing) + group_items_loc.Y;
1559 SetItemLocation (i, x, y, row + starting_row, col);
1560 item_index_matrix [row + starting_row, col] = i;
1564 x = col * (item_size.Width + x_spacing);
1565 y = row * (item_size.Height + y_spacing);
1567 SetItemLocation (i, x, y, row, col);
1568 item_index_matrix [row, col] = i;
1577 if (++col == cols) {
1586 item_control.Size = new Size (layout_wd, layout_ht);
1590 void CalculateGroupsLayout (Size item_size, int y_spacing, int y_origin)
1593 bool details = view == View.Details;
1595 for (int i = 0; i < groups.InternalCount; i++) {
1596 ListViewGroup group = groups.GetInternalGroup (i);
1597 if (group.ItemCount == 0)
1600 group.current_item = 0; // Reset layout
1601 y += LayoutGroupHeader (group, y, item_size.Height, y_spacing, details ? group.ItemCount : group.rows);
1604 layout_ht = y; // Update height taking into account Groups' headers heights
1607 int LayoutGroupHeader (ListViewGroup group, int y_origin, int item_height, int y_spacing, int rows)
1609 Rectangle client_area = ClientRectangle;
1610 int header_height = text_size.Height + 10;
1612 group.HeaderBounds = new Rectangle (0, y_origin, client_area.Width - v_scroll.Width, header_height);
1613 group.items_area_location = new Point (0, y_origin + header_height);
1615 int items_area_height = ((item_height + y_spacing) * rows);
1616 return header_height + items_area_height + 10; // Add a small bottom margin
1620 void LayoutHeader ()
1623 for (int i = 0; i < Columns.Count; i++) {
1624 ColumnHeader col = GetReorderedColumn (i);
1627 col.CalcColumnHeader ();
1633 if (x < ClientRectangle.Width)
1634 x = ClientRectangle.Width;
1636 if (header_style == ColumnHeaderStyle.None) {
1637 header_control.Visible = false;
1638 header_control.Size = Size.Empty;
1639 layout_wd = ClientRectangle.Width;
1641 header_control.Width = x;
1642 header_control.Height = columns.Count > 0 ? columns [0].Ht : Font.Height + 5;
1643 header_control.Visible = true;
1647 void LayoutDetails ()
1651 if (columns.Count == 0) {
1652 item_control.Visible = false;
1653 layout_wd = ClientRectangle.Width;
1654 layout_ht = ClientRectangle.Height;
1658 item_control.Visible = true;
1659 item_control.Location = Point.Empty;
1660 item_control.Width = ClientRectangle.Width;
1662 int item_height = GetDetailsItemHeight ();
1663 ItemSize = new Size (0, item_height); // We only cache Height for details view
1664 int y = header_control.Height;
1666 bool using_groups = show_groups && groups.Count > 0 && view != View.List;
1668 CalculateGroupsLayout (ItemSize, 2, y);
1671 for (int i = 0; i < items.Count; i++) {
1672 ListViewItem item = items [i];
1674 if (!virtual_mode) // Virtual mode sets Layout until draw time
1680 ListViewGroup group = item.Group;
1682 group = groups.DefaultGroup;
1684 int current_item = group.current_item++;
1685 Point group_items_loc = group.items_area_location;
1687 SetItemLocation (i, 0, current_item * (item_height + 2) + group_items_loc.Y, 0, 0);
1691 SetItemLocation (i, 0, y, 0, 0);
1692 y += item_height + 4;
1696 // some space for bottom gridline
1697 if (items.Count > 0 && grid_lines)
1701 if (!using_groups) // With groups it has been previously computed
1706 private void AdjustItemsPositionArray (int count)
1708 if (items_location.Length >= count)
1711 // items_location and items_matrix_location must keep the same length
1712 count = Math.Max (count, items_location.Length * 2);
1713 items_location = new Point [count];
1714 items_matrix_location = new ItemMatrixLocation [count];
1717 private void CalculateListView (ListViewAlignment align)
1721 AdjustItemsPositionArray (items.Count);
1728 case View.SmallIcon:
1729 LayoutIcons (SmallIconItemSize, alignment == ListViewAlignment.Left,
1730 ThemeEngine.Current.ListViewHorizontalSpacing, 2);
1733 case View.LargeIcon:
1734 LayoutIcons (LargeIconItemSize, alignment == ListViewAlignment.Left,
1735 ThemeEngine.Current.ListViewHorizontalSpacing,
1736 ThemeEngine.Current.ListViewVerticalSpacing);
1740 LayoutIcons (SmallIconItemSize, true,
1741 ThemeEngine.Current.ListViewHorizontalSpacing, 2);
1745 LayoutIcons (TileItemSize, alignment == ListViewAlignment.Left,
1746 ThemeEngine.Current.ListViewHorizontalSpacing,
1747 ThemeEngine.Current.ListViewVerticalSpacing);
1752 CalculateScrollBars ();
1755 internal Point GetItemLocation (int index)
1757 Point loc = items_location [index];
1758 loc.X -= h_marker; // Adjust to scroll
1764 private bool KeySearchString (KeyEventArgs ke)
1766 int current_tickcnt = Environment.TickCount;
1767 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
1768 keysearch_text = string.Empty;
1771 if (!Char.IsLetterOrDigit ((char)ke.KeyCode))
1774 keysearch_text += (char)ke.KeyCode;
1775 keysearch_tickcnt = current_tickcnt;
1777 int start = FocusedItem == null ? 0 : FocusedItem.Index;
1780 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1781 CompareOptions.IgnoreCase)) {
1783 items [i].Selected = true;
1787 i = (i + 1 < Items.Count) ? i+1 : 0;
1795 int GetAdjustedIndex (Keys key)
1799 if (View == View.Details) {
1802 result = FocusedItem.Index - 1;
1805 result = FocusedItem.Index + 1;
1806 if (result == items.Count)
1810 int last_index = LastVisibleIndex;
1811 Rectangle item_rect = new Rectangle (GetItemLocation (last_index), ItemSize);
1812 if (item_rect.Bottom > item_control.ClientRectangle.Bottom)
1814 if (FocusedItem.Index == last_index) {
1815 if (FocusedItem.Index < Items.Count - 1) {
1816 int page_size = item_control.Height / ItemSize.Height - 1;
1817 result = FocusedItem.Index + page_size - 1;
1818 if (result >= Items.Count)
1819 result = Items.Count - 1;
1822 result = last_index;
1825 int first_index = FirstVisibleIndex;
1826 if (GetItemLocation (first_index).Y < 0)
1828 if (FocusedItem.Index == first_index) {
1829 if (first_index > 0) {
1830 int page_size = item_control.Height / ItemSize.Height - 1;
1831 result = first_index - page_size + 1;
1836 result = first_index;
1842 ItemMatrixLocation item_matrix_location = items_matrix_location [FocusedItem.Index];
1843 int row = item_matrix_location.Row;
1844 int col = item_matrix_location.Col;
1850 return item_index_matrix [row, col - 1];
1853 if (col == (cols - 1))
1855 while (item_index_matrix [row, col + 1] == 0) {
1860 return item_index_matrix [row, col + 1];
1865 while (item_index_matrix [row - 1, col] == 0 && row != 1) {
1870 return item_index_matrix [row - 1, col];
1873 if (row == (rows - 1) || row == Items.Count - 1)
1875 while (item_index_matrix [row + 1, col] == 0) {
1880 return item_index_matrix [row + 1, col];
1887 ListViewItem selection_start;
1889 private bool SelectItems (ArrayList sel_items)
1891 bool changed = false;
1892 foreach (ListViewItem item in SelectedItems)
1893 if (!sel_items.Contains (item)) {
1894 item.Selected = false;
1897 foreach (ListViewItem item in sel_items)
1898 if (!item.Selected) {
1899 item.Selected = true;
1905 private void UpdateMultiSelection (int index, bool reselect)
1907 bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
1908 bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
1909 ListViewItem item = items [index];
1911 if (shift_pressed && selection_start != null) {
1912 ArrayList list = new ArrayList ();
1913 int start_index = selection_start.Index;
1914 int start = Math.Min (start_index, index);
1915 int end = Math.Max (start_index, index);
1916 if (View == View.Details) {
1917 for (int i = start; i <= end; i++)
1918 list.Add (items [i]);
1920 ItemMatrixLocation start_item_matrix_location = items_matrix_location [start];
1921 ItemMatrixLocation end_item_matrix_location = items_matrix_location [end];
1922 int left = Math.Min (start_item_matrix_location.Col, end_item_matrix_location.Col);
1923 int right = Math.Max (start_item_matrix_location.Col, end_item_matrix_location.Col);
1924 int top = Math.Min (start_item_matrix_location.Row, end_item_matrix_location.Row);
1925 int bottom = Math.Max (start_item_matrix_location.Row, end_item_matrix_location.Row);
1927 for (int i = 0; i < items.Count; i++) {
1928 ItemMatrixLocation item_matrix_loc = items_matrix_location [i];
1930 if (item_matrix_loc.Row >= top && item_matrix_loc.Row <= bottom &&
1931 item_matrix_loc.Col >= left && item_matrix_loc.Col <= right)
1932 list.Add (items [i]);
1936 } else if (ctrl_pressed) {
1937 item.Selected = !item.Selected;
1938 selection_start = item;
1941 // do not unselect, and reselect the item
1942 foreach (int itemIndex in SelectedIndices) {
1943 if (index == itemIndex)
1945 items [itemIndex].Selected = false;
1948 SelectedItems.Clear ();
1949 item.Selected = true;
1951 selection_start = item;
1955 internal override bool InternalPreProcessMessage (ref Message msg)
1957 if (msg.Msg == (int)Msg.WM_KEYDOWN) {
1958 Keys key_data = (Keys)msg.WParam.ToInt32();
1960 HandleNavKeys (key_data);
1963 return base.InternalPreProcessMessage (ref msg);
1966 bool HandleNavKeys (Keys key_data)
1968 if (Items.Count == 0 || !item_control.Visible)
1971 if (FocusedItem == null)
1976 SelectIndex (Items.Count - 1);
1989 SelectIndex (GetAdjustedIndex (key_data));
1993 ToggleItemsCheckState ();
1996 if (selected_indices.Count > 0)
1997 OnItemActivate (EventArgs.Empty);
2007 void ToggleItemsCheckState ()
2012 // Don't modify check state if StateImageList has less than 2 elements
2013 if (StateImageList != null && StateImageList.Images.Count < 2)
2016 if (SelectedIndices.Count > 0) {
2017 for (int i = 0; i < SelectedIndices.Count; i++) {
2018 ListViewItem item = Items [SelectedIndices [i]];
2019 item.Checked = !item.Checked;
2024 if (FocusedItem != null) {
2025 FocusedItem.Checked = !FocusedItem.Checked;
2026 SelectIndex (FocusedItem.Index);
2030 void SelectIndex (int index)
2036 UpdateMultiSelection (index, true);
2037 else if (!items [index].Selected)
2038 items [index].Selected = true;
2040 SetFocusedItem (index);
2041 EnsureVisible (index);
2044 private void ListView_KeyDown (object sender, KeyEventArgs ke)
2046 if (ke.Handled || Items.Count == 0 || !item_control.Visible)
2049 if (ke.Alt || ke.Control)
2052 ke.Handled = KeySearchString (ke);
2055 private MouseEventArgs TranslateMouseEventArgs (MouseEventArgs args)
2057 Point loc = PointToClient (Control.MousePosition);
2058 return new MouseEventArgs (args.Button, args.Clicks, loc.X, loc.Y, args.Delta);
2061 internal class ItemControl : Control {
2064 ListViewItem clicked_item;
2065 ListViewItem last_clicked_item;
2066 bool hover_processed = false;
2067 bool checking = false;
2068 ListViewItem prev_hovered_item;
2070 ListViewItem prev_tooltip_item;
2074 ListViewLabelEditTextBox edit_text_box;
2075 internal ListViewItem edit_item;
2076 LabelEditEventArgs edit_args;
2078 public ItemControl (ListView owner)
2081 DoubleClick += new EventHandler(ItemsDoubleClick);
2082 MouseDown += new MouseEventHandler(ItemsMouseDown);
2083 MouseMove += new MouseEventHandler(ItemsMouseMove);
2084 MouseHover += new EventHandler(ItemsMouseHover);
2085 MouseUp += new MouseEventHandler(ItemsMouseUp);
2088 void ItemsDoubleClick (object sender, EventArgs e)
2090 if (owner.activation == ItemActivation.Standard)
2091 owner.OnItemActivate (EventArgs.Empty);
2101 BoxSelect box_select_mode = BoxSelect.None;
2102 IList prev_selection;
2103 Point box_select_start;
2105 Rectangle box_select_rect;
2106 internal Rectangle BoxSelectRectangle {
2107 get { return box_select_rect; }
2109 if (box_select_rect == value)
2112 InvalidateBoxSelectRect ();
2113 box_select_rect = value;
2114 InvalidateBoxSelectRect ();
2118 void InvalidateBoxSelectRect ()
2120 if (BoxSelectRectangle.Size.IsEmpty)
2123 Rectangle edge = BoxSelectRectangle;
2129 edge.Y = BoxSelectRectangle.Bottom - 1;
2131 edge.Y = BoxSelectRectangle.Y - 1;
2133 edge.Height = BoxSelectRectangle.Height + 2;
2135 edge.X = BoxSelectRectangle.Right - 1;
2139 private Rectangle CalculateBoxSelectRectangle (Point pt)
2141 int left = Math.Min (box_select_start.X, pt.X);
2142 int right = Math.Max (box_select_start.X, pt.X);
2143 int top = Math.Min (box_select_start.Y, pt.Y);
2144 int bottom = Math.Max (box_select_start.Y, pt.Y);
2145 return Rectangle.FromLTRB (left, top, right, bottom);
2148 bool BoxIntersectsItem (int index)
2150 Rectangle r = new Rectangle (owner.GetItemLocation (index), owner.ItemSize);
2151 if (owner.View != View.Details) {
2153 r.Y += r.Height / 4;
2157 return BoxSelectRectangle.IntersectsWith (r);
2160 bool BoxIntersectsText (int index)
2162 Rectangle r = owner.Items [index].TextBounds;
2163 return BoxSelectRectangle.IntersectsWith (r);
2166 ArrayList BoxSelectedItems {
2168 ArrayList result = new ArrayList ();
2169 for (int i = 0; i < owner.Items.Count; i++) {
2171 if (owner.View == View.Details && !owner.FullRowSelect)
2172 intersects = BoxIntersectsText (i);
2174 intersects = BoxIntersectsItem (i);
2177 result.Add (owner.Items [i]);
2183 private bool PerformBoxSelection (Point pt)
2185 if (box_select_mode == BoxSelect.None)
2188 BoxSelectRectangle = CalculateBoxSelectRectangle (pt);
2190 ArrayList box_items = BoxSelectedItems;
2194 switch (box_select_mode) {
2196 case BoxSelect.Normal:
2200 case BoxSelect.Control:
2201 items = new ArrayList ();
2202 foreach (int index in prev_selection)
2203 if (!box_items.Contains (owner.Items [index]))
2204 items.Add (owner.Items [index]);
2205 foreach (ListViewItem item in box_items)
2206 if (!prev_selection.Contains (item.Index))
2210 case BoxSelect.Shift:
2212 foreach (ListViewItem item in box_items)
2213 prev_selection.Remove (item.Index);
2214 foreach (int index in prev_selection)
2215 items.Add (owner.Items [index]);
2219 throw new Exception ("Unexpected Selection mode: " + box_select_mode);
2223 owner.SelectItems (items);
2229 private void ItemsMouseDown (object sender, MouseEventArgs me)
2231 owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
2232 if (owner.items.Count == 0)
2235 bool box_selecting = false;
2236 Size item_size = owner.ItemSize;
2237 Point pt = new Point (me.X, me.Y);
2238 for (int i = 0; i < owner.items.Count; i++) {
2239 Rectangle item_rect = new Rectangle (owner.GetItemLocation (i), item_size);
2240 if (!item_rect.Contains (pt))
2243 if (owner.items [i].CheckRectReal.Contains (pt)) {
2244 ListViewItem item = owner.items [i];
2246 // Don't modify check state if we have only one image
2247 // and if we are in 1.1 profile only take into account
2249 if (owner.StateImageList != null && owner.StateImageList.Images.Count < 2
2256 // Generate an extra ItemCheck event when we got two clicks
2257 // (Match weird .Net behaviour)
2259 item.Checked = !item.Checked;
2261 item.Checked = !item.Checked;
2266 if (owner.View == View.Details) {
2267 bool over_text = owner.items [i].TextBounds.Contains (pt);
2268 if (owner.FullRowSelect) {
2269 clicked_item = owner.items [i];
2270 bool over_item_column = (me.X > owner.Columns[0].X && me.X < owner.Columns[0].X + owner.Columns[0].Width);
2271 if (!over_text && over_item_column && owner.MultiSelect)
2272 box_selecting = true;
2273 } else if (over_text)
2274 clicked_item = owner.items [i];
2276 owner.SetFocusedItem (i);
2278 clicked_item = owner.items [i];
2284 if (clicked_item != null) {
2285 bool changed = !clicked_item.Selected;
2286 if (me.Button == MouseButtons.Left || (XplatUI.State.ModifierKeys == Keys.None && changed))
2287 owner.SetFocusedItem (clicked_item.Index);
2289 if (owner.MultiSelect) {
2290 bool reselect = (!owner.LabelEdit || changed);
2291 if (me.Button == MouseButtons.Left || (XplatUI.State.ModifierKeys == Keys.None && changed))
2292 owner.UpdateMultiSelection (clicked_item.Index, reselect);
2294 clicked_item.Selected = true;
2298 if (owner.VirtualMode && changed) {
2299 // Broken event - It's not fired from Item.Selected also
2300 ListViewVirtualItemsSelectionRangeChangedEventArgs args =
2301 new ListViewVirtualItemsSelectionRangeChangedEventArgs (0, owner.items.Count - 1, false);
2303 owner.OnVirtualItemsSelectionRangeChanged (args);
2306 // Report clicks only if the item was clicked. On MS the
2307 // clicks are only raised if you click an item
2309 if (me.Clicks > 1) {
2310 if (owner.CheckBoxes)
2311 clicked_item.Checked = !clicked_item.Checked;
2312 } else if (me.Clicks == 1) {
2313 if (owner.LabelEdit && !changed)
2314 BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
2317 if (owner.MultiSelect)
2318 box_selecting = true;
2319 else if (owner.SelectedItems.Count > 0)
2320 owner.SelectedItems.Clear ();
2323 if (box_selecting) {
2324 Keys mods = XplatUI.State.ModifierKeys;
2325 if ((mods & Keys.Shift) != 0)
2326 box_select_mode = BoxSelect.Shift;
2327 else if ((mods & Keys.Control) != 0)
2328 box_select_mode = BoxSelect.Control;
2330 box_select_mode = BoxSelect.Normal;
2331 box_select_start = pt;
2332 prev_selection = owner.SelectedIndices.List.Clone () as IList;
2336 private void ItemsMouseMove (object sender, MouseEventArgs me)
2338 bool done = PerformBoxSelection (new Point (me.X, me.Y));
2340 owner.OnMouseMove (owner.TranslateMouseEventArgs (me));
2344 if (!hover_processed && owner.Activation != ItemActivation.OneClick
2346 && !owner.ShowItemToolTips
2351 Point pt = PointToClient (Control.MousePosition);
2352 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
2354 if (hover_processed && item != null && item != prev_hovered_item) {
2355 hover_processed = false;
2356 XplatUI.ResetMouseHover (Handle);
2359 // Need to invalidate the item in HotTracking to show/hide the underline style
2360 if (owner.Activation == ItemActivation.OneClick) {
2361 if (item == null && owner.HotItemIndex != -1) {
2363 if (owner.HotTracking)
2364 Invalidate (owner.Items [owner.HotItemIndex].Bounds); // Previous one
2367 Cursor = Cursors.Default;
2368 owner.HotItemIndex = -1;
2369 } else if (item != null && owner.HotItemIndex == -1) {
2371 if (owner.HotTracking)
2372 Invalidate (item.Bounds);
2375 Cursor = Cursors.Hand;
2376 owner.HotItemIndex = item.Index;
2381 if (owner.ShowItemToolTips) {
2383 owner.item_tooltip.Active = false;
2384 prev_tooltip_item = null;
2385 } else if (item != prev_tooltip_item && item.ToolTipText.Length > 0) {
2386 owner.item_tooltip.Active = true;
2387 owner.item_tooltip.SetToolTip (owner, item.ToolTipText);
2388 prev_tooltip_item = item;
2396 private void ItemsMouseHover (object sender, EventArgs e)
2398 if (owner.hover_pending) {
2399 owner.OnMouseHover (e);
2400 owner.hover_pending = false;
2406 hover_processed = true;
2407 Point pt = PointToClient (Control.MousePosition);
2408 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
2412 prev_hovered_item = item;
2414 if (owner.HoverSelection) {
2415 if (owner.MultiSelect)
2416 owner.UpdateMultiSelection (item.Index, true);
2418 item.Selected = true;
2420 owner.SetFocusedItem (item.Index);
2421 Select (); // Make sure we have the focus, since MouseHover doesn't give it to us
2425 owner.OnItemMouseHover (new ListViewItemMouseHoverEventArgs (item));
2429 void HandleClicks (MouseEventArgs me)
2431 // if the click is not on an item,
2432 // clicks remains as 0
2435 owner.OnDoubleClick (EventArgs.Empty);
2436 } else if (clicks == 1) {
2437 owner.OnClick (EventArgs.Empty);
2439 owner.OnDoubleClick (EventArgs.Empty);
2440 owner.OnMouseDoubleClick (me);
2441 } else if (clicks == 1) {
2442 owner.OnClick (EventArgs.Empty);
2443 owner.OnMouseClick (me);
2450 private void ItemsMouseUp (object sender, MouseEventArgs me)
2452 MouseEventArgs owner_me = owner.TranslateMouseEventArgs (me);
2453 HandleClicks (owner_me);
2456 if (owner.Items.Count == 0) {
2457 owner.OnMouseUp (owner_me);
2461 Point pt = new Point (me.X, me.Y);
2463 Rectangle rect = Rectangle.Empty;
2464 if (clicked_item != null) {
2465 if (owner.view == View.Details && !owner.full_row_select)
2466 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
2468 rect = clicked_item.Bounds;
2470 if (rect.Contains (pt)) {
2471 switch (owner.activation) {
2472 case ItemActivation.OneClick:
2473 owner.OnItemActivate (EventArgs.Empty);
2476 case ItemActivation.TwoClick:
2477 if (last_clicked_item == clicked_item) {
2478 owner.OnItemActivate (EventArgs.Empty);
2479 last_clicked_item = null;
2481 last_clicked_item = clicked_item;
2484 // DoubleClick activation is handled in another handler
2488 } else if (!checking && owner.SelectedItems.Count > 0 && BoxSelectRectangle.Size.IsEmpty) {
2489 // Need this to clean up background clicks
2490 owner.SelectedItems.Clear ();
2493 clicked_item = null;
2494 box_select_start = Point.Empty;
2495 BoxSelectRectangle = Rectangle.Empty;
2496 prev_selection = null;
2497 box_select_mode = BoxSelect.None;
2499 owner.OnMouseUp (owner_me);
2502 private void LabelEditFinished (object sender, EventArgs e)
2504 EndEdit (edit_item);
2507 private void LabelEditCancelled (object sender, EventArgs e)
2509 edit_args.SetLabel (null);
2510 EndEdit (edit_item);
2513 private void LabelTextChanged (object sender, EventArgs e)
2515 if (edit_args != null)
2516 edit_args.SetLabel (edit_text_box.Text);
2519 internal void BeginEdit (ListViewItem item)
2521 if (edit_item != null)
2522 EndEdit (edit_item);
2524 if (edit_text_box == null) {
2525 edit_text_box = new ListViewLabelEditTextBox ();
2526 edit_text_box.BorderStyle = BorderStyle.FixedSingle;
2527 edit_text_box.EditingCancelled += new EventHandler (LabelEditCancelled);
2528 edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
2529 edit_text_box.TextChanged += new EventHandler (LabelTextChanged);
2530 edit_text_box.Visible = false;
2531 Controls.Add (edit_text_box);
2534 item.EnsureVisible();
2536 edit_text_box.Reset ();
2538 switch (owner.view) {
2540 case View.SmallIcon:
2542 edit_text_box.TextAlign = HorizontalAlignment.Left;
2543 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
2544 SizeF sizef = TextRenderer.MeasureString (item.Text, item.Font);
2545 edit_text_box.Width = (int)sizef.Width + 4;
2546 edit_text_box.MaxWidth = owner.ClientRectangle.Width - edit_text_box.Bounds.X;
2547 edit_text_box.WordWrap = false;
2548 edit_text_box.Multiline = false;
2550 case View.LargeIcon:
2551 edit_text_box.TextAlign = HorizontalAlignment.Center;
2552 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
2553 sizef = TextRenderer.MeasureString (item.Text, item.Font);
2554 edit_text_box.Width = (int)sizef.Width + 4;
2555 edit_text_box.MaxWidth = item.GetBounds(ItemBoundsPortion.Entire).Width;
2556 edit_text_box.MaxHeight = owner.ClientRectangle.Height - edit_text_box.Bounds.Y;
2557 edit_text_box.WordWrap = true;
2558 edit_text_box.Multiline = true;
2564 edit_text_box.Text = item.Text;
2565 edit_text_box.Font = item.Font;
2566 edit_text_box.Visible = true;
2567 edit_text_box.Focus ();
2568 edit_text_box.SelectAll ();
2570 edit_args = new LabelEditEventArgs (owner.Items.IndexOf (edit_item));
2571 owner.OnBeforeLabelEdit (edit_args);
2573 if (edit_args.CancelEdit)
2577 internal void CancelEdit (ListViewItem item)
2579 // do nothing if there's no item being edited, or if the
2580 // item being edited is not the one passed in
2581 if (edit_item == null || edit_item != item)
2584 edit_args.SetLabel (null);
2588 internal void EndEdit (ListViewItem item)
2590 // do nothing if there's no item being edited, or if the
2591 // item being edited is not the one passed in
2592 if (edit_item == null || edit_item != item)
2595 owner.OnAfterLabelEdit (edit_args);
2596 if (!edit_args.CancelEdit && edit_args.Label != null)
2597 edit_item.Text = edit_text_box.Text;
2599 if (edit_text_box != null) {
2600 if (edit_text_box.Visible)
2601 edit_text_box.Visible = false;
2602 // ensure listview gets focus
2609 internal override void OnPaintInternal (PaintEventArgs pe)
2611 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
2614 protected override void WndProc (ref Message m)
2616 switch ((Msg)m.Msg) {
2617 case Msg.WM_KILLFOCUS:
2618 owner.Select (false, true);
2620 case Msg.WM_SETFOCUS:
2621 owner.Select (false, true);
2623 case Msg.WM_RBUTTONDOWN:
2624 owner.Select (false, true);
2629 base.WndProc (ref m);
2633 internal class ListViewLabelEditTextBox : TextBox
2638 int max_height = -1;
2639 int min_height = -1;
2641 int old_number_lines = 1;
2643 SizeF text_size_one_char;
2645 public ListViewLabelEditTextBox ()
2647 min_height = DefaultSize.Height;
2648 text_size_one_char = TextRenderer.MeasureString ("B", Font);
2651 public int MaxWidth {
2653 if (value < min_width)
2654 max_width = min_width;
2660 public int MaxHeight {
2662 if (value < min_height)
2663 max_height = min_height;
2669 public new int Width {
2679 public override Font Font {
2685 text_size_one_char = TextRenderer.MeasureString ("B", Font);
2689 protected override void OnTextChanged (EventArgs e)
2691 SizeF text_size = TextRenderer.MeasureString (Text, Font);
2693 int new_width = (int)text_size.Width + 8;
2696 ResizeTextBoxWidth (new_width);
2698 if (Width != max_width)
2699 ResizeTextBoxWidth (new_width);
2701 int number_lines = Lines.Length;
2703 if (number_lines != old_number_lines) {
2704 int new_height = number_lines * (int)text_size_one_char.Height + 4;
2705 old_number_lines = number_lines;
2707 ResizeTextBoxHeight (new_height);
2711 base.OnTextChanged (e);
2714 protected override bool IsInputKey (Keys key_data)
2716 if ((key_data & Keys.Alt) == 0) {
2717 switch (key_data & Keys.KeyCode) {
2724 return base.IsInputKey (key_data);
2727 protected override void OnKeyDown (KeyEventArgs e)
2732 switch (e.KeyCode) {
2736 OnEditingFinished (e);
2741 OnEditingCancelled (e);
2746 protected override void OnLostFocus (EventArgs e)
2749 OnEditingFinished (e);
2753 protected void OnEditingCancelled (EventArgs e)
2755 EventHandler eh = (EventHandler)(Events [EditingCancelledEvent]);
2760 protected void OnEditingFinished (EventArgs e)
2762 EventHandler eh = (EventHandler)(Events [EditingFinishedEvent]);
2767 private void ResizeTextBoxWidth (int new_width)
2769 if (new_width > max_width)
2770 base.Width = max_width;
2772 if (new_width >= min_width)
2773 base.Width = new_width;
2775 base.Width = min_width;
2778 private void ResizeTextBoxHeight (int new_height)
2780 if (new_height > max_height)
2781 base.Height = max_height;
2783 if (new_height >= min_height)
2784 base.Height = new_height;
2786 base.Height = min_height;
2789 public void Reset ()
2796 old_number_lines = 1;
2798 Text = String.Empty;
2803 static object EditingCancelledEvent = new object ();
2804 public event EventHandler EditingCancelled {
2805 add { Events.AddHandler (EditingCancelledEvent, value); }
2806 remove { Events.RemoveHandler (EditingCancelledEvent, value); }
2809 static object EditingFinishedEvent = new object ();
2810 public event EventHandler EditingFinished {
2811 add { Events.AddHandler (EditingFinishedEvent, value); }
2812 remove { Events.RemoveHandler (EditingFinishedEvent, value); }
2816 internal override void OnPaintInternal (PaintEventArgs pe)
2821 CalculateScrollBars ();
2824 void FocusChanged (object o, EventArgs args)
2826 if (Items.Count == 0)
2829 if (FocusedItem == null)
2832 ListViewItem focused_item = FocusedItem;
2834 if (focused_item.ListView != null) {
2835 item_control.Invalidate (focused_item.Bounds);
2836 focused_item.Layout ();
2837 item_control.Invalidate (focused_item.Bounds);
2841 private void ListView_MouseEnter (object sender, EventArgs args)
2843 hover_pending = true; // Need a hover event for every Enter/Leave cycle
2846 private void ListView_MouseWheel (object sender, MouseEventArgs me)
2848 if (Items.Count == 0)
2851 int lines = me.Delta / 120;
2858 case View.SmallIcon:
2859 Scroll (v_scroll, -ItemSize.Height * SystemInformation.MouseWheelScrollLines * lines);
2861 case View.LargeIcon:
2862 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * lines);
2865 Scroll (h_scroll, -ItemSize.Width * lines);
2869 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * 2 * lines);
2875 private void ListView_SizeChanged (object sender, EventArgs e)
2877 CalculateListView (alignment);
2880 private void SetFocusedItem (int index)
2883 items [index].Focused = true;
2884 else if (focused_item_index != -1) // Previous focused item
2885 items [focused_item_index].Focused = false;
2887 focused_item_index = index;
2890 private void HorizontalScroller (object sender, EventArgs e)
2892 item_control.EndEdit (item_control.edit_item);
2894 // Avoid unnecessary flickering, when button is
2895 // kept pressed at the end
2896 if (h_marker != h_scroll.Value) {
2898 int pixels = h_marker - h_scroll.Value;
2900 h_marker = h_scroll.Value;
2901 if (header_control.Visible)
2902 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
2904 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
2908 private void VerticalScroller (object sender, EventArgs e)
2910 item_control.EndEdit (item_control.edit_item);
2912 // Avoid unnecessary flickering, when button is
2913 // kept pressed at the end
2914 if (v_marker != v_scroll.Value) {
2915 int pixels = v_marker - v_scroll.Value;
2916 Rectangle area = item_control.ClientRectangle;
2917 if (header_control.Visible) {
2918 area.Y += header_control.Height;
2919 area.Height -= header_control.Height;
2922 v_marker = v_scroll.Value;
2923 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
2927 internal override bool IsInputCharInternal (char charCode)
2931 #endregion // Internal Methods Properties
2933 #region Protected Methods
2934 protected override void CreateHandle ()
2936 base.CreateHandle ();
2937 for (int i = 0; i < SelectedItems.Count; i++)
2938 OnSelectedIndexChanged (EventArgs.Empty);
2941 protected override void Dispose (bool disposing)
2944 h_scroll.Dispose ();
2945 v_scroll.Dispose ();
2947 large_image_list = null;
2948 small_image_list = null;
2949 state_image_list = null;
2951 foreach (ColumnHeader col in columns)
2952 col.SetListView (null);
2955 if (!virtual_mode) // In virtual mode we don't save the items
2957 foreach (ListViewItem item in items)
2961 base.Dispose (disposing);
2964 protected override bool IsInputKey (Keys keyData)
2981 return base.IsInputKey (keyData);
2984 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
2986 LabelEditEventHandler eh = (LabelEditEventHandler)(Events [AfterLabelEditEvent]);
2992 protected override void OnBackgroundImageChanged (EventArgs args)
2994 base.OnBackgroundImageChanged (args);
2998 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
3000 LabelEditEventHandler eh = (LabelEditEventHandler)(Events [BeforeLabelEditEvent]);
3005 protected virtual void OnColumnClick (ColumnClickEventArgs e)
3007 ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]);
3013 protected internal virtual void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
3015 DrawListViewColumnHeaderEventHandler eh = (DrawListViewColumnHeaderEventHandler)(Events[DrawColumnHeaderEvent]);
3020 protected internal virtual void OnDrawItem(DrawListViewItemEventArgs e)
3022 DrawListViewItemEventHandler eh = (DrawListViewItemEventHandler)(Events[DrawItemEvent]);
3027 protected internal virtual void OnDrawSubItem(DrawListViewSubItemEventArgs e)
3029 DrawListViewSubItemEventHandler eh = (DrawListViewSubItemEventHandler)(Events[DrawSubItemEvent]);
3035 protected override void OnEnabledChanged (EventArgs e)
3037 base.OnEnabledChanged (e);
3040 protected override void OnFontChanged (EventArgs e)
3042 base.OnFontChanged (e);
3046 protected override void OnHandleCreated (EventArgs e)
3048 base.OnHandleCreated (e);
3049 CalculateListView (alignment);
3051 if (!virtual_mode) // Sorting is not allowed in virtual mode
3056 protected override void OnHandleDestroyed (EventArgs e)
3058 base.OnHandleDestroyed (e);
3061 protected virtual void OnItemActivate (EventArgs e)
3063 EventHandler eh = (EventHandler)(Events [ItemActivateEvent]);
3068 protected internal virtual void OnItemCheck (ItemCheckEventArgs ice)
3070 ItemCheckEventHandler eh = (ItemCheckEventHandler)(Events [ItemCheckEvent]);
3076 protected internal virtual void OnItemChecked (ItemCheckedEventArgs icea)
3078 ItemCheckedEventHandler eh = (ItemCheckedEventHandler)(Events [ItemCheckedEvent]);
3084 protected virtual void OnItemDrag (ItemDragEventArgs e)
3086 EventHandler eh = (EventHandler)(Events [ItemDragEvent]);
3092 protected virtual void OnItemMouseHover (ListViewItemMouseHoverEventArgs args)
3094 ListViewItemMouseHoverEventHandler eh = (ListViewItemMouseHoverEventHandler)(Events [ItemMouseHoverEvent]);
3099 protected internal virtual void OnItemSelectionChanged (ListViewItemSelectionChangedEventArgs args)
3101 ListViewItemSelectionChangedEventHandler eh =
3102 (ListViewItemSelectionChangedEventHandler) Events [ItemSelectionChangedEvent];
3107 protected override void OnMouseHover (EventArgs args)
3109 base.OnMouseHover (args);
3112 protected override void OnParentChanged (EventArgs args)
3114 base.OnParentChanged (args);
3118 protected virtual void OnSelectedIndexChanged (EventArgs e)
3120 EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
3125 protected override void OnSystemColorsChanged (EventArgs e)
3127 base.OnSystemColorsChanged (e);
3131 protected virtual void OnCacheVirtualItems (CacheVirtualItemsEventArgs args)
3133 EventHandler eh = (EventHandler)Events [CacheVirtualItemsEvent];
3138 protected virtual void OnRetrieveVirtualItem (RetrieveVirtualItemEventArgs args)
3140 RetrieveVirtualItemEventHandler eh = (RetrieveVirtualItemEventHandler)Events [RetrieveVirtualItemEvent];
3145 protected virtual void OnVirtualItemsSelectionRangeChanged (ListViewVirtualItemsSelectionRangeChangedEventArgs args)
3147 ListViewVirtualItemsSelectionRangeChangedEventHandler eh =
3148 (ListViewVirtualItemsSelectionRangeChangedEventHandler) Events [VirtualItemsSelectionRangeChangedEvent];
3154 protected void RealizeProperties ()
3159 protected void UpdateExtendedStyles ()
3164 bool refocusing = false;
3166 protected override void WndProc (ref Message m)
3168 switch ((Msg)m.Msg) {
3169 case Msg.WM_KILLFOCUS:
3170 Control receiver = Control.FromHandle (m.WParam);
3171 if (receiver == item_control) {
3177 case Msg.WM_SETFOCUS:
3187 base.WndProc (ref m);
3189 #endregion // Protected Methods
3191 #region Public Instance Methods
3192 public void ArrangeIcons ()
3194 ArrangeIcons (this.alignment);
3197 public void ArrangeIcons (ListViewAlignment alignment)
3199 // Icons are arranged only if view is set to LargeIcon or SmallIcon
3200 if (view == View.LargeIcon || view == View.SmallIcon) {
3201 this.CalculateListView (alignment);
3202 // we have done the calculations already
3203 this.Redraw (false);
3208 public void AutoResizeColumn (int columnIndex, ColumnHeaderAutoResizeStyle headerAutoResize)
3210 if (columnIndex < 0 || columnIndex >= columns.Count)
3211 throw new ArgumentOutOfRangeException ("columnIndex");
3213 columns [columnIndex].AutoResize (headerAutoResize);
3216 public void AutoResizeColumns (ColumnHeaderAutoResizeStyle headerAutoResize)
3219 foreach (ColumnHeader col in columns)
3220 col.AutoResize (headerAutoResize);
3225 public void BeginUpdate ()
3227 // flag to avoid painting
3231 public void Clear ()
3234 items.Clear (); // Redraw (true) called here
3237 public void EndUpdate ()
3239 // flag to avoid painting
3242 // probably, now we need a redraw with recalculations
3246 public void EnsureVisible (int index)
3248 if (index < 0 || index >= items.Count || scrollable == false)
3251 Rectangle view_rect = item_control.ClientRectangle;
3252 Rectangle bounds = new Rectangle (GetItemLocation (index), ItemSize);
3254 if (view_rect.Contains (bounds))
3257 if (View != View.Details) {
3258 if (bounds.Left < 0)
3259 h_scroll.Value += bounds.Left;
3260 else if (bounds.Right > view_rect.Right)
3261 h_scroll.Value += (bounds.Right - view_rect.Right);
3265 v_scroll.Value += bounds.Top;
3266 else if (bounds.Bottom > view_rect.Bottom)
3267 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
3271 public ListViewItem FindItemWithText (string text)
3273 if (items.Count == 0)
3276 return FindItemWithText (text, true, 0, true);
3279 public ListViewItem FindItemWithText (string text, bool includeSubItems, int startIndex)
3281 return FindItemWithText (text, includeSubItems, startIndex, true);
3284 public ListViewItem FindItemWithText (string text, bool includeSubItems, int startIndex, bool prefixSearch)
3286 if (startIndex < 0 || startIndex >= items.Count)
3287 throw new ArgumentOutOfRangeException ("startIndex");
3290 throw new ArgumentNullException ("text");
3292 for (int i = startIndex; i < items.Count; i++) {
3293 ListViewItem lvi = items [i];
3295 if ((prefixSearch && lvi.Text.StartsWith (text, true, CultureInfo.CurrentCulture)) // prefix search
3296 || String.Compare (lvi.Text, text, true) == 0) // match
3300 if (includeSubItems) {
3301 for (int i = startIndex; i < items.Count; i++) {
3302 ListViewItem lvi = items [i];
3303 foreach (ListViewItem.ListViewSubItem sub_item in lvi.SubItems)
3304 if ((prefixSearch && sub_item.Text.StartsWith (text, true, CultureInfo.CurrentCulture))
3305 || String.Compare (sub_item.Text, text, true) == 0)
3314 public ListViewItem GetItemAt (int x, int y)
3316 Size item_size = ItemSize;
3317 for (int i = 0; i < items.Count; i++) {
3318 Point item_location = GetItemLocation (i);
3319 Rectangle item_rect = new Rectangle (item_location, item_size);
3320 if (item_rect.Contains (x, y))
3327 public Rectangle GetItemRect (int index)
3329 return GetItemRect (index, ItemBoundsPortion.Entire);
3332 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
3334 if (index < 0 || index >= items.Count)
3335 throw new IndexOutOfRangeException ("index");
3337 return items [index].GetBounds (portion);
3341 public ListViewHitTestInfo HitTest (Point pt)
3343 return HitTest (pt.X, pt.Y);
3346 public ListViewHitTestInfo HitTest (int x, int y)
3349 throw new ArgumentOutOfRangeException ("x");
3351 throw new ArgumentOutOfRangeException ("y");
3353 ListViewItem item = GetItemAt (x, y);
3355 return new ListViewHitTestInfo (null, null, ListViewHitTestLocations.None);
3357 ListViewHitTestLocations locations = 0;
3358 if (item.GetBounds (ItemBoundsPortion.Label).Contains (x, y))
3359 locations |= ListViewHitTestLocations.Label;
3360 else if (item.GetBounds (ItemBoundsPortion.Icon).Contains (x, y))
3361 locations |= ListViewHitTestLocations.Image;
3362 else if (item.CheckRectReal.Contains (x, y))
3363 locations |= ListViewHitTestLocations.StateImage;
3365 ListViewItem.ListViewSubItem subitem = null;
3366 if (view == View.Details)
3367 foreach (ListViewItem.ListViewSubItem si in item.SubItems)
3368 if (si.Bounds.Contains (x, y)) {
3373 return new ListViewHitTestInfo (item, subitem, locations);
3376 public void RedrawItems (int startIndex, int endIndex, bool invalidateOnly)
3378 if (startIndex < 0 || startIndex >= items.Count)
3379 throw new ArgumentOutOfRangeException ("startIndex");
3380 if (endIndex < 0 || endIndex >= items.Count)
3381 throw new ArgumentOutOfRangeException ("endIndex");
3382 if (startIndex > endIndex)
3383 throw new ArgumentException ("startIndex");
3388 for (int i = startIndex; i <= endIndex; i++)
3389 item_control.Invalidate (items [i].Bounds);
3391 if (!invalidateOnly)
3400 throw new InvalidOperationException ();
3406 // we need this overload to reuse the logic for sorting, while allowing
3407 // redrawing to be done by caller or have it done by this method when
3408 // sorting is really performed
3410 // ListViewItemCollection's Add and AddRange methods call this overload
3411 // with redraw set to false, as they take care of redrawing themselves
3412 // (they even want to redraw the listview if no sort is performed, as
3413 // an item was added), while ListView.Sort () only wants to redraw if
3414 // sorting was actually performed
3415 private void Sort (bool redraw)
3417 if (!IsHandleCreated || item_sorter == null) {
3421 items.Sort (item_sorter);
3426 public override string ToString ()
3428 int count = this.Items.Count;
3431 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
3433 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
3435 #endregion // Public Instance Methods
3440 class HeaderControl : Control {
3443 bool column_resize_active = false;
3444 ColumnHeader resize_column;
3445 ColumnHeader clicked_column;
3446 ColumnHeader drag_column;
3448 int drag_to_index = -1;
3450 public HeaderControl (ListView owner)
3453 MouseDown += new MouseEventHandler (HeaderMouseDown);
3454 MouseMove += new MouseEventHandler (HeaderMouseMove);
3455 MouseUp += new MouseEventHandler (HeaderMouseUp);
3458 private ColumnHeader ColumnAtX (int x)
3460 Point pt = new Point (x, 0);
3461 ColumnHeader result = null;
3462 foreach (ColumnHeader col in owner.Columns) {
3463 if (col.Rect.Contains (pt)) {
3471 private int GetReorderedIndex (ColumnHeader col)
3473 if (owner.reordered_column_indices == null)
3476 for (int i = 0; i < owner.Columns.Count; i++)
3477 if (owner.reordered_column_indices [i] == col.Index)
3479 throw new Exception ("Column index missing from reordered array");
3482 private void HeaderMouseDown (object sender, MouseEventArgs me)
3484 if (resize_column != null) {
3485 column_resize_active = true;
3490 clicked_column = ColumnAtX (me.X + owner.h_marker);
3492 if (clicked_column != null) {
3494 if (owner.AllowColumnReorder) {
3496 drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
3497 drag_column.Rect = clicked_column.Rect;
3498 drag_to_index = GetReorderedIndex (clicked_column);
3500 clicked_column.Pressed = true;
3501 Rectangle bounds = clicked_column.Rect;
3502 bounds.X -= owner.h_marker;
3503 Invalidate (bounds);
3510 column_resize_active = false;
3511 resize_column = null;
3513 Cursor = Cursors.Default;
3516 private void HeaderMouseMove (object sender, MouseEventArgs me)
3518 Point pt = new Point (me.X + owner.h_marker, me.Y);
3520 if (column_resize_active) {
3521 int width = pt.X - resize_column.X;
3525 if (!owner.CanProceedWithResize (resize_column, width)){
3529 resize_column.Width = width;
3533 resize_column = null;
3535 if (clicked_column != null) {
3536 if (owner.AllowColumnReorder) {
3539 r = drag_column.Rect;
3540 r.X = clicked_column.Rect.X + me.X - drag_x;
3541 drag_column.Rect = r;
3543 int x = me.X + owner.h_marker;
3544 ColumnHeader over = ColumnAtX (x);
3546 drag_to_index = owner.Columns.Count;
3547 else if (x < over.X + over.Width / 2)
3548 drag_to_index = GetReorderedIndex (over);
3550 drag_to_index = GetReorderedIndex (over) + 1;
3553 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
3554 bool pressed = clicked_column.Pressed;
3555 clicked_column.Pressed = over == clicked_column;
3556 if (clicked_column.Pressed ^ pressed) {
3557 Rectangle bounds = clicked_column.Rect;
3558 bounds.X -= owner.h_marker;
3559 Invalidate (bounds);
3565 for (int i = 0; i < owner.Columns.Count; i++) {
3566 Rectangle zone = owner.Columns [i].Rect;
3567 zone.X = zone.Right - 5;
3569 if (zone.Contains (pt)) {
3570 if (i < owner.Columns.Count - 1 && owner.Columns [i + 1].Width == 0)
3572 resize_column = owner.Columns [i];
3577 if (resize_column == null)
3578 Cursor = Cursors.Default;
3580 Cursor = Cursors.VSplit;
3583 void HeaderMouseUp (object sender, MouseEventArgs me)
3587 if (column_resize_active) {
3588 int column_idx = resize_column.Index;
3590 owner.RaiseColumnWidthChanged (column_idx);
3594 if (clicked_column != null && clicked_column.Pressed) {
3595 clicked_column.Pressed = false;
3596 Rectangle bounds = clicked_column.Rect;
3597 bounds.X -= owner.h_marker;
3598 Invalidate (bounds);
3599 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
3602 if (drag_column != null && owner.AllowColumnReorder) {
3604 if (drag_to_index > GetReorderedIndex (clicked_column))
3606 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
3607 owner.ReorderColumn (clicked_column, drag_to_index, true);
3612 clicked_column = null;
3615 internal override void OnPaintInternal (PaintEventArgs pe)
3620 Theme theme = ThemeEngine.Current;
3621 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
3623 if (drag_column == null)
3627 if (drag_to_index == owner.Columns.Count)
3628 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
3630 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
3631 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
3634 protected override void WndProc (ref Message m)
3636 switch ((Msg)m.Msg) {
3637 case Msg.WM_SETFOCUS:
3641 base.WndProc (ref m);
3647 private class ItemComparer : IComparer {
3648 readonly SortOrder sort_order;
3650 public ItemComparer (SortOrder sortOrder)
3652 sort_order = sortOrder;
3655 public int Compare (object x, object y)
3657 ListViewItem item_x = x as ListViewItem;
3658 ListViewItem item_y = y as ListViewItem;
3659 if (sort_order == SortOrder.Ascending)
3660 return String.Compare (item_x.Text, item_y.Text);
3662 return String.Compare (item_y.Text, item_x.Text);
3666 public class CheckedIndexCollection : IList, ICollection, IEnumerable
3668 private readonly ListView owner;
3670 #region Public Constructor
3671 public CheckedIndexCollection (ListView owner)
3675 #endregion // Public Constructor
3677 #region Public Properties
3680 get { return owner.CheckedItems.Count; }
3683 public bool IsReadOnly {
3684 get { return true; }
3687 public int this [int index] {
3689 int [] indices = GetIndices ();
3690 if (index < 0 || index >= indices.Length)
3691 throw new ArgumentOutOfRangeException ("index");
3692 return indices [index];
3696 bool ICollection.IsSynchronized {
3697 get { return false; }
3700 object ICollection.SyncRoot {
3701 get { return this; }
3704 bool IList.IsFixedSize {
3705 get { return true; }
3708 object IList.this [int index] {
3709 get { return this [index]; }
3710 set { throw new NotSupportedException ("SetItem operation is not supported."); }
3712 #endregion // Public Properties
3714 #region Public Methods
3715 public bool Contains (int checkedIndex)
3717 int [] indices = GetIndices ();
3718 for (int i = 0; i < indices.Length; i++) {
3719 if (indices [i] == checkedIndex)
3725 public IEnumerator GetEnumerator ()
3727 int [] indices = GetIndices ();
3728 return indices.GetEnumerator ();
3731 void ICollection.CopyTo (Array dest, int index)
3733 int [] indices = GetIndices ();
3734 Array.Copy (indices, 0, dest, index, indices.Length);
3737 int IList.Add (object value)
3739 throw new NotSupportedException ("Add operation is not supported.");
3744 throw new NotSupportedException ("Clear operation is not supported.");
3747 bool IList.Contains (object checkedIndex)
3749 if (!(checkedIndex is int))
3751 return Contains ((int) checkedIndex);
3754 int IList.IndexOf (object checkedIndex)
3756 if (!(checkedIndex is int))
3758 return IndexOf ((int) checkedIndex);
3761 void IList.Insert (int index, object value)
3763 throw new NotSupportedException ("Insert operation is not supported.");
3766 void IList.Remove (object value)
3768 throw new NotSupportedException ("Remove operation is not supported.");
3771 void IList.RemoveAt (int index)
3773 throw new NotSupportedException ("RemoveAt operation is not supported.");
3776 public int IndexOf (int checkedIndex)
3778 int [] indices = GetIndices ();
3779 for (int i = 0; i < indices.Length; i++) {
3780 if (indices [i] == checkedIndex)
3785 #endregion // Public Methods
3787 private int [] GetIndices ()
3789 ArrayList checked_items = owner.CheckedItems.List;
3790 int [] indices = new int [checked_items.Count];
3791 for (int i = 0; i < checked_items.Count; i++) {
3792 ListViewItem item = (ListViewItem) checked_items [i];
3793 indices [i] = item.Index;
3797 } // CheckedIndexCollection
3799 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
3801 private readonly ListView owner;
3802 private ArrayList list;
3804 #region Public Constructor
3805 public CheckedListViewItemCollection (ListView owner)
3808 this.owner.Items.Changed += new CollectionChangedHandler (
3809 ItemsCollection_Changed);
3811 #endregion // Public Constructor
3813 #region Public Properties
3817 if (!owner.CheckBoxes)
3823 public bool IsReadOnly {
3824 get { return true; }
3827 public ListViewItem this [int index] {
3830 if (owner.VirtualMode)
3831 throw new InvalidOperationException ();
3833 ArrayList checked_items = List;
3834 if (index < 0 || index >= checked_items.Count)
3835 throw new ArgumentOutOfRangeException ("index");
3836 return (ListViewItem) checked_items [index];
3841 public virtual ListViewItem this [string key] {
3843 int idx = IndexOfKey (key);
3844 return idx == -1 ? null : (ListViewItem) List [idx];
3849 bool ICollection.IsSynchronized {
3850 get { return false; }
3853 object ICollection.SyncRoot {
3854 get { return this; }
3857 bool IList.IsFixedSize {
3858 get { return true; }
3861 object IList.this [int index] {
3862 get { return this [index]; }
3863 set { throw new NotSupportedException ("SetItem operation is not supported."); }
3865 #endregion // Public Properties
3867 #region Public Methods
3868 public bool Contains (ListViewItem item)
3870 if (!owner.CheckBoxes)
3872 return List.Contains (item);
3876 public virtual bool ContainsKey (string key)
3878 return IndexOfKey (key) != -1;
3882 public void CopyTo (Array dest, int index)
3885 if (owner.VirtualMode)
3886 throw new InvalidOperationException ();
3888 if (!owner.CheckBoxes)
3890 List.CopyTo (dest, index);
3893 public IEnumerator GetEnumerator ()
3896 if (owner.VirtualMode)
3897 throw new InvalidOperationException ();
3899 if (!owner.CheckBoxes)
3900 return (new ListViewItem [0]).GetEnumerator ();
3901 return List.GetEnumerator ();
3904 int IList.Add (object value)
3906 throw new NotSupportedException ("Add operation is not supported.");
3911 throw new NotSupportedException ("Clear operation is not supported.");
3914 bool IList.Contains (object item)
3916 if (!(item is ListViewItem))
3918 return Contains ((ListViewItem) item);
3921 int IList.IndexOf (object item)
3923 if (!(item is ListViewItem))
3925 return IndexOf ((ListViewItem) item);
3928 void IList.Insert (int index, object value)
3930 throw new NotSupportedException ("Insert operation is not supported.");
3933 void IList.Remove (object value)
3935 throw new NotSupportedException ("Remove operation is not supported.");
3938 void IList.RemoveAt (int index)
3940 throw new NotSupportedException ("RemoveAt operation is not supported.");
3943 public int IndexOf (ListViewItem item)
3946 if (owner.VirtualMode)
3947 throw new InvalidOperationException ();
3949 if (!owner.CheckBoxes)
3951 return List.IndexOf (item);
3955 public virtual int IndexOfKey (string key)
3958 if (owner.VirtualMode)
3959 throw new InvalidOperationException ();
3961 if (key == null || key.Length == 0)
3964 ArrayList checked_items = List;
3965 for (int i = 0; i < checked_items.Count; i++) {
3966 ListViewItem item = (ListViewItem) checked_items [i];
3967 if (String.Compare (key, item.Name, true) == 0)
3974 #endregion // Public Methods
3976 internal ArrayList List {
3979 list = new ArrayList ();
3980 foreach (ListViewItem item in owner.Items) {
3989 internal void Reset ()
3991 // force re-population of list
3995 private void ItemsCollection_Changed ()
3999 } // CheckedListViewItemCollection
4001 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
4003 internal ArrayList list;
4004 private ListView owner;
4006 #region Public Constructor
4007 public ColumnHeaderCollection (ListView owner)
4009 list = new ArrayList ();
4012 #endregion // Public Constructor
4014 #region Public Properties
4017 get { return list.Count; }
4020 public bool IsReadOnly {
4021 get { return false; }
4024 public virtual ColumnHeader this [int index] {
4026 if (index < 0 || index >= list.Count)
4027 throw new ArgumentOutOfRangeException ("index");
4028 return (ColumnHeader) list [index];
4033 public virtual ColumnHeader this [string key] {
4035 int idx = IndexOfKey (key);
4039 return (ColumnHeader) list [idx];
4044 bool ICollection.IsSynchronized {
4045 get { return true; }
4048 object ICollection.SyncRoot {
4049 get { return this; }
4052 bool IList.IsFixedSize {
4053 get { return list.IsFixedSize; }
4056 object IList.this [int index] {
4057 get { return this [index]; }
4058 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4060 #endregion // Public Properties
4062 #region Public Methods
4063 public virtual int Add (ColumnHeader value)
4065 int idx = list.Add (value);
4066 owner.AddColumn (value, idx, true);
4070 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
4072 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
4073 this.Add (colHeader);
4078 public virtual ColumnHeader Add (string text)
4080 return Add (String.Empty, text);
4083 public virtual ColumnHeader Add (string text, int iwidth)
4085 return Add (String.Empty, text, iwidth);
4088 public virtual ColumnHeader Add (string key, string text)
4090 ColumnHeader colHeader = new ColumnHeader ();
4091 colHeader.Name = key;
4092 colHeader.Text = text;
4097 public virtual ColumnHeader Add (string key, string text, int iwidth)
4099 return Add (key, text, iwidth, HorizontalAlignment.Left, -1);
4102 public virtual ColumnHeader Add (string key, string text, int iwidth, HorizontalAlignment textAlign, int imageIndex)
4104 ColumnHeader colHeader = new ColumnHeader (key, text, iwidth, textAlign);
4105 colHeader.ImageIndex = imageIndex;
4110 public virtual ColumnHeader Add (string key, string text, int iwidth, HorizontalAlignment textAlign, string imageKey)
4112 ColumnHeader colHeader = new ColumnHeader (key, text, iwidth, textAlign);
4113 colHeader.ImageKey = imageKey;
4119 public virtual void AddRange (ColumnHeader [] values)
4121 foreach (ColumnHeader colHeader in values) {
4122 int idx = list.Add (colHeader);
4123 owner.AddColumn (colHeader, idx, false);
4126 owner.Redraw (true);
4129 public virtual void Clear ()
4131 foreach (ColumnHeader col in list)
4132 col.SetListView (null);
4134 owner.ReorderColumns (new int [0], true);
4137 public bool Contains (ColumnHeader value)
4139 return list.Contains (value);
4143 public virtual bool ContainsKey (string key)
4145 return IndexOfKey (key) != -1;
4149 public IEnumerator GetEnumerator ()
4151 return list.GetEnumerator ();
4154 void ICollection.CopyTo (Array dest, int index)
4156 list.CopyTo (dest, index);
4159 int IList.Add (object value)
4161 if (! (value is ColumnHeader)) {
4162 throw new ArgumentException ("Not of type ColumnHeader", "value");
4165 return this.Add ((ColumnHeader) value);
4168 bool IList.Contains (object value)
4170 if (! (value is ColumnHeader)) {
4171 throw new ArgumentException ("Not of type ColumnHeader", "value");
4174 return this.Contains ((ColumnHeader) value);
4177 int IList.IndexOf (object value)
4179 if (! (value is ColumnHeader)) {
4180 throw new ArgumentException ("Not of type ColumnHeader", "value");
4183 return this.IndexOf ((ColumnHeader) value);
4186 void IList.Insert (int index, object value)
4188 if (! (value is ColumnHeader)) {
4189 throw new ArgumentException ("Not of type ColumnHeader", "value");
4192 this.Insert (index, (ColumnHeader) value);
4195 void IList.Remove (object value)
4197 if (! (value is ColumnHeader)) {
4198 throw new ArgumentException ("Not of type ColumnHeader", "value");
4201 this.Remove ((ColumnHeader) value);
4204 public int IndexOf (ColumnHeader value)
4206 return list.IndexOf (value);
4210 public virtual int IndexOfKey (string key)
4212 if (key == null || key.Length == 0)
4215 for (int i = 0; i < list.Count; i++) {
4216 ColumnHeader col = (ColumnHeader) list [i];
4217 if (String.Compare (key, col.Name, true) == 0)
4225 public void Insert (int index, ColumnHeader value)
4227 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
4228 // but it's really only greater.
4229 if (index < 0 || index > list.Count)
4230 throw new ArgumentOutOfRangeException ("index");
4232 list.Insert (index, value);
4233 owner.AddColumn (value, index, true);
4237 public void Insert (int index, string text)
4239 Insert (index, String.Empty, text);
4242 public void Insert (int index, string text, int width)
4244 Insert (index, String.Empty, text, width);
4247 public void Insert (int index, string key, string text)
4249 ColumnHeader colHeader = new ColumnHeader ();
4250 colHeader.Name = key;
4251 colHeader.Text = text;
4252 Insert (index, colHeader);
4255 public void Insert (int index, string key, string text, int width)
4257 ColumnHeader colHeader = new ColumnHeader (key, text, width, HorizontalAlignment.Left);
4258 Insert (index, colHeader);
4261 public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
4263 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4264 colHeader.ImageIndex = imageIndex;
4265 Insert (index, colHeader);
4268 public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
4270 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4271 colHeader.ImageKey = imageKey;
4272 Insert (index, colHeader);
4276 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
4278 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
4279 this.Insert (index, colHeader);
4282 public virtual void Remove (ColumnHeader column)
4284 if (!Contains (column))
4287 list.Remove (column);
4288 column.SetListView (null);
4290 int rem_display_index = column.InternalDisplayIndex;
4291 int [] display_indices = new int [list.Count];
4292 for (int i = 0; i < display_indices.Length; i++) {
4293 ColumnHeader col = (ColumnHeader) list [i];
4294 int display_index = col.InternalDisplayIndex;
4295 if (display_index < rem_display_index) {
4296 display_indices [i] = display_index;
4298 display_indices [i] = (display_index - 1);
4302 column.InternalDisplayIndex = -1;
4303 owner.ReorderColumns (display_indices, true);
4307 public virtual void RemoveByKey (string key)
4309 int idx = IndexOfKey (key);
4315 public virtual void RemoveAt (int index)
4317 if (index < 0 || index >= list.Count)
4318 throw new ArgumentOutOfRangeException ("index");
4320 ColumnHeader col = (ColumnHeader) list [index];
4323 #endregion // Public Methods
4326 } // ColumnHeaderCollection
4328 public class ListViewItemCollection : IList, ICollection, IEnumerable
4330 private readonly ArrayList list;
4331 private ListView owner;
4333 private ListViewGroup group;
4336 // The collection can belong to a ListView (main) or to a ListViewGroup (sub-collection)
4337 // In the later case ListViewItem.ListView never gets modified
4338 private bool is_main_collection = true;
4340 #region Public Constructor
4341 public ListViewItemCollection (ListView owner)
4343 list = new ArrayList (0);
4346 #endregion // Public Constructor
4349 internal ListViewItemCollection (ListView owner, ListViewGroup group) : this (owner)
4352 is_main_collection = false;
4356 #region Public Properties
4361 if (owner != null && owner.VirtualMode)
4362 return owner.VirtualListSize;
4369 public bool IsReadOnly {
4370 get { return false; }
4373 public virtual ListViewItem this [int displayIndex] {
4375 if (displayIndex < 0 || displayIndex >= Count)
4376 throw new ArgumentOutOfRangeException ("displayIndex");
4379 if (owner != null && owner.VirtualMode)
4380 return RetrieveVirtualItemFromOwner (displayIndex);
4382 return (ListViewItem) list [displayIndex];
4386 if (displayIndex < 0 || displayIndex >= Count)
4387 throw new ArgumentOutOfRangeException ("displayIndex");
4390 if (owner != null && owner.VirtualMode)
4391 throw new InvalidOperationException ();
4394 if (list.Contains (value))
4395 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
4397 if (value.ListView != null && value.ListView != owner)
4398 throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value");
4400 if (is_main_collection)
4401 value.Owner = owner;
4404 if (value.Group != null)
4405 value.Group.Items.Remove (value);
4407 value.SetGroup (group);
4411 list [displayIndex] = value;
4412 CollectionChanged (true);
4417 public virtual ListViewItem this [string key] {
4419 int idx = IndexOfKey (key);
4428 bool ICollection.IsSynchronized {
4429 get { return true; }
4432 object ICollection.SyncRoot {
4433 get { return this; }
4436 bool IList.IsFixedSize {
4437 get { return list.IsFixedSize; }
4440 object IList.this [int index] {
4441 get { return this [index]; }
4443 if (value is ListViewItem)
4444 this [index] = (ListViewItem) value;
4446 this [index] = new ListViewItem (value.ToString ());
4450 #endregion // Public Properties
4452 #region Public Methods
4453 public virtual ListViewItem Add (ListViewItem value)
4456 if (owner != null && owner.VirtualMode)
4457 throw new InvalidOperationException ();
4461 CollectionChanged (true);
4466 public virtual ListViewItem Add (string text)
4468 ListViewItem item = new ListViewItem (text);
4469 return this.Add (item);
4472 public virtual ListViewItem Add (string text, int imageIndex)
4474 ListViewItem item = new ListViewItem (text, imageIndex);
4475 return this.Add (item);
4479 public virtual ListViewItem Add (string text, string imageKey)
4481 ListViewItem item = new ListViewItem (text, imageKey);
4482 return this.Add (item);
4485 public virtual ListViewItem Add (string key, string text, int imageIndex)
4487 ListViewItem item = new ListViewItem (text, imageIndex);
4489 return this.Add (item);
4492 public virtual ListViewItem Add (string key, string text, string imageKey)
4494 ListViewItem item = new ListViewItem (text, imageKey);
4496 return this.Add (item);
4500 public void AddRange (ListViewItem [] values)
4503 throw new ArgumentNullException ("Argument cannot be null!", "values");
4505 if (owner != null && owner.VirtualMode)
4506 throw new InvalidOperationException ();
4509 foreach (ListViewItem item in values)
4512 CollectionChanged (true);
4516 public void AddRange (ListViewItemCollection items)
4519 throw new ArgumentNullException ("Argument cannot be null!", "items");
4521 ListViewItem[] itemArray = new ListViewItem[items.Count];
4522 items.CopyTo (itemArray,0);
4523 this.AddRange (itemArray);
4527 public virtual void Clear ()
4530 if (owner != null && owner.VirtualMode)
4531 throw new InvalidOperationException ();
4533 if (is_main_collection && owner != null) {
4534 owner.SetFocusedItem (-1);
4535 owner.h_scroll.Value = owner.v_scroll.Value = 0;
4537 foreach (ListViewItem item in list) {
4538 owner.item_control.CancelEdit (item);
4545 foreach (ListViewItem item in list)
4546 item.SetGroup (null);
4550 CollectionChanged (false);
4553 public bool Contains (ListViewItem item)
4555 return IndexOf (item) != -1;
4559 public virtual bool ContainsKey (string key)
4561 return IndexOfKey (key) != -1;
4565 public void CopyTo (Array dest, int index)
4567 list.CopyTo (dest, index);
4571 public ListViewItem [] Find (string key, bool searchAllSubitems)
4574 return new ListViewItem [0];
4576 List<ListViewItem> temp_list = new List<ListViewItem> ();
4578 for (int i = 0; i < list.Count; i++) {
4579 ListViewItem lvi = (ListViewItem) list [i];
4580 if (String.Compare (key, lvi.Name, true) == 0)
4581 temp_list.Add (lvi);
4584 ListViewItem [] retval = new ListViewItem [temp_list.Count];
4585 temp_list.CopyTo (retval);
4591 public IEnumerator GetEnumerator ()
4594 if (owner != null && owner.VirtualMode)
4595 throw new InvalidOperationException ();
4598 return list.GetEnumerator ();
4601 int IList.Add (object item)
4607 if (owner != null && owner.VirtualMode)
4608 throw new InvalidOperationException ();
4611 if (item is ListViewItem) {
4612 li = (ListViewItem) item;
4613 if (list.Contains (li))
4614 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
4616 if (li.ListView != null && li.ListView != owner)
4617 throw new ArgumentException ("Cannot add or insert the item '" + li.Text + "' in more than one place. You must first remove it from its current location or clone it.", "item");
4620 li = new ListViewItem (item.ToString ());
4623 result = list.Add (li);
4624 CollectionChanged (true);
4629 bool IList.Contains (object item)
4631 return Contains ((ListViewItem) item);
4634 int IList.IndexOf (object item)
4636 return IndexOf ((ListViewItem) item);
4639 void IList.Insert (int index, object item)
4641 if (item is ListViewItem)
4642 this.Insert (index, (ListViewItem) item);
4644 this.Insert (index, item.ToString ());
4647 void IList.Remove (object item)
4649 Remove ((ListViewItem) item);
4652 public int IndexOf (ListViewItem item)
4655 if (owner != null && owner.VirtualMode) {
4656 for (int i = 0; i < Count; i++)
4657 if (RetrieveVirtualItemFromOwner (i) == item)
4664 return list.IndexOf (item);
4668 public virtual int IndexOfKey (string key)
4670 if (key == null || key.Length == 0)
4673 for (int i = 0; i < Count; i++) {
4674 ListViewItem lvi = this [i];
4675 if (String.Compare (key, lvi.Name, true) == 0)
4683 public ListViewItem Insert (int index, ListViewItem item)
4685 if (index < 0 || index > list.Count)
4686 throw new ArgumentOutOfRangeException ("index");
4689 if (owner != null && owner.VirtualMode)
4690 throw new InvalidOperationException ();
4693 if (list.Contains (item))
4694 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
4696 if (item.ListView != null && item.ListView != owner)
4697 throw new ArgumentException ("Cannot add or insert the item '" + item.Text + "' in more than one place. You must first remove it from its current location or clone it.", "item");
4699 if (is_main_collection)
4703 if (item.Group != null)
4704 item.Group.Items.Remove (item);
4706 item.SetGroup (group);
4710 list.Insert (index, item);
4711 CollectionChanged (true);
4715 public ListViewItem Insert (int index, string text)
4717 return this.Insert (index, new ListViewItem (text));
4720 public ListViewItem Insert (int index, string text, int imageIndex)
4722 return this.Insert (index, new ListViewItem (text, imageIndex));
4726 public ListViewItem Insert (int index, string text, string imageKey)
4728 ListViewItem lvi = new ListViewItem (text, imageKey);
4729 return Insert (index, lvi);
4732 public virtual ListViewItem Insert (int index, string key, string text, int imageIndex)
4734 ListViewItem lvi = new ListViewItem (text, imageIndex);
4736 return Insert (index, lvi);
4739 public virtual ListViewItem Insert (int index, string key, string text, string imageKey)
4741 ListViewItem lvi = new ListViewItem (text, imageKey);
4743 return Insert (index, lvi);
4747 public virtual void Remove (ListViewItem item)
4750 if (owner != null && owner.VirtualMode)
4751 throw new InvalidOperationException ();
4753 if (!list.Contains (item))
4756 bool selection_changed = false;
4757 if (is_main_collection && owner != null) {
4758 selection_changed = owner.SelectedItems.Contains (item);
4759 owner.item_control.CancelEdit (item);
4764 if (is_main_collection)
4768 item.SetGroup (null);
4771 CollectionChanged (false);
4772 if (selection_changed && owner != null)
4773 owner.OnSelectedIndexChanged (EventArgs.Empty);
4776 public virtual void RemoveAt (int index)
4778 if (index < 0 || index >= Count)
4779 throw new ArgumentOutOfRangeException ("index");
4782 if (owner != null && owner.VirtualMode)
4783 throw new InvalidOperationException ();
4786 ListViewItem item = (ListViewItem) list [index];
4791 public virtual void RemoveByKey (string key)
4793 int idx = IndexOfKey (key);
4799 #endregion // Public Methods
4801 internal ListView Owner {
4811 internal ListViewGroup Group {
4821 void AddItem (ListViewItem value)
4823 if (list.Contains (value))
4824 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
4826 if (value.ListView != null && value.ListView != owner)
4827 throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value");
4828 if (is_main_collection)
4829 value.Owner = owner;
4832 if (value.Group != null)
4833 value.Group.Items.Remove (value);
4835 value.SetGroup (group);
4842 void CollectionChanged (bool sort)
4844 if (owner != null) {
4849 owner.Redraw (true);
4854 ListViewItem RetrieveVirtualItemFromOwner (int displayIndex)
4856 RetrieveVirtualItemEventArgs args = new RetrieveVirtualItemEventArgs (displayIndex);
4858 owner.OnRetrieveVirtualItem (args);
4859 ListViewItem retval = args.Item;
4860 retval.Owner = owner;
4861 retval.SetIndex (displayIndex);
4867 internal event CollectionChangedHandler Changed;
4869 internal void Sort (IComparer comparer)
4871 list.Sort (comparer);
4875 internal void OnChange ()
4877 if (Changed != null)
4880 } // ListViewItemCollection
4883 // In normal mode, the selection information resides in the Items,
4884 // making SelectedIndexCollection.List read-only
4886 // In virtual mode, SelectedIndexCollection directly saves the selection
4887 // information, instead of getting it from Items, making List read-and-write
4888 public class SelectedIndexCollection : IList, ICollection, IEnumerable
4890 private readonly ListView owner;
4891 private ArrayList list;
4893 #region Public Constructor
4894 public SelectedIndexCollection (ListView owner)
4897 owner.Items.Changed += new CollectionChangedHandler (ItemsCollection_Changed);
4899 #endregion // Public Constructor
4901 #region Public Properties
4905 if (!owner.IsHandleCreated)
4912 public bool IsReadOnly {
4922 public int this [int index] {
4924 if (!owner.IsHandleCreated || index < 0 || index >= List.Count)
4925 throw new ArgumentOutOfRangeException ("index");
4927 return (int) List [index];
4931 bool ICollection.IsSynchronized {
4932 get { return false; }
4935 object ICollection.SyncRoot {
4936 get { return this; }
4939 bool IList.IsFixedSize {
4949 object IList.this [int index] {
4950 get { return this [index]; }
4951 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4953 #endregion // Public Properties
4955 #region Public Methods
4957 public int Add (int itemIndex)
4959 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
4960 throw new ArgumentOutOfRangeException ("index");
4962 if (owner.virtual_mode && !owner.IsHandleCreated)
4965 owner.Items [itemIndex].Selected = true;
4967 if (!owner.IsHandleCreated)
4981 if (!owner.IsHandleCreated)
4984 int [] indexes = (int []) List.ToArray (typeof (int));
4985 foreach (int index in indexes)
4986 owner.Items [index].Selected = false;
4989 public bool Contains (int selectedIndex)
4991 return IndexOf (selectedIndex) != -1;
4994 public void CopyTo (Array dest, int index)
4996 List.CopyTo (dest, index);
4999 public IEnumerator GetEnumerator ()
5001 return List.GetEnumerator ();
5004 int IList.Add (object value)
5006 throw new NotSupportedException ("Add operation is not supported.");
5014 bool IList.Contains (object selectedIndex)
5016 if (!(selectedIndex is int))
5018 return Contains ((int) selectedIndex);
5021 int IList.IndexOf (object selectedIndex)
5023 if (!(selectedIndex is int))
5025 return IndexOf ((int) selectedIndex);
5028 void IList.Insert (int index, object value)
5030 throw new NotSupportedException ("Insert operation is not supported.");
5033 void IList.Remove (object value)
5035 throw new NotSupportedException ("Remove operation is not supported.");
5038 void IList.RemoveAt (int index)
5040 throw new NotSupportedException ("RemoveAt operation is not supported.");
5043 public int IndexOf (int selectedIndex)
5045 if (!owner.IsHandleCreated)
5048 return List.IndexOf (selectedIndex);
5052 public void Remove (int itemIndex)
5054 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
5055 throw new ArgumentOutOfRangeException ("itemIndex");
5057 owner.Items [itemIndex].Selected = false;
5060 #endregion // Public Methods
5062 internal ArrayList List {
5065 list = new ArrayList ();
5067 if (!owner.VirtualMode)
5069 for (int i = 0; i < owner.Items.Count; i++) {
5070 if (owner.Items [i].Selected)
5078 internal void Reset ()
5080 // force re-population of list
5082 if (!owner.VirtualMode)
5087 private void ItemsCollection_Changed ()
5093 internal void RemoveIndex (int index)
5095 int idx = List.BinarySearch (index);
5097 List.RemoveAt (idx);
5100 // actually store index in the collection
5101 // also, keep the collection sorted, as .Net does
5102 internal void InsertIndex (int index)
5105 int iMax = List.Count - 1;
5106 while (iMin <= iMax) {
5107 int iMid = (iMin + iMax) / 2;
5108 int current_index = (int) List [iMid];
5110 if (current_index == index)
5111 return; // Already added
5112 if (current_index > index)
5118 List.Insert (iMin, index);
5122 } // SelectedIndexCollection
5124 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
5126 private readonly ListView owner;
5128 #region Public Constructor
5129 public SelectedListViewItemCollection (ListView owner)
5133 #endregion // Public Constructor
5135 #region Public Properties
5139 return owner.SelectedIndices.Count;
5143 public bool IsReadOnly {
5144 get { return true; }
5147 public ListViewItem this [int index] {
5149 if (!owner.IsHandleCreated || index < 0 || index >= Count)
5150 throw new ArgumentOutOfRangeException ("index");
5152 int item_index = owner.SelectedIndices [index];
5153 return owner.Items [item_index];
5158 public virtual ListViewItem this [string key] {
5160 int idx = IndexOfKey (key);
5169 bool ICollection.IsSynchronized {
5170 get { return false; }
5173 object ICollection.SyncRoot {
5174 get { return this; }
5177 bool IList.IsFixedSize {
5178 get { return true; }
5181 object IList.this [int index] {
5182 get { return this [index]; }
5183 set { throw new NotSupportedException ("SetItem operation is not supported."); }
5185 #endregion // Public Properties
5187 #region Public Methods
5188 public void Clear ()
5190 owner.SelectedIndices.Clear ();
5193 public bool Contains (ListViewItem item)
5195 return IndexOf (item) != -1;
5199 public virtual bool ContainsKey (string key)
5201 return IndexOfKey (key) != -1;
5205 public void CopyTo (Array dest, int index)
5207 if (!owner.IsHandleCreated)
5209 if (index > Count) // Throws ArgumentException instead of IOOR exception
5210 throw new ArgumentException ("index");
5212 for (int i = 0; i < Count; i++)
5213 dest.SetValue (this [i], index++);
5216 public IEnumerator GetEnumerator ()
5218 if (!owner.IsHandleCreated)
5219 return (new ListViewItem [0]).GetEnumerator ();
5221 ListViewItem [] items = new ListViewItem [Count];
5222 for (int i = 0; i < Count; i++)
5223 items [i] = this [i];
5225 return items.GetEnumerator ();
5228 int IList.Add (object value)
5230 throw new NotSupportedException ("Add operation is not supported.");
5233 bool IList.Contains (object item)
5235 if (!(item is ListViewItem))
5237 return Contains ((ListViewItem) item);
5240 int IList.IndexOf (object item)
5242 if (!(item is ListViewItem))
5244 return IndexOf ((ListViewItem) item);
5247 void IList.Insert (int index, object value)
5249 throw new NotSupportedException ("Insert operation is not supported.");
5252 void IList.Remove (object value)
5254 throw new NotSupportedException ("Remove operation is not supported.");
5257 void IList.RemoveAt (int index)
5259 throw new NotSupportedException ("RemoveAt operation is not supported.");
5262 public int IndexOf (ListViewItem item)
5264 if (!owner.IsHandleCreated)
5267 for (int i = 0; i < Count; i++)
5268 if (this [i] == item)
5275 public virtual int IndexOfKey (string key)
5277 if (!owner.IsHandleCreated || key == null || key.Length == 0)
5280 for (int i = 0; i < Count; i++) {
5281 ListViewItem item = this [i];
5282 if (String.Compare (item.Name, key, true) == 0)
5289 #endregion // Public Methods
5291 } // SelectedListViewItemCollection
5293 internal delegate void CollectionChangedHandler ();
5295 struct ItemMatrixLocation
5300 public ItemMatrixLocation (int row, int col)
5327 #endregion // Subclasses
5329 protected override void OnResize (EventArgs e)
5334 protected override void OnMouseLeave (EventArgs e)
5336 base.OnMouseLeave (e);
5340 // ColumnReorder event
5342 static object ColumnReorderedEvent = new object ();
5343 public event ColumnReorderedEventHandler ColumnReordered {
5344 add { Events.AddHandler (ColumnReorderedEvent, value); }
5345 remove { Events.RemoveHandler (ColumnReorderedEvent, value); }
5348 protected virtual void OnColumnReordered (ColumnReorderedEventArgs e)
5350 ColumnReorderedEventHandler creh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
5357 // ColumnWidthChanged
5359 static object ColumnWidthChangedEvent = new object ();
5360 public event ColumnWidthChangedEventHandler ColumnWidthChanged {
5361 add { Events.AddHandler (ColumnWidthChangedEvent, value); }
5362 remove { Events.RemoveHandler (ColumnWidthChangedEvent, value); }
5365 protected virtual void OnColumnWidthChanged (ColumnWidthChangedEventArgs e)
5367 ColumnWidthChangedEventHandler eh = (ColumnWidthChangedEventHandler) (Events[ColumnWidthChangedEvent]);
5372 void RaiseColumnWidthChanged (int resize_column)
5374 ColumnWidthChangedEventArgs n = new ColumnWidthChangedEventArgs (resize_column);
5376 OnColumnWidthChanged (n);
5380 // ColumnWidthChanging
5382 static object ColumnWidthChangingEvent = new object ();
5383 public event ColumnWidthChangingEventHandler ColumnWidthChanging {
5384 add { Events.AddHandler (ColumnWidthChangingEvent, value); }
5385 remove { Events.RemoveHandler (ColumnWidthChangingEvent, value); }
5388 protected virtual void OnColumnWidthChanging (ColumnWidthChangingEventArgs e)
5390 ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
5396 // 2.0 profile based implementation
5398 bool CanProceedWithResize (ColumnHeader col, int width)
5400 ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
5404 ColumnWidthChangingEventArgs changing = new ColumnWidthChangingEventArgs (col.Index, width);
5405 cwceh (this, changing);
5406 return !changing.Cancel;
5410 // 1.0 profile based implementation
5412 bool CanProceedWithResize (ColumnHeader col, int width)
5417 void RaiseColumnWidthChanged (int resize_column)