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)
27 // Carlos Alberto Cortez <calberto.cortez@gmail.com>
34 using System.Collections;
35 using System.ComponentModel;
36 using System.ComponentModel.Design;
38 using System.Runtime.InteropServices;
39 using System.Globalization;
41 using System.Collections.Generic;
44 namespace System.Windows.Forms
46 [DefaultEvent ("SelectedIndexChanged")]
47 [DefaultProperty ("Items")]
48 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
50 [ClassInterface (ClassInterfaceType.AutoDispatch)]
52 [Docking (DockingBehavior.Ask)]
54 public class ListView : Control
56 private ItemActivation activation = ItemActivation.Standard;
57 private ListViewAlignment alignment = ListViewAlignment.Top;
58 private bool allow_column_reorder;
59 private bool auto_arrange = true;
60 private bool check_boxes;
61 private readonly CheckedIndexCollection checked_indices;
62 private readonly CheckedListViewItemCollection checked_items;
63 private readonly ColumnHeaderCollection columns;
64 internal int focused_item_index = -1;
65 private bool full_row_select;
66 private bool grid_lines;
67 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
68 private bool hide_selection = true;
69 private bool hover_selection;
70 private IComparer item_sorter;
71 private readonly ListViewItemCollection items;
73 private readonly ListViewGroupCollection groups;
74 private bool owner_draw;
75 private bool show_groups = true;
77 private bool label_edit;
78 private bool label_wrap = true;
79 private bool multiselect = true;
80 private bool scrollable = true;
81 private bool hover_pending;
82 private readonly SelectedIndexCollection selected_indices;
83 private readonly SelectedListViewItemCollection selected_items;
84 private SortOrder sort_order = SortOrder.None;
85 private ImageList state_image_list;
86 internal bool updating;
87 private View view = View.LargeIcon;
88 private int layout_wd; // We might draw more than our client area
89 private int layout_ht; // therefore we need to have these two.
90 internal HeaderControl header_control;
91 internal ItemControl item_control;
92 internal ScrollBar h_scroll; // used for scrolling horizontally
93 internal ScrollBar v_scroll; // used for scrolling vertically
94 internal int h_marker; // Position markers for scrolling
95 internal int v_marker;
96 private int keysearch_tickcnt;
97 private string keysearch_text;
98 static private readonly int keysearch_keydelay = 1000;
99 private int[] reordered_column_indices;
100 private int[] reordered_items_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 custom_column_width; // used when using Columns with SmallIcon/List views
105 private int hot_item_index = -1;
107 private bool hot_tracking;
108 private ListViewInsertionMark insertion_mark;
109 private bool show_item_tooltips;
110 private ToolTip item_tooltip;
111 private Size tile_size;
112 private bool virtual_mode;
113 private int virtual_list_size;
114 private bool right_to_left_layout;
117 // internal variables
118 internal ImageList large_image_list;
119 internal ImageList small_image_list;
120 internal Size text_size = Size.Empty;
123 static object AfterLabelEditEvent = new object ();
124 static object BeforeLabelEditEvent = new object ();
125 static object ColumnClickEvent = new object ();
126 static object ItemActivateEvent = new object ();
127 static object ItemCheckEvent = new object ();
128 static object ItemDragEvent = new object ();
129 static object SelectedIndexChangedEvent = new object ();
131 static object DrawColumnHeaderEvent = new object();
132 static object DrawItemEvent = new object();
133 static object DrawSubItemEvent = new object();
134 static object ItemCheckedEvent = new object ();
135 static object ItemMouseHoverEvent = new object ();
136 static object ItemSelectionChangedEvent = new object ();
137 static object CacheVirtualItemsEvent = new object ();
138 static object RetrieveVirtualItemEvent = new object ();
139 static object RightToLeftLayoutChangedEvent = new object ();
140 static object SearchForVirtualItemEvent = new object ();
141 static object VirtualItemsSelectionRangeChangedEvent = new object ();
144 public event LabelEditEventHandler AfterLabelEdit {
145 add { Events.AddHandler (AfterLabelEditEvent, value); }
146 remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
151 [EditorBrowsable (EditorBrowsableState.Never)]
152 public new event EventHandler BackgroundImageChanged {
153 add { base.BackgroundImageChanged += value; }
154 remove { base.BackgroundImageChanged -= value; }
160 [EditorBrowsable (EditorBrowsableState.Never)]
161 public new event EventHandler BackgroundImageLayoutChanged {
162 add { base.BackgroundImageLayoutChanged += value; }
163 remove { base.BackgroundImageLayoutChanged -= value; }
167 public event LabelEditEventHandler BeforeLabelEdit {
168 add { Events.AddHandler (BeforeLabelEditEvent, value); }
169 remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
172 public event ColumnClickEventHandler ColumnClick {
173 add { Events.AddHandler (ColumnClickEvent, value); }
174 remove { Events.RemoveHandler (ColumnClickEvent, value); }
178 public event DrawListViewColumnHeaderEventHandler DrawColumnHeader {
179 add { Events.AddHandler(DrawColumnHeaderEvent, value); }
180 remove { Events.RemoveHandler(DrawColumnHeaderEvent, value); }
183 public event DrawListViewItemEventHandler DrawItem {
184 add { Events.AddHandler(DrawItemEvent, value); }
185 remove { Events.RemoveHandler(DrawItemEvent, value); }
188 public event DrawListViewSubItemEventHandler DrawSubItem {
189 add { Events.AddHandler(DrawSubItemEvent, value); }
190 remove { Events.RemoveHandler(DrawSubItemEvent, value); }
194 public event EventHandler ItemActivate {
195 add { Events.AddHandler (ItemActivateEvent, value); }
196 remove { Events.RemoveHandler (ItemActivateEvent, value); }
199 public event ItemCheckEventHandler ItemCheck {
200 add { Events.AddHandler (ItemCheckEvent, value); }
201 remove { Events.RemoveHandler (ItemCheckEvent, value); }
205 public event ItemCheckedEventHandler ItemChecked {
206 add { Events.AddHandler (ItemCheckedEvent, value); }
207 remove { Events.RemoveHandler (ItemCheckedEvent, value); }
211 public event ItemDragEventHandler ItemDrag {
212 add { Events.AddHandler (ItemDragEvent, value); }
213 remove { Events.RemoveHandler (ItemDragEvent, value); }
217 public event ListViewItemMouseHoverEventHandler ItemMouseHover {
218 add { Events.AddHandler (ItemMouseHoverEvent, value); }
219 remove { Events.RemoveHandler (ItemMouseHoverEvent, value); }
222 public event ListViewItemSelectionChangedEventHandler ItemSelectionChanged {
223 add { Events.AddHandler (ItemSelectionChangedEvent, value); }
224 remove { Events.RemoveHandler (ItemSelectionChangedEvent, value); }
228 [EditorBrowsable (EditorBrowsableState.Never)]
229 public new event EventHandler PaddingChanged {
230 add { base.PaddingChanged += value; }
231 remove { base.PaddingChanged -= value; }
236 [EditorBrowsable (EditorBrowsableState.Never)]
237 public new event PaintEventHandler Paint {
238 add { base.Paint += value; }
239 remove { base.Paint -= value; }
242 public event EventHandler SelectedIndexChanged {
243 add { Events.AddHandler (SelectedIndexChangedEvent, value); }
244 remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
248 [EditorBrowsable (EditorBrowsableState.Never)]
249 public new event EventHandler TextChanged {
250 add { base.TextChanged += value; }
251 remove { base.TextChanged -= value; }
255 public event CacheVirtualItemsEventHandler CacheVirtualItems {
256 add { Events.AddHandler (CacheVirtualItemsEvent, value); }
257 remove { Events.RemoveHandler (CacheVirtualItemsEvent, value); }
260 public event RetrieveVirtualItemEventHandler RetrieveVirtualItem {
261 add { Events.AddHandler (RetrieveVirtualItemEvent, value); }
262 remove { Events.RemoveHandler (RetrieveVirtualItemEvent, value); }
265 public event EventHandler RightToLeftLayoutChanged {
266 add { Events.AddHandler (RightToLeftLayoutChangedEvent, value); }
267 remove { Events.RemoveHandler (RightToLeftLayoutChangedEvent, value); }
270 public event SearchForVirtualItemEventHandler SearchForVirtualItem {
271 add { Events.AddHandler (SearchForVirtualItemEvent, value); }
272 remove { Events.AddHandler (SearchForVirtualItemEvent, value); }
275 public event ListViewVirtualItemsSelectionRangeChangedEventHandler VirtualItemsSelectionRangeChanged {
276 add { Events.AddHandler (VirtualItemsSelectionRangeChangedEvent, value); }
277 remove { Events.RemoveHandler (VirtualItemsSelectionRangeChangedEvent, value); }
283 #region Public Constructors
286 background_color = ThemeEngine.Current.ColorWindow;
288 groups = new ListViewGroupCollection (this);
290 items = new ListViewItemCollection (this);
291 items.Changed += new CollectionChangedHandler (OnItemsChanged);
292 checked_indices = new CheckedIndexCollection (this);
293 checked_items = new CheckedListViewItemCollection (this);
294 columns = new ColumnHeaderCollection (this);
295 foreground_color = SystemColors.WindowText;
296 selected_indices = new SelectedIndexCollection (this);
297 selected_items = new SelectedListViewItemCollection (this);
298 items_location = new Point [16];
299 items_matrix_location = new ItemMatrixLocation [16];
300 reordered_items_indices = new int [16];
302 item_tooltip = new ToolTip ();
303 item_tooltip.Active = false;
304 insertion_mark = new ListViewInsertionMark (this);
307 InternalBorderStyle = BorderStyle.Fixed3D;
309 header_control = new HeaderControl (this);
310 header_control.Visible = false;
311 Controls.AddImplicit (header_control);
313 item_control = new ItemControl (this);
314 Controls.AddImplicit (item_control);
316 h_scroll = new ImplicitHScrollBar ();
317 Controls.AddImplicit (this.h_scroll);
319 v_scroll = new ImplicitVScrollBar ();
320 Controls.AddImplicit (this.v_scroll);
322 h_marker = v_marker = 0;
323 keysearch_tickcnt = 0;
325 // scroll bars are disabled initially
326 h_scroll.Visible = false;
327 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
328 v_scroll.Visible = false;
329 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
332 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
333 SizeChanged += new EventHandler (ListView_SizeChanged);
334 GotFocus += new EventHandler (FocusChanged);
335 LostFocus += new EventHandler (FocusChanged);
336 MouseWheel += new MouseEventHandler(ListView_MouseWheel);
337 MouseEnter += new EventHandler (ListView_MouseEnter);
338 Invalidated += new InvalidateEventHandler (ListView_Invalidated);
341 BackgroundImageTiled = false;
344 this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
346 | ControlStyles.UseTextForAccessibility
350 #endregion // Public Constructors
352 #region Private Internal Properties
353 internal Size CheckBoxSize {
355 if (this.check_boxes) {
356 if (this.state_image_list != null)
357 return this.state_image_list.ImageSize;
359 return ThemeEngine.Current.ListViewCheckBoxSize;
365 internal Size ItemSize {
367 if (view != View.Details)
370 Size size = new Size ();
371 size.Height = item_size.Height;
372 for (int i = 0; i < columns.Count; i++)
373 size.Width += columns [i].Wd;
382 internal int HotItemIndex {
384 return hot_item_index;
387 hot_item_index = value;
392 internal bool UsingGroups {
394 return show_groups && groups.Count > 0 && view != View.List &&
395 Application.VisualStylesEnabled;
400 internal override bool ScaleChildrenInternal {
401 get { return false; }
404 internal bool UseCustomColumnWidth {
406 return (view == View.List || view == View.SmallIcon) && columns.Count > 0;
410 internal ColumnHeader EnteredColumnHeader {
412 return header_control.EnteredColumnHeader;
415 #endregion // Private Internal Properties
417 #region Protected Properties
418 protected override CreateParams CreateParams {
419 get { return base.CreateParams; }
422 protected override Size DefaultSize {
423 get { return ThemeEngine.Current.ListViewDefaultSize; }
426 protected override bool DoubleBuffered {
428 return base.DoubleBuffered;
431 base.DoubleBuffered = value;
435 #endregion // Protected Properties
437 #region Public Instance Properties
438 [DefaultValue (ItemActivation.Standard)]
439 public ItemActivation Activation {
440 get { return activation; }
442 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
443 value != ItemActivation.TwoClick) {
444 throw new InvalidEnumArgumentException (string.Format
445 ("Enum argument value '{0}' is not valid for Activation", value));
448 if (hot_tracking && value != ItemActivation.OneClick)
449 throw new ArgumentException ("When HotTracking is on, activation must be ItemActivation.OneClick");
456 [DefaultValue (ListViewAlignment.Top)]
458 public ListViewAlignment Alignment {
459 get { return alignment; }
461 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
462 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
463 throw new InvalidEnumArgumentException (string.Format
464 ("Enum argument value '{0}' is not valid for Alignment", value));
467 if (this.alignment != value) {
469 // alignment does not matter in Details/List views
470 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
476 [DefaultValue (false)]
477 public bool AllowColumnReorder {
478 get { return allow_column_reorder; }
479 set { allow_column_reorder = value; }
482 [DefaultValue (true)]
483 public bool AutoArrange {
484 get { return auto_arrange; }
486 if (auto_arrange != value) {
487 auto_arrange = value;
488 // autoarrange does not matter in Details/List views
489 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
495 public override Color BackColor {
497 if (background_color.IsEmpty)
498 return ThemeEngine.Current.ColorWindow;
500 return background_color;
503 background_color = value;
504 item_control.BackColor = value;
510 [EditorBrowsable (EditorBrowsableState.Never)]
511 public override Image BackgroundImage {
512 get { return base.BackgroundImage; }
513 set { base.BackgroundImage = value; }
519 [EditorBrowsable (EditorBrowsableState.Never)]
520 public override ImageLayout BackgroundImageLayout {
522 return base.BackgroundImageLayout;
525 base.BackgroundImageLayout = value;
529 [DefaultValue (false)]
530 public bool BackgroundImageTiled {
532 return item_control.BackgroundImageLayout == ImageLayout.Tile;
535 ImageLayout new_image_layout = value ? ImageLayout.Tile : ImageLayout.None;
536 if (new_image_layout == item_control.BackgroundImageLayout)
539 item_control.BackgroundImageLayout = new_image_layout;
544 [DefaultValue (BorderStyle.Fixed3D)]
546 public BorderStyle BorderStyle {
547 get { return InternalBorderStyle; }
548 set { InternalBorderStyle = value; }
551 [DefaultValue (false)]
552 public bool CheckBoxes {
553 get { return check_boxes; }
555 if (check_boxes != value) {
557 if (value && View == View.Tile)
558 throw new NotSupportedException ("CheckBoxes are not"
559 + " supported in Tile view. Choose a different"
560 + " view or set CheckBoxes to false.");
567 //UIA Framework: Event used by ListView to set/unset Toggle Pattern
568 OnUIACheckBoxesChanged ();
575 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
576 public CheckedIndexCollection CheckedIndices {
577 get { return checked_indices; }
581 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
582 public CheckedListViewItemCollection CheckedItems {
583 get { return checked_items; }
587 [Editor ("System.Windows.Forms.Design.ColumnHeaderCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
589 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
591 [MergableProperty (false)]
592 public ColumnHeaderCollection Columns {
593 get { return columns; }
597 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
598 public ListViewItem FocusedItem {
600 if (focused_item_index == -1)
603 return GetItemAtDisplayIndex (focused_item_index);
607 if (value == null || value.ListView != this ||
611 SetFocusedItem (value.DisplayIndex);
616 public override Color ForeColor {
618 if (foreground_color.IsEmpty)
619 return ThemeEngine.Current.ColorWindowText;
621 return foreground_color;
623 set { foreground_color = value; }
626 [DefaultValue (false)]
627 public bool FullRowSelect {
628 get { return full_row_select; }
630 if (full_row_select != value) {
631 full_row_select = value;
632 InvalidateSelection ();
637 [DefaultValue (false)]
638 public bool GridLines {
639 get { return grid_lines; }
641 if (grid_lines != value) {
648 [DefaultValue (ColumnHeaderStyle.Clickable)]
649 public ColumnHeaderStyle HeaderStyle {
650 get { return header_style; }
652 if (header_style == value)
656 case ColumnHeaderStyle.Clickable:
657 case ColumnHeaderStyle.Nonclickable:
658 case ColumnHeaderStyle.None:
661 throw new InvalidEnumArgumentException (string.Format
662 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
665 header_style = value;
666 if (view == View.Details)
671 [DefaultValue (true)]
672 public bool HideSelection {
673 get { return hide_selection; }
675 if (hide_selection != value) {
676 hide_selection = value;
677 InvalidateSelection ();
683 [DefaultValue (false)]
684 public bool HotTracking {
689 if (hot_tracking == value)
692 hot_tracking = value;
694 hover_selection = true;
695 activation = ItemActivation.OneClick;
701 [DefaultValue (false)]
702 public bool HoverSelection {
703 get { return hover_selection; }
706 if (hot_tracking && value == false)
707 throw new ArgumentException ("When HotTracking is on, hover selection must be true");
709 hover_selection = value;
714 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
716 public ListViewInsertionMark InsertionMark {
718 return insertion_mark;
724 [Editor ("System.Windows.Forms.Design.ListViewItemCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
726 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
728 [MergableProperty (false)]
729 public ListViewItemCollection Items {
730 get { return items; }
733 [DefaultValue (false)]
734 public bool LabelEdit {
735 get { return label_edit; }
737 if (value != label_edit) {
741 // UIA Framework: Event used by Value Pattern in ListView.ListItem provider
742 OnUIALabelEditChanged ();
749 [DefaultValue (true)]
751 public bool LabelWrap {
752 get { return label_wrap; }
754 if (label_wrap != value) {
761 [DefaultValue (null)]
762 public ImageList LargeImageList {
763 get { return large_image_list; }
765 large_image_list = value;
771 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
772 public IComparer ListViewItemSorter {
774 if (View != View.SmallIcon && View != View.LargeIcon && item_sorter is ItemComparer)
779 if (item_sorter != value) {
786 [DefaultValue (true)]
787 public bool MultiSelect {
788 get { return multiselect; }
790 if (value != multiselect) {
794 // UIA Framework: Event used by Selection Pattern in ListView.ListItem provider
795 OnUIAMultiSelectChanged ();
803 [DefaultValue(false)]
804 public bool OwnerDraw {
805 get { return owner_draw; }
813 [EditorBrowsable (EditorBrowsableState.Never)]
814 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
815 public new Padding Padding {
820 base.Padding = value;
824 [MonoTODO ("RTL not supported")]
826 [DefaultValue (false)]
827 public virtual bool RightToLeftLayout {
828 get { return right_to_left_layout; }
830 if (right_to_left_layout != value) {
831 right_to_left_layout = value;
832 OnRightToLeftLayoutChanged (EventArgs.Empty);
838 [DefaultValue (true)]
839 public bool Scrollable {
840 get { return scrollable; }
842 if (scrollable != value) {
850 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
851 public SelectedIndexCollection SelectedIndices {
852 get { return selected_indices; }
856 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
857 public SelectedListViewItemCollection SelectedItems {
858 get { return selected_items; }
863 public bool ShowGroups {
864 get { return show_groups; }
866 if (show_groups != value) {
870 // UIA Framework: Used to update a11y Tree
871 OnUIAShowGroupsChanged ();
876 [LocalizableAttribute (true)]
877 [MergableProperty (false)]
878 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
879 [Editor ("System.Windows.Forms.Design.ListViewGroupCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
880 public ListViewGroupCollection Groups {
881 get { return groups; }
884 [DefaultValue (false)]
885 public bool ShowItemToolTips {
887 return show_item_tooltips;
890 show_item_tooltips = value;
891 item_tooltip.Active = false;
896 [DefaultValue (null)]
897 public ImageList SmallImageList {
898 get { return small_image_list; }
900 small_image_list = value;
905 [DefaultValue (SortOrder.None)]
906 public SortOrder Sorting {
907 get { return sort_order; }
909 if (!Enum.IsDefined (typeof (SortOrder), value)) {
910 throw new InvalidEnumArgumentException ("value", (int) value,
914 if (sort_order == value)
920 if (virtual_mode) // Sorting is not allowed in virtual mode
924 if (value == SortOrder.None) {
925 if (item_sorter != null) {
926 // ListViewItemSorter should never be reset for SmallIcon
927 // and LargeIcon view
928 if (View != View.SmallIcon && View != View.LargeIcon)
932 // in .NET 1.1, only internal IComparer would be
934 if (item_sorter is ItemComparer)
940 if (item_sorter == null)
941 item_sorter = new ItemComparer (value);
942 if (item_sorter is ItemComparer) {
944 item_sorter = new ItemComparer (value);
946 // in .NET 1.1, the sort order is not updated for
947 // SmallIcon and LargeIcon views if no custom IComparer
949 if (View != View.SmallIcon && View != View.LargeIcon)
950 item_sorter = new ItemComparer (value);
958 private void OnImageListChanged (object sender, EventArgs args)
960 item_control.Invalidate ();
963 [DefaultValue (null)]
964 public ImageList StateImageList {
965 get { return state_image_list; }
967 if (state_image_list == value)
970 if (state_image_list != null)
971 state_image_list.Images.Changed -= new EventHandler (OnImageListChanged);
973 state_image_list = value;
975 if (state_image_list != null)
976 state_image_list.Images.Changed += new EventHandler (OnImageListChanged);
984 [EditorBrowsable (EditorBrowsableState.Never)]
985 public override string Text {
986 get { return base.Text; }
988 if (value == base.Text)
998 public Size TileSize {
1003 if (value.Width <= 0 || value.Height <= 0)
1004 throw new ArgumentOutOfRangeException ("value");
1007 if (view == View.Tile)
1014 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1015 public ListViewItem TopItem {
1018 if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
1019 throw new InvalidOperationException ("Cannot get the top item in LargeIcon, SmallIcon or Tile view.");
1022 if (this.items.Count == 0)
1024 // if contents are not scrolled
1025 // it is the first item
1026 else if (h_marker == 0 && v_marker == 0)
1027 return this.items [0];
1028 // do a hit test for the scrolled position
1030 for (int i = 0; i < items.Count; i++) {
1031 Point item_loc = GetItemLocation (i);
1032 if (item_loc.X >= 0 && item_loc.Y >= 0)
1040 if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
1041 throw new InvalidOperationException ("Cannot set the top item in LargeIcon, SmallIcon or Tile view.");
1043 // .Net doesn't throw any exception in the cases below
1044 if (value == null || value.ListView != this)
1047 EnsureVisible (value.Index);
1053 [EditorBrowsable (EditorBrowsableState.Advanced)]
1054 [DefaultValue (true)]
1056 [MonoInternalNote ("Stub, not implemented")]
1057 public bool UseCompatibleStateImageBehavior {
1066 [DefaultValue (View.LargeIcon)]
1068 get { return view; }
1070 if (!Enum.IsDefined (typeof (View), value))
1071 throw new InvalidEnumArgumentException ("value", (int) value,
1074 if (view != value) {
1076 if (CheckBoxes && value == View.Tile)
1077 throw new NotSupportedException ("CheckBoxes are not"
1078 + " supported in Tile view. Choose a different"
1079 + " view or set CheckBoxes to false.");
1082 h_scroll.Value = v_scroll.Value = 0;
1087 // UIA Framework: Event used to update UIA Tree.
1088 OnUIAViewChanged ();
1095 [DefaultValue (false)]
1096 [RefreshProperties (RefreshProperties.Repaint)]
1097 public bool VirtualMode {
1099 return virtual_mode;
1102 if (virtual_mode == value)
1105 if (!virtual_mode && items.Count > 0)
1106 throw new InvalidOperationException ();
1108 virtual_mode = value;
1114 [RefreshProperties (RefreshProperties.Repaint)]
1115 public int VirtualListSize {
1117 return virtual_list_size;
1121 throw new ArgumentException ("value");
1123 if (virtual_list_size == value)
1126 virtual_list_size = value;
1128 selected_indices.Reset ();
1134 #endregion // Public Instance Properties
1136 #region Internal Methods Properties
1138 internal int FirstVisibleIndex {
1141 if (this.items.Count == 0)
1144 if (h_marker == 0 && v_marker == 0)
1147 Size item_size = ItemSize;
1148 for (int i = 0; i < items.Count; i++) {
1149 Rectangle item_rect = new Rectangle (GetItemLocation (i), item_size);
1150 if (item_rect.Right >= 0 && item_rect.Bottom >= 0)
1159 internal int LastVisibleIndex {
1161 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
1162 if (View == View.List || Alignment == ListViewAlignment.Left) {
1163 if (GetItemLocation (i).X > item_control.ClientRectangle.Right)
1166 if (GetItemLocation (i).Y > item_control.ClientRectangle.Bottom)
1171 return Items.Count - 1;
1175 internal void OnSelectedIndexChanged ()
1177 if (IsHandleCreated)
1178 OnSelectedIndexChanged (EventArgs.Empty);
1181 internal int TotalWidth {
1182 get { return Math.Max (this.Width, this.layout_wd); }
1185 internal int TotalHeight {
1186 get { return Math.Max (this.Height, this.layout_ht); }
1189 internal void Redraw (bool recalculate)
1191 // Avoid calculations when control is being updated
1195 // VirtualMode doesn't do any calculations until handle is created
1196 if (virtual_mode && !IsHandleCreated)
1202 CalculateListView (this.alignment);
1207 void InvalidateSelection ()
1209 foreach (int selected_index in SelectedIndices)
1210 items [selected_index].Invalidate ();
1213 const int text_padding = 15;
1215 internal Size GetChildColumnSize (int index)
1217 Size ret_size = Size.Empty;
1218 ColumnHeader col = this.columns [index];
1220 if (col.Width == -2) { // autosize = max(items, columnheader)
1221 Size size = Size.Ceiling (TextRenderer.MeasureString
1222 (col.Text, this.Font));
1223 size.Width += text_padding;
1224 ret_size = BiggestItem (index);
1225 if (size.Width > ret_size.Width)
1228 else { // -1 and all the values < -2 are put under one category
1229 ret_size = BiggestItem (index);
1230 // fall back to empty columns' width if no subitem is available for a column
1231 if (ret_size.IsEmpty) {
1232 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
1233 if (col.Text.Length > 0)
1234 ret_size.Height = Size.Ceiling (TextRenderer.MeasureString
1235 (col.Text, this.Font)).Height;
1237 ret_size.Height = this.Font.Height;
1241 ret_size.Height += text_padding;
1243 // adjust the size for icon and checkbox for 0th column
1245 ret_size.Width += (this.CheckBoxSize.Width + 4);
1246 if (this.small_image_list != null)
1247 ret_size.Width += this.small_image_list.ImageSize.Width;
1252 // Returns the size of biggest item text in a column
1253 // or the sum of the text and indent count if we are on 2.0
1254 private Size BiggestItem (int col)
1256 Size temp = Size.Empty;
1257 Size ret_size = Size.Empty;
1259 bool use_indent_count = small_image_list != null;
1261 // VirtualMode uses the first item text size
1262 if (virtual_mode && items.Count > 0) {
1263 ListViewItem item = items [0];
1264 ret_size = Size.Ceiling (TextRenderer.MeasureString (item.SubItems[col].Text,
1267 if (use_indent_count)
1268 ret_size.Width += item.IndentCount * small_image_list.ImageSize.Width;
1271 // 0th column holds the item text, we check the size of
1272 // the various subitems falling in that column and get
1273 // the biggest one's size.
1274 foreach (ListViewItem item in items) {
1275 if (col >= item.SubItems.Count)
1278 temp = Size.Ceiling (TextRenderer.MeasureString
1279 (item.SubItems [col].Text, Font));
1282 if (use_indent_count)
1283 temp.Width += item.IndentCount * small_image_list.ImageSize.Width;
1286 if (temp.Width > ret_size.Width)
1293 // adjustment for space in Details view
1294 if (!ret_size.IsEmpty && view == View.Details)
1295 ret_size.Width += ThemeEngine.Current.ListViewItemPaddingWidth;
1300 const int max_wrap_padding = 30;
1302 // Sets the size of the biggest item text as per the view
1303 private void CalcTextSize ()
1305 // clear the old value
1306 text_size = Size.Empty;
1308 if (items.Count == 0)
1311 text_size = BiggestItem (0);
1313 if (view == View.LargeIcon && this.label_wrap) {
1314 Size temp = Size.Empty;
1315 if (this.check_boxes)
1316 temp.Width += 2 * this.CheckBoxSize.Width;
1317 int icon_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1318 temp.Width += icon_w + max_wrap_padding;
1319 // wrapping is done for two lines only
1320 if (text_size.Width > temp.Width) {
1321 text_size.Width = temp.Width;
1322 text_size.Height *= 2;
1325 else if (view == View.List) {
1326 // in list view max text shown in determined by the
1327 // control width, even if scolling is enabled.
1328 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
1329 if (this.small_image_list != null)
1330 max_wd -= this.small_image_list.ImageSize.Width;
1332 if (text_size.Width > max_wd)
1333 text_size.Width = max_wd;
1336 // we do the default settings, if we have got 0's
1337 if (text_size.Height <= 0)
1338 text_size.Height = this.Font.Height;
1339 if (text_size.Width <= 0)
1340 text_size.Width = this.Width;
1342 // little adjustment
1343 text_size.Width += 2;
1344 text_size.Height += 2;
1347 private void Scroll (ScrollBar scrollbar, int delta)
1349 if (delta == 0 || !scrollbar.Visible)
1353 if (scrollbar == h_scroll)
1354 max = h_scroll.Maximum - item_control.Width;
1356 max = v_scroll.Maximum - item_control.Height;
1358 int val = scrollbar.Value + delta;
1361 else if (val < scrollbar.Minimum)
1362 val = scrollbar.Minimum;
1363 scrollbar.Value = val;
1366 private void CalculateScrollBars ()
1368 Rectangle client_area = ClientRectangle;
1369 int height = client_area.Height;
1370 int width = client_area.Width;
1373 h_scroll.Visible = false;
1374 v_scroll.Visible = false;
1375 item_control.Size = new Size (width, height);
1376 header_control.Width = width;
1380 // Don't calculate if the view is not displayable
1381 if (client_area.Height < 0 || client_area.Width < 0)
1384 // making a scroll bar visible might make
1385 // other scroll bar visible
1386 if (layout_wd > client_area.Right) {
1387 h_scroll.Visible = true;
1388 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
1389 v_scroll.Visible = true;
1391 v_scroll.Visible = false;
1392 } else if (layout_ht > client_area.Bottom) {
1393 v_scroll.Visible = true;
1394 if ((layout_wd + v_scroll.Width) > client_area.Right)
1395 h_scroll.Visible = true;
1397 h_scroll.Visible = false;
1399 h_scroll.Visible = false;
1400 v_scroll.Visible = false;
1404 if (h_scroll.is_visible) {
1405 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
1406 h_scroll.Minimum = 0;
1408 // if v_scroll is visible, adjust the maximum of the
1409 // h_scroll to account for the width of v_scroll
1410 if (v_scroll.Visible) {
1411 h_scroll.Maximum = layout_wd + v_scroll.Width;
1412 h_scroll.Width = client_area.Width - v_scroll.Width;
1415 h_scroll.Maximum = layout_wd;
1416 h_scroll.Width = client_area.Width;
1419 h_scroll.LargeChange = client_area.Width;
1420 h_scroll.SmallChange = item_size.Width + ThemeEngine.Current.ListViewHorizontalSpacing;
1421 height -= h_scroll.Height;
1424 if (v_scroll.is_visible) {
1425 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
1426 v_scroll.Minimum = 0;
1427 v_scroll.Maximum = layout_ht;
1429 // if h_scroll is visible, adjust the height of
1430 // v_scroll to account for the height of h_scroll
1431 if (h_scroll.Visible)
1432 v_scroll.Height = client_area.Height - h_scroll.Height;
1434 v_scroll.Height = client_area.Height;
1436 v_scroll.LargeChange = client_area.Height;
1437 v_scroll.SmallChange = Font.Height;
1438 width -= v_scroll.Width;
1441 item_control.Size = new Size (width, height);
1443 if (header_control.is_visible)
1444 header_control.Width = width;
1448 internal int GetReorderedColumnIndex (ColumnHeader column)
1450 if (reordered_column_indices == null)
1451 return column.Index;
1453 for (int i = 0; i < Columns.Count; i++)
1454 if (reordered_column_indices [i] == column.Index)
1461 internal ColumnHeader GetReorderedColumn (int index)
1463 if (reordered_column_indices == null)
1464 return Columns [index];
1466 return Columns [reordered_column_indices [index]];
1469 internal void ReorderColumn (ColumnHeader col, int index, bool fireEvent)
1473 ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
1475 ColumnReorderedEventArgs args = new ColumnReorderedEventArgs (col.Index, index, col);
1479 header_control.Invalidate ();
1480 item_control.Invalidate ();
1486 int column_count = Columns.Count;
1488 if (reordered_column_indices == null) {
1489 reordered_column_indices = new int [column_count];
1490 for (int i = 0; i < column_count; i++)
1491 reordered_column_indices [i] = i;
1494 if (reordered_column_indices [index] == col.Index)
1497 int[] curr = reordered_column_indices;
1498 int [] result = new int [column_count];
1500 for (int i = 0; i < column_count; i++) {
1501 if (curr_idx < column_count && curr [curr_idx] == col.Index)
1505 result [i] = col.Index;
1507 result [i] = curr [curr_idx++];
1510 ReorderColumns (result, true);
1513 internal void ReorderColumns (int [] display_indices, bool redraw)
1515 reordered_column_indices = display_indices;
1516 for (int i = 0; i < Columns.Count; i++) {
1517 ColumnHeader col = Columns [i];
1518 col.InternalDisplayIndex = reordered_column_indices [i];
1520 if (redraw && view == View.Details && IsHandleCreated) {
1522 header_control.Invalidate ();
1523 item_control.Invalidate ();
1527 internal void AddColumn (ColumnHeader newCol, int index, bool redraw)
1529 int column_count = Columns.Count;
1530 newCol.SetListView (this);
1532 int [] display_indices = new int [column_count];
1533 for (int i = 0; i < column_count; i++) {
1534 ColumnHeader col = Columns [i];
1536 display_indices [i] = index;
1538 int display_index = col.InternalDisplayIndex;
1539 if (display_index < index) {
1540 display_indices [i] = display_index;
1542 display_indices [i] = (display_index + 1);
1547 ReorderColumns (display_indices, redraw);
1551 Size LargeIconItemSize
1554 int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1555 int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
1556 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
1557 int w = Math.Max (text_size.Width, image_w);
1560 w += 2 + CheckBoxSize.Width;
1562 return new Size (w, h);
1566 Size SmallIconItemSize {
1568 int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
1569 int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1570 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
1571 int w = text_size.Width + image_w;
1574 w += 2 + CheckBoxSize.Width;
1576 return new Size (w, h);
1583 // Calculate tile size if needed
1584 // It appears that using Font.Size instead of a SizeF value can give us
1585 // a slightly better approach to the proportions defined in .Net
1586 if (tile_size == Size.Empty) {
1587 int image_w = LargeImageList == null ? 0 : LargeImageList.ImageSize.Width;
1588 int image_h = LargeImageList == null ? 0 : LargeImageList.ImageSize.Height;
1589 int w = (int)Font.Size * ThemeEngine.Current.ListViewTileWidthFactor + image_w + 4;
1590 int h = Math.Max ((int)Font.Size * ThemeEngine.Current.ListViewTileHeightFactor, image_h);
1592 tile_size = new Size (w, h);
1600 int GetDetailsItemHeight ()
1603 int checkbox_height = CheckBoxes ? CheckBoxSize.Height : 0;
1604 int small_image_height = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1605 item_height = Math.Max (checkbox_height, text_size.Height);
1606 item_height = Math.Max (item_height, small_image_height);
1610 void SetItemLocation (int index, int x, int y, int row, int col)
1612 Point old_location = items_location [index];
1613 if (old_location.X == x && old_location.Y == y)
1616 items_location [index] = new Point (x, y);
1617 items_matrix_location [index] = new ItemMatrixLocation (row, col);
1620 // Initial position matches item's position in ListViewItemCollection
1622 reordered_items_indices [index] = index;
1626 void ShiftItemsPositions (int from, int to, bool forward)
1629 for (int i = to + 1; i > from; i--) {
1630 reordered_items_indices [i] = reordered_items_indices [i - 1];
1632 ListViewItem item = items [reordered_items_indices [i]];
1634 item.DisplayIndex = i;
1638 for (int i = from - 1; i < to; i++) {
1639 reordered_items_indices [i] = reordered_items_indices [i + 1];
1641 ListViewItem item = items [reordered_items_indices [i]];
1643 item.DisplayIndex = i;
1649 internal void ChangeItemLocation (int display_index, Point new_pos)
1651 int new_display_index = GetDisplayIndexFromLocation (new_pos);
1652 if (new_display_index == display_index)
1655 int item_index = reordered_items_indices [display_index];
1656 ListViewItem item = items [item_index];
1658 bool forward = new_display_index < display_index;
1659 int index_from, index_to;
1661 index_from = new_display_index;
1662 index_to = display_index - 1;
1664 index_from = display_index + 1;
1665 index_to = new_display_index;
1668 ShiftItemsPositions (index_from, index_to, forward);
1670 reordered_items_indices [new_display_index] = item_index;
1673 item.DisplayIndex = new_display_index;
1677 int GetDisplayIndexFromLocation (Point loc)
1679 int display_index = -1;
1680 Rectangle item_area;
1683 if (loc.X < 0 || loc.Y < 0)
1686 // Adjustment to put in the next position refered by 'loc'
1687 loc.X -= item_size.Width / 2;
1691 for (int i = 0; i < items.Count; i++) {
1692 item_area = new Rectangle (GetItemLocation (i), item_size);
1693 item_area.Inflate (ThemeEngine.Current.ListViewHorizontalSpacing,
1694 ThemeEngine.Current.ListViewVerticalSpacing);
1696 if (item_area.Contains (loc)) {
1702 // Put in in last position
1703 if (display_index == -1)
1704 display_index = items.Count - 1;
1706 return display_index;
1709 // When using groups, the items with no group assigned
1710 // belong to the DefaultGroup
1711 int GetDefaultGroupItems ()
1714 foreach (ListViewItem item in items)
1715 if (item.Group == null)
1724 int[,] item_index_matrix;
1726 void CalculateRowsAndCols (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1728 Rectangle area = ClientRectangle;
1730 if (UseCustomColumnWidth)
1731 CalculateCustomColumnWidth ();
1734 // When groups are used the alignment is always top-aligned
1739 groups.DefaultGroup.ItemCount = GetDefaultGroupItems ();
1740 for (int i = 0; i < groups.InternalCount; i++) {
1741 ListViewGroup group = groups.GetInternalGroup (i);
1742 int items_in_group = group.GetActualItemCount ();
1744 if (items_in_group == 0)
1747 int group_cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
1748 if (group_cols <= 0)
1750 int group_rows = (int) Math.Ceiling ((double)items_in_group / (double)group_cols);
1752 group.starting_row = rows;
1753 group.rows = group_rows;
1754 group.starting_item = items;
1755 group.current_item = 0; // Reset layout
1757 cols = Math.Max (group_cols, cols);
1759 items += items_in_group;
1764 // Simple matrix if no groups are used
1766 rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(item_size.Height + y_spacing));
1769 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
1771 if (UseCustomColumnWidth)
1772 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width) / (double)(custom_column_width));
1774 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
1779 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
1783 item_index_matrix = new int [rows, cols];
1786 // When using custom column width, we look for the minimum one
1787 void CalculateCustomColumnWidth ()
1789 int min_width = Int32.MaxValue;
1790 for (int i = 0; i < columns.Count; i++) {
1791 int col_width = columns [i].Width;
1793 if (col_width < min_width)
1794 min_width = col_width;
1797 custom_column_width = min_width;
1800 void LayoutIcons (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1802 header_control.Visible = false;
1803 header_control.Size = Size.Empty;
1804 item_control.Visible = true;
1805 item_control.Location = Point.Empty;
1806 ItemSize = item_size; // Cache item size
1808 if (items.Count == 0)
1811 Size sz = item_size;
1813 bool using_groups = UsingGroups;
1816 CalculateRowsAndCols (sz, left_aligned, x_spacing, y_spacing);
1818 layout_wd = UseCustomColumnWidth ? cols * custom_column_width : cols * (sz.Width + x_spacing) - x_spacing;
1819 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
1822 CalculateGroupsLayout (sz, y_spacing, 0);
1825 int row = 0, col = 0;
1827 int display_index = 0;
1829 for (int i = 0; i < items.Count; i++) {
1832 ListViewGroup group = items [i].Group;
1834 group = groups.DefaultGroup;
1836 Point group_items_loc = group.items_area_location;
1837 int current_item = group.current_item++;
1838 int starting_row = group.starting_row;
1840 display_index = group.starting_item + current_item;
1841 row = (current_item / cols);
1842 col = current_item % cols;
1844 x = UseCustomColumnWidth ? col * custom_column_width : col * (item_size.Width + x_spacing);
1845 y = row * (item_size.Height + y_spacing) + group_items_loc.Y;
1847 SetItemLocation (display_index, x, y, row + starting_row, col);
1848 SetItemAtDisplayIndex (display_index, i);
1849 item_index_matrix [row + starting_row, col] = i;
1854 x = UseCustomColumnWidth ? col * custom_column_width : col * (item_size.Width + x_spacing);
1855 y = row * (item_size.Height + y_spacing);
1856 display_index = i; // Same as item index in Items
1858 SetItemLocation (i, x, y, row, col);
1859 item_index_matrix [row, col] = i;
1868 if (++col == cols) {
1878 ListViewItem item = items [i];
1880 item.DisplayIndex = display_index;
1882 item.SetPosition (new Point (x, y));
1889 item_control.Size = new Size (layout_wd, layout_ht);
1893 void CalculateGroupsLayout (Size item_size, int y_spacing, int y_origin)
1896 bool details = view == View.Details;
1898 for (int i = 0; i < groups.InternalCount; i++) {
1899 ListViewGroup group = groups.GetInternalGroup (i);
1900 if (group.ItemCount == 0)
1903 y += LayoutGroupHeader (group, y, item_size.Height, y_spacing, details ? group.ItemCount : group.rows);
1906 layout_ht = y; // Update height taking into account Groups' headers heights
1909 int LayoutGroupHeader (ListViewGroup group, int y_origin, int item_height, int y_spacing, int rows)
1911 Rectangle client_area = ClientRectangle;
1912 int header_height = text_size.Height + 10;
1914 group.HeaderBounds = new Rectangle (0, y_origin, client_area.Width - v_scroll.Width, header_height);
1915 group.items_area_location = new Point (0, y_origin + header_height);
1917 int items_area_height = ((item_height + y_spacing) * rows);
1918 return header_height + items_area_height + 10; // Add a small bottom margin
1921 void CalculateDetailsGroupItemsCount ()
1925 groups.DefaultGroup.ItemCount = GetDefaultGroupItems ();
1926 for (int i = 0; i < groups.InternalCount; i++) {
1927 ListViewGroup group = groups.GetInternalGroup (i);
1928 int items_in_group = group.GetActualItemCount ();
1930 if (items_in_group == 0)
1933 group.starting_item = items;
1934 group.current_item = 0; // Reset layout.
1935 items += items_in_group;
1940 void LayoutHeader ()
1943 for (int i = 0; i < Columns.Count; i++) {
1944 ColumnHeader col = GetReorderedColumn (i);
1947 col.CalcColumnHeader ();
1953 if (x < ClientRectangle.Width)
1954 x = ClientRectangle.Width;
1956 if (header_style == ColumnHeaderStyle.None) {
1957 header_control.Visible = false;
1958 header_control.Size = Size.Empty;
1959 layout_wd = ClientRectangle.Width;
1961 header_control.Width = x;
1962 header_control.Height = columns.Count > 0 ? columns [0].Ht : ThemeEngine.Current.ListViewGetHeaderHeight (this, Font);
1963 header_control.Visible = true;
1967 void LayoutDetails ()
1971 if (columns.Count == 0) {
1972 item_control.Visible = false;
1973 layout_wd = ClientRectangle.Width;
1974 layout_ht = ClientRectangle.Height;
1978 item_control.Visible = true;
1979 item_control.Location = Point.Empty;
1980 item_control.Width = ClientRectangle.Width;
1982 int item_height = GetDetailsItemHeight ();
1983 ItemSize = new Size (0, item_height); // We only cache Height for details view
1984 int y = header_control.Height;
1986 bool using_groups = UsingGroups;
1988 CalculateDetailsGroupItemsCount ();
1989 CalculateGroupsLayout (ItemSize, 2, y);
1993 for (int i = 0; i < items.Count; i++) {
1994 ListViewItem item = items [i];
1998 ListViewGroup group = item.Group;
2000 group = groups.DefaultGroup;
2002 int current_item = group.current_item++;
2003 Point group_items_loc = group.items_area_location;
2004 display_index = group.starting_item + current_item;
2006 y = current_item * (item_height + 2) + group_items_loc.Y;
2007 SetItemLocation (display_index, 0, y, 0, 0);
2008 SetItemAtDisplayIndex (display_index, i);
2009 item.SetPosition (new Point (0, y));
2014 SetItemLocation (i, 0, y, 0, 0);
2016 item.SetPosition (new Point (0, y));
2021 if (!virtual_mode) // Virtual mode sets Layout until draw time
2025 item.DisplayIndex = display_index;
2030 // some space for bottom gridline
2031 if (items.Count > 0 && grid_lines)
2035 if (!using_groups) // With groups it has been previously computed
2040 private void AdjustItemsPositionArray (int count)
2042 if (items_location.Length >= count)
2045 // items_location, items_matrix_location and reordered_items_indices must keep the same length
2046 count = Math.Max (count, items_location.Length * 2);
2047 items_location = new Point [count];
2048 items_matrix_location = new ItemMatrixLocation [count];
2049 reordered_items_indices = new int [count];
2052 private void CalculateListView (ListViewAlignment align)
2056 AdjustItemsPositionArray (items.Count);
2063 case View.SmallIcon:
2064 LayoutIcons (SmallIconItemSize, alignment == ListViewAlignment.Left,
2065 ThemeEngine.Current.ListViewHorizontalSpacing, 2);
2068 case View.LargeIcon:
2069 LayoutIcons (LargeIconItemSize, alignment == ListViewAlignment.Left,
2070 ThemeEngine.Current.ListViewHorizontalSpacing,
2071 ThemeEngine.Current.ListViewVerticalSpacing);
2075 LayoutIcons (SmallIconItemSize, true,
2076 ThemeEngine.Current.ListViewHorizontalSpacing, 2);
2080 if (!Application.VisualStylesEnabled)
2081 goto case View.LargeIcon;
2083 LayoutIcons (TileItemSize, alignment == ListViewAlignment.Left,
2084 ThemeEngine.Current.ListViewHorizontalSpacing,
2085 ThemeEngine.Current.ListViewVerticalSpacing);
2090 CalculateScrollBars ();
2093 internal Point GetItemLocation (int index)
2095 Point loc = items_location [index];
2096 loc.X -= h_marker; // Adjust to scroll
2102 internal int GetItemIndex (int display_index)
2104 return reordered_items_indices [display_index];
2107 internal ListViewItem GetItemAtDisplayIndex (int display_index)
2109 return items [reordered_items_indices [display_index]];
2112 internal void SetItemAtDisplayIndex (int display_index, int index)
2114 reordered_items_indices [display_index] = index;
2117 private bool KeySearchString (KeyEventArgs ke)
2119 int current_tickcnt = Environment.TickCount;
2120 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
2121 keysearch_text = string.Empty;
2124 if (!Char.IsLetterOrDigit ((char)ke.KeyCode))
2127 keysearch_text += (char)ke.KeyCode;
2128 keysearch_tickcnt = current_tickcnt;
2130 int prev_focused = FocusedItem == null ? 0 : FocusedItem.DisplayIndex;
2131 int start = prev_focused + 1 < Items.Count ? prev_focused + 1 : 0;
2133 ListViewItem item = FindItemWithText (keysearch_text, false, start, true, true);
2134 if (item != null && prev_focused != item.DisplayIndex) {
2135 selected_indices.Clear ();
2137 SetFocusedItem (item.DisplayIndex);
2138 item.Selected = true;
2139 EnsureVisible (GetItemIndex (item.DisplayIndex));
2145 private void OnItemsChanged ()
2147 ResetSearchString ();
2150 private void ResetSearchString ()
2152 keysearch_text = String.Empty;
2155 int GetAdjustedIndex (Keys key)
2159 if (View == View.Details) {
2162 result = FocusedItem.DisplayIndex - 1;
2165 result = FocusedItem.DisplayIndex + 1;
2166 if (result == items.Count)
2170 int last_index = LastVisibleIndex;
2171 Rectangle item_rect = new Rectangle (GetItemLocation (last_index), ItemSize);
2172 if (item_rect.Bottom > item_control.ClientRectangle.Bottom)
2174 if (FocusedItem.DisplayIndex == last_index) {
2175 if (FocusedItem.DisplayIndex < Items.Count - 1) {
2176 int page_size = item_control.Height / ItemSize.Height - 1;
2177 result = FocusedItem.DisplayIndex + page_size - 1;
2178 if (result >= Items.Count)
2179 result = Items.Count - 1;
2182 result = last_index;
2185 int first_index = FirstVisibleIndex;
2186 if (GetItemLocation (first_index).Y < 0)
2188 if (FocusedItem.DisplayIndex == first_index) {
2189 if (first_index > 0) {
2190 int page_size = item_control.Height / ItemSize.Height - 1;
2191 result = first_index - page_size + 1;
2196 result = first_index;
2202 ItemMatrixLocation item_matrix_location = items_matrix_location [FocusedItem.DisplayIndex];
2203 int row = item_matrix_location.Row;
2204 int col = item_matrix_location.Col;
2206 int adjusted_index = -1;
2212 adjusted_index = item_index_matrix [row, col - 1];
2216 if (col == (cols - 1))
2218 while (item_index_matrix [row, col + 1] == 0) {
2223 adjusted_index = item_index_matrix [row, col + 1];
2229 while (item_index_matrix [row - 1, col] == 0 && row != 1) {
2234 adjusted_index = item_index_matrix [row - 1, col];
2238 if (row == (rows - 1) || row == Items.Count - 1)
2240 while (item_index_matrix [row + 1, col] == 0) {
2245 adjusted_index = item_index_matrix [row + 1, col];
2252 return items [adjusted_index].DisplayIndex;
2255 ListViewItem selection_start;
2257 private bool SelectItems (ArrayList sel_items)
2259 bool changed = false;
2260 foreach (ListViewItem item in SelectedItems)
2261 if (!sel_items.Contains (item)) {
2262 item.Selected = false;
2265 foreach (ListViewItem item in sel_items)
2266 if (!item.Selected) {
2267 item.Selected = true;
2273 private void UpdateMultiSelection (int index, bool reselect)
2275 bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
2276 bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
2277 ListViewItem item = GetItemAtDisplayIndex (index);
2279 if (shift_pressed && selection_start != null) {
2280 ArrayList list = new ArrayList ();
2281 int start_index = selection_start.DisplayIndex;
2282 int start = Math.Min (start_index, index);
2283 int end = Math.Max (start_index, index);
2284 if (View == View.Details) {
2285 for (int i = start; i <= end; i++)
2286 list.Add (GetItemAtDisplayIndex (i));
2288 ItemMatrixLocation start_item_matrix_location = items_matrix_location [start];
2289 ItemMatrixLocation end_item_matrix_location = items_matrix_location [end];
2290 int left = Math.Min (start_item_matrix_location.Col, end_item_matrix_location.Col);
2291 int right = Math.Max (start_item_matrix_location.Col, end_item_matrix_location.Col);
2292 int top = Math.Min (start_item_matrix_location.Row, end_item_matrix_location.Row);
2293 int bottom = Math.Max (start_item_matrix_location.Row, end_item_matrix_location.Row);
2295 for (int i = 0; i < items.Count; i++) {
2296 ItemMatrixLocation item_matrix_loc = items_matrix_location [i];
2298 if (item_matrix_loc.Row >= top && item_matrix_loc.Row <= bottom &&
2299 item_matrix_loc.Col >= left && item_matrix_loc.Col <= right)
2300 list.Add (GetItemAtDisplayIndex (i));
2304 } else if (ctrl_pressed) {
2305 item.Selected = !item.Selected;
2306 selection_start = item;
2309 // do not unselect, and reselect the item
2310 foreach (int itemIndex in SelectedIndices) {
2311 if (index == itemIndex)
2313 items [itemIndex].Selected = false;
2316 SelectedItems.Clear ();
2317 item.Selected = true;
2319 selection_start = item;
2323 internal override bool InternalPreProcessMessage (ref Message msg)
2325 if (msg.Msg == (int)Msg.WM_KEYDOWN) {
2326 Keys key_data = (Keys)msg.WParam.ToInt32();
2328 HandleNavKeys (key_data);
2331 return base.InternalPreProcessMessage (ref msg);
2334 bool HandleNavKeys (Keys key_data)
2336 if (Items.Count == 0 || !item_control.Visible)
2339 if (FocusedItem == null)
2344 SelectIndex (Items.Count - 1);
2357 SelectIndex (GetAdjustedIndex (key_data));
2361 SelectIndex (focused_item_index);
2362 ToggleItemsCheckState ();
2365 if (selected_indices.Count > 0)
2366 OnItemActivate (EventArgs.Empty);
2376 void ToggleItemsCheckState ()
2381 // Don't modify check state if StateImageList has less than 2 elements
2382 if (StateImageList != null && StateImageList.Images.Count < 2)
2385 if (SelectedIndices.Count > 0) {
2386 for (int i = 0; i < SelectedIndices.Count; i++) {
2387 ListViewItem item = Items [SelectedIndices [i]];
2388 item.Checked = !item.Checked;
2393 if (FocusedItem != null) {
2394 FocusedItem.Checked = !FocusedItem.Checked;
2395 SelectIndex (FocusedItem.Index);
2399 void SelectIndex (int display_index)
2401 if (display_index == -1)
2405 UpdateMultiSelection (display_index, true);
2406 else if (!GetItemAtDisplayIndex (display_index).Selected)
2407 GetItemAtDisplayIndex (display_index).Selected = true;
2409 SetFocusedItem (display_index);
2410 EnsureVisible (GetItemIndex (display_index)); // Index in Items collection, not display index
2413 private void ListView_KeyDown (object sender, KeyEventArgs ke)
2415 if (ke.Handled || Items.Count == 0 || !item_control.Visible)
2418 if (ke.Alt || ke.Control)
2421 ke.Handled = KeySearchString (ke);
2424 private MouseEventArgs TranslateMouseEventArgs (MouseEventArgs args)
2426 Point loc = PointToClient (Control.MousePosition);
2427 return new MouseEventArgs (args.Button, args.Clicks, loc.X, loc.Y, args.Delta);
2430 internal class ItemControl : Control {
2433 ListViewItem clicked_item;
2434 ListViewItem last_clicked_item;
2435 bool hover_processed = false;
2436 bool checking = false;
2437 ListViewItem prev_hovered_item;
2439 ListViewItem prev_tooltip_item;
2442 Point drag_begin = new Point (-1, -1);
2443 internal int dragged_item_index = -1;
2445 ListViewLabelEditTextBox edit_text_box;
2446 internal ListViewItem edit_item;
2447 LabelEditEventArgs edit_args;
2449 public ItemControl (ListView owner)
2452 this.SetStyle (ControlStyles.DoubleBuffer, true);
2453 DoubleClick += new EventHandler(ItemsDoubleClick);
2454 MouseDown += new MouseEventHandler(ItemsMouseDown);
2455 MouseMove += new MouseEventHandler(ItemsMouseMove);
2456 MouseHover += new EventHandler(ItemsMouseHover);
2457 MouseUp += new MouseEventHandler(ItemsMouseUp);
2460 void ItemsDoubleClick (object sender, EventArgs e)
2462 if (owner.activation == ItemActivation.Standard)
2463 owner.OnItemActivate (EventArgs.Empty);
2473 BoxSelect box_select_mode = BoxSelect.None;
2474 IList prev_selection;
2475 Point box_select_start;
2477 Rectangle box_select_rect;
2478 internal Rectangle BoxSelectRectangle {
2479 get { return box_select_rect; }
2481 if (box_select_rect == value)
2484 InvalidateBoxSelectRect ();
2485 box_select_rect = value;
2486 InvalidateBoxSelectRect ();
2490 void InvalidateBoxSelectRect ()
2492 if (BoxSelectRectangle.Size.IsEmpty)
2495 Rectangle edge = BoxSelectRectangle;
2501 edge.Y = BoxSelectRectangle.Bottom - 1;
2503 edge.Y = BoxSelectRectangle.Y - 1;
2505 edge.Height = BoxSelectRectangle.Height + 2;
2507 edge.X = BoxSelectRectangle.Right - 1;
2511 private Rectangle CalculateBoxSelectRectangle (Point pt)
2513 int left = Math.Min (box_select_start.X, pt.X);
2514 int right = Math.Max (box_select_start.X, pt.X);
2515 int top = Math.Min (box_select_start.Y, pt.Y);
2516 int bottom = Math.Max (box_select_start.Y, pt.Y);
2517 return Rectangle.FromLTRB (left, top, right, bottom);
2520 bool BoxIntersectsItem (int index)
2522 Rectangle r = new Rectangle (owner.GetItemLocation (index), owner.ItemSize);
2523 if (owner.View != View.Details) {
2525 r.Y += r.Height / 4;
2529 return BoxSelectRectangle.IntersectsWith (r);
2532 bool BoxIntersectsText (int index)
2534 Rectangle r = owner.GetItemAtDisplayIndex (index).TextBounds;
2535 return BoxSelectRectangle.IntersectsWith (r);
2538 ArrayList BoxSelectedItems {
2540 ArrayList result = new ArrayList ();
2541 for (int i = 0; i < owner.Items.Count; i++) {
2544 // Can't iterate over specific items properties in virtualmode
2545 if (owner.View == View.Details && !owner.FullRowSelect && !owner.VirtualMode)
2547 if (owner.View == View.Details && !owner.FullRowSelect)
2549 intersects = BoxIntersectsText (i);
2551 intersects = BoxIntersectsItem (i);
2554 result.Add (owner.GetItemAtDisplayIndex (i));
2560 private bool PerformBoxSelection (Point pt)
2562 if (box_select_mode == BoxSelect.None)
2565 BoxSelectRectangle = CalculateBoxSelectRectangle (pt);
2567 ArrayList box_items = BoxSelectedItems;
2571 switch (box_select_mode) {
2573 case BoxSelect.Normal:
2577 case BoxSelect.Control:
2578 items = new ArrayList ();
2579 foreach (int index in prev_selection)
2580 if (!box_items.Contains (owner.Items [index]))
2581 items.Add (owner.Items [index]);
2582 foreach (ListViewItem item in box_items)
2583 if (!prev_selection.Contains (item.Index))
2587 case BoxSelect.Shift:
2589 foreach (ListViewItem item in box_items)
2590 prev_selection.Remove (item.Index);
2591 foreach (int index in prev_selection)
2592 items.Add (owner.Items [index]);
2596 throw new Exception ("Unexpected Selection mode: " + box_select_mode);
2600 owner.SelectItems (items);
2606 private void ItemsMouseDown (object sender, MouseEventArgs me)
2608 owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
2609 if (owner.items.Count == 0)
2612 bool box_selecting = false;
2613 Size item_size = owner.ItemSize;
2614 Point pt = new Point (me.X, me.Y);
2615 for (int i = 0; i < owner.items.Count; i++) {
2616 Rectangle item_rect = new Rectangle (owner.GetItemLocation (i), item_size);
2617 if (!item_rect.Contains (pt))
2620 // Actual item in 'i' position
2621 ListViewItem item = owner.GetItemAtDisplayIndex (i);
2623 if (item.CheckRectReal.Contains (pt)) {
2624 // Don't modify check state if we have only one image
2625 // and if we are in 1.1 profile only take into account
2627 if (owner.StateImageList != null && owner.StateImageList.Images.Count < 2
2634 // Generate an extra ItemCheck event when we got two clicks
2635 // (Match weird .Net behaviour)
2637 item.Checked = !item.Checked;
2639 item.Checked = !item.Checked;
2644 if (owner.View == View.Details) {
2645 bool over_text = item.TextBounds.Contains (pt);
2646 if (owner.FullRowSelect) {
2647 clicked_item = item;
2648 bool over_item_column = (me.X > owner.Columns[0].X && me.X < owner.Columns[0].X + owner.Columns[0].Width);
2649 if (!over_text && over_item_column && owner.MultiSelect)
2650 box_selecting = true;
2651 } else if (over_text)
2652 clicked_item = item;
2654 owner.SetFocusedItem (i);
2656 clicked_item = item;
2662 if (clicked_item != null) {
2663 bool changed = !clicked_item.Selected;
2664 if (me.Button == MouseButtons.Left || (XplatUI.State.ModifierKeys == Keys.None && changed))
2665 owner.SetFocusedItem (clicked_item.DisplayIndex);
2667 if (owner.MultiSelect) {
2668 bool reselect = (!owner.LabelEdit || changed);
2669 if (me.Button == MouseButtons.Left || (XplatUI.State.ModifierKeys == Keys.None && changed))
2670 owner.UpdateMultiSelection (clicked_item.DisplayIndex, reselect);
2672 clicked_item.Selected = true;
2676 if (owner.VirtualMode && changed) {
2677 // Broken event - It's not fired from Item.Selected also
2678 ListViewVirtualItemsSelectionRangeChangedEventArgs args =
2679 new ListViewVirtualItemsSelectionRangeChangedEventArgs (0, owner.items.Count - 1, false);
2681 owner.OnVirtualItemsSelectionRangeChanged (args);
2684 // Report clicks only if the item was clicked. On MS the
2685 // clicks are only raised if you click an item
2687 if (me.Clicks > 1) {
2688 if (owner.CheckBoxes)
2689 clicked_item.Checked = !clicked_item.Checked;
2690 } else if (me.Clicks == 1) {
2691 if (owner.LabelEdit && !changed)
2692 BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
2695 if (owner.MultiSelect)
2696 box_selecting = true;
2697 else if (owner.SelectedItems.Count > 0)
2698 owner.SelectedItems.Clear ();
2701 if (box_selecting) {
2702 Keys mods = XplatUI.State.ModifierKeys;
2703 if ((mods & Keys.Shift) != 0)
2704 box_select_mode = BoxSelect.Shift;
2705 else if ((mods & Keys.Control) != 0)
2706 box_select_mode = BoxSelect.Control;
2708 box_select_mode = BoxSelect.Normal;
2709 box_select_start = pt;
2710 prev_selection = owner.SelectedIndices.List.Clone () as IList;
2714 private void ItemsMouseMove (object sender, MouseEventArgs me)
2716 bool done = PerformBoxSelection (new Point (me.X, me.Y));
2718 owner.OnMouseMove (owner.TranslateMouseEventArgs (me));
2722 if ((me.Button != MouseButtons.Left && me.Button != MouseButtons.Right) &&
2723 !hover_processed && owner.Activation != ItemActivation.OneClick
2725 && !owner.ShowItemToolTips
2730 Point pt = PointToClient (Control.MousePosition);
2731 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
2733 if (hover_processed && item != null && item != prev_hovered_item) {
2734 hover_processed = false;
2735 XplatUI.ResetMouseHover (Handle);
2738 // Need to invalidate the item in HotTracking to show/hide the underline style
2739 if (owner.Activation == ItemActivation.OneClick) {
2740 if (item == null && owner.HotItemIndex != -1) {
2742 if (owner.HotTracking)
2743 Invalidate (owner.Items [owner.HotItemIndex].Bounds); // Previous one
2746 Cursor = Cursors.Default;
2747 owner.HotItemIndex = -1;
2748 } else if (item != null && owner.HotItemIndex == -1) {
2750 if (owner.HotTracking)
2751 Invalidate (item.Bounds);
2754 Cursor = Cursors.Hand;
2755 owner.HotItemIndex = item.Index;
2759 if (me.Button == MouseButtons.Left || me.Button == MouseButtons.Right) {
2760 if (drag_begin.X == -1 && drag_begin.Y == -1) {
2762 drag_begin = new Point (me.X, me.Y);
2763 dragged_item_index = item.Index;
2767 Rectangle r = new Rectangle (drag_begin, SystemInformation.DragSize);
2768 if (!r.Contains (me.X, me.Y)) {
2769 ListViewItem dragged_item = owner.items [dragged_item_index];
2770 owner.OnItemDrag (new ItemDragEventArgs (me.Button, dragged_item));
2772 drag_begin = new Point (-1, -1);
2773 dragged_item_index = -1;
2779 if (owner.ShowItemToolTips) {
2781 owner.item_tooltip.Active = false;
2782 prev_tooltip_item = null;
2783 } else if (item != prev_tooltip_item && item.ToolTipText.Length > 0) {
2784 owner.item_tooltip.Active = true;
2785 owner.item_tooltip.SetToolTip (owner, item.ToolTipText);
2786 prev_tooltip_item = item;
2793 private void ItemsMouseHover (object sender, EventArgs e)
2795 if (owner.hover_pending) {
2796 owner.OnMouseHover (e);
2797 owner.hover_pending = false;
2803 hover_processed = true;
2804 Point pt = PointToClient (Control.MousePosition);
2805 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
2809 prev_hovered_item = item;
2811 if (owner.HoverSelection) {
2812 if (owner.MultiSelect)
2813 owner.UpdateMultiSelection (item.Index, true);
2815 item.Selected = true;
2817 owner.SetFocusedItem (item.DisplayIndex);
2818 Select (); // Make sure we have the focus, since MouseHover doesn't give it to us
2822 owner.OnItemMouseHover (new ListViewItemMouseHoverEventArgs (item));
2826 void HandleClicks (MouseEventArgs me)
2828 // if the click is not on an item,
2829 // clicks remains as 0
2832 owner.OnDoubleClick (EventArgs.Empty);
2833 } else if (clicks == 1) {
2834 owner.OnClick (EventArgs.Empty);
2836 owner.OnDoubleClick (EventArgs.Empty);
2837 owner.OnMouseDoubleClick (me);
2838 } else if (clicks == 1) {
2839 owner.OnClick (EventArgs.Empty);
2840 owner.OnMouseClick (me);
2847 private void ItemsMouseUp (object sender, MouseEventArgs me)
2849 MouseEventArgs owner_me = owner.TranslateMouseEventArgs (me);
2850 HandleClicks (owner_me);
2853 if (owner.Items.Count == 0) {
2855 owner.OnMouseUp (owner_me);
2859 Point pt = new Point (me.X, me.Y);
2861 Rectangle rect = Rectangle.Empty;
2862 if (clicked_item != null) {
2863 if (owner.view == View.Details && !owner.full_row_select)
2864 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
2866 rect = clicked_item.Bounds;
2868 if (rect.Contains (pt)) {
2869 switch (owner.activation) {
2870 case ItemActivation.OneClick:
2871 owner.OnItemActivate (EventArgs.Empty);
2874 case ItemActivation.TwoClick:
2875 if (last_clicked_item == clicked_item) {
2876 owner.OnItemActivate (EventArgs.Empty);
2877 last_clicked_item = null;
2879 last_clicked_item = clicked_item;
2882 // DoubleClick activation is handled in another handler
2886 } else if (!checking && owner.SelectedItems.Count > 0 && BoxSelectRectangle.Size.IsEmpty) {
2887 // Need this to clean up background clicks
2888 owner.SelectedItems.Clear ();
2892 owner.OnMouseUp (owner_me);
2895 private void ResetMouseState ()
2897 clicked_item = null;
2898 box_select_start = Point.Empty;
2899 BoxSelectRectangle = Rectangle.Empty;
2900 prev_selection = null;
2901 box_select_mode = BoxSelect.None;
2904 // Clean these bits in case the mouse buttons were
2905 // released before firing ItemDrag
2906 dragged_item_index = -1;
2907 drag_begin = new Point (-1, -1);
2910 private void LabelEditFinished (object sender, EventArgs e)
2912 EndEdit (edit_item);
2915 private void LabelEditCancelled (object sender, EventArgs e)
2917 edit_args.SetLabel (null);
2918 EndEdit (edit_item);
2921 private void LabelTextChanged (object sender, EventArgs e)
2923 if (edit_args != null)
2924 edit_args.SetLabel (edit_text_box.Text);
2927 internal void BeginEdit (ListViewItem item)
2929 if (edit_item != null)
2930 EndEdit (edit_item);
2932 if (edit_text_box == null) {
2933 edit_text_box = new ListViewLabelEditTextBox ();
2934 edit_text_box.BorderStyle = BorderStyle.FixedSingle;
2935 edit_text_box.EditingCancelled += new EventHandler (LabelEditCancelled);
2936 edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
2937 edit_text_box.TextChanged += new EventHandler (LabelTextChanged);
2938 edit_text_box.Visible = false;
2939 Controls.Add (edit_text_box);
2942 item.EnsureVisible();
2944 edit_text_box.Reset ();
2946 switch (owner.view) {
2948 case View.SmallIcon:
2950 edit_text_box.TextAlign = HorizontalAlignment.Left;
2951 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
2952 SizeF sizef = TextRenderer.MeasureString (item.Text, item.Font);
2953 edit_text_box.Width = (int)sizef.Width + 4;
2954 edit_text_box.MaxWidth = owner.ClientRectangle.Width - edit_text_box.Bounds.X;
2955 edit_text_box.WordWrap = false;
2956 edit_text_box.Multiline = false;
2958 case View.LargeIcon:
2959 edit_text_box.TextAlign = HorizontalAlignment.Center;
2960 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
2961 sizef = TextRenderer.MeasureString (item.Text, item.Font);
2962 edit_text_box.Width = (int)sizef.Width + 4;
2963 edit_text_box.MaxWidth = item.GetBounds(ItemBoundsPortion.Entire).Width;
2964 edit_text_box.MaxHeight = owner.ClientRectangle.Height - edit_text_box.Bounds.Y;
2965 edit_text_box.WordWrap = true;
2966 edit_text_box.Multiline = true;
2972 edit_text_box.Text = item.Text;
2973 edit_text_box.Font = item.Font;
2974 edit_text_box.Visible = true;
2975 edit_text_box.Focus ();
2976 edit_text_box.SelectAll ();
2978 edit_args = new LabelEditEventArgs (owner.Items.IndexOf (edit_item));
2979 owner.OnBeforeLabelEdit (edit_args);
2981 if (edit_args.CancelEdit)
2985 internal void CancelEdit (ListViewItem item)
2987 // do nothing if there's no item being edited, or if the
2988 // item being edited is not the one passed in
2989 if (edit_item == null || edit_item != item)
2992 edit_args.SetLabel (null);
2996 internal void EndEdit (ListViewItem item)
2998 // do nothing if there's no item being edited, or if the
2999 // item being edited is not the one passed in
3000 if (edit_item == null || edit_item != item)
3003 if (edit_text_box != null) {
3004 if (edit_text_box.Visible)
3005 edit_text_box.Visible = false;
3006 // ensure listview gets focus
3010 // Same as TreeView.EndEdit: need to have focus in synch
3011 Application.DoEvents ();
3014 // Create a new instance, since we could get a call to BeginEdit
3015 // from the handler and have fields out of synch
3017 LabelEditEventArgs args = new LabelEditEventArgs (item.Index, edit_args.Label);
3020 owner.OnAfterLabelEdit (args);
3021 if (!args.CancelEdit && args.Label != null)
3022 item.Text = args.Label;
3025 internal override void OnPaintInternal (PaintEventArgs pe)
3027 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
3030 protected override void WndProc (ref Message m)
3032 switch ((Msg)m.Msg) {
3033 case Msg.WM_KILLFOCUS:
3034 owner.Select (false, true);
3036 case Msg.WM_SETFOCUS:
3037 owner.Select (false, true);
3039 case Msg.WM_LBUTTONDOWN:
3041 owner.Select (false, true);
3043 case Msg.WM_RBUTTONDOWN:
3045 owner.Select (false, true);
3050 base.WndProc (ref m);
3054 internal class ListViewLabelEditTextBox : TextBox
3059 int max_height = -1;
3060 int min_height = -1;
3062 int old_number_lines = 1;
3064 SizeF text_size_one_char;
3066 public ListViewLabelEditTextBox ()
3068 min_height = DefaultSize.Height;
3069 text_size_one_char = TextRenderer.MeasureString ("B", Font);
3072 public int MaxWidth {
3074 if (value < min_width)
3075 max_width = min_width;
3081 public int MaxHeight {
3083 if (value < min_height)
3084 max_height = min_height;
3090 public new int Width {
3100 public override Font Font {
3106 text_size_one_char = TextRenderer.MeasureString ("B", Font);
3110 protected override void OnTextChanged (EventArgs e)
3112 SizeF text_size = TextRenderer.MeasureString (Text, Font);
3114 int new_width = (int)text_size.Width + 8;
3117 ResizeTextBoxWidth (new_width);
3119 if (Width != max_width)
3120 ResizeTextBoxWidth (new_width);
3122 int number_lines = Lines.Length;
3124 if (number_lines != old_number_lines) {
3125 int new_height = number_lines * (int)text_size_one_char.Height + 4;
3126 old_number_lines = number_lines;
3128 ResizeTextBoxHeight (new_height);
3132 base.OnTextChanged (e);
3135 protected override bool IsInputKey (Keys key_data)
3137 if ((key_data & Keys.Alt) == 0) {
3138 switch (key_data & Keys.KeyCode) {
3145 return base.IsInputKey (key_data);
3148 protected override void OnKeyDown (KeyEventArgs e)
3153 switch (e.KeyCode) {
3157 OnEditingFinished (e);
3162 OnEditingCancelled (e);
3167 protected override void OnLostFocus (EventArgs e)
3170 OnEditingFinished (e);
3174 protected void OnEditingCancelled (EventArgs e)
3176 EventHandler eh = (EventHandler)(Events [EditingCancelledEvent]);
3181 protected void OnEditingFinished (EventArgs e)
3183 EventHandler eh = (EventHandler)(Events [EditingFinishedEvent]);
3188 private void ResizeTextBoxWidth (int new_width)
3190 if (new_width > max_width)
3191 base.Width = max_width;
3193 if (new_width >= min_width)
3194 base.Width = new_width;
3196 base.Width = min_width;
3199 private void ResizeTextBoxHeight (int new_height)
3201 if (new_height > max_height)
3202 base.Height = max_height;
3204 if (new_height >= min_height)
3205 base.Height = new_height;
3207 base.Height = min_height;
3210 public void Reset ()
3217 old_number_lines = 1;
3219 Text = String.Empty;
3224 static object EditingCancelledEvent = new object ();
3225 public event EventHandler EditingCancelled {
3226 add { Events.AddHandler (EditingCancelledEvent, value); }
3227 remove { Events.RemoveHandler (EditingCancelledEvent, value); }
3230 static object EditingFinishedEvent = new object ();
3231 public event EventHandler EditingFinished {
3232 add { Events.AddHandler (EditingFinishedEvent, value); }
3233 remove { Events.RemoveHandler (EditingFinishedEvent, value); }
3237 internal override void OnPaintInternal (PaintEventArgs pe)
3242 CalculateScrollBars ();
3245 void FocusChanged (object o, EventArgs args)
3247 if (Items.Count == 0)
3250 if (FocusedItem == null)
3253 ListViewItem focused_item = FocusedItem;
3255 if (focused_item.ListView != null) {
3256 focused_item.Invalidate ();
3257 focused_item.Layout ();
3258 focused_item.Invalidate ();
3262 private void ListView_Invalidated (object sender, InvalidateEventArgs e)
3264 // When the ListView is invalidated, we need to invalidate
3265 // the child controls.
3266 header_control.Invalidate ();
3267 item_control.Invalidate ();
3270 private void ListView_MouseEnter (object sender, EventArgs args)
3272 hover_pending = true; // Need a hover event for every Enter/Leave cycle
3275 private void ListView_MouseWheel (object sender, MouseEventArgs me)
3277 if (Items.Count == 0)
3280 int lines = me.Delta / 120;
3287 case View.SmallIcon:
3288 Scroll (v_scroll, -ItemSize.Height * SystemInformation.MouseWheelScrollLines * lines);
3290 case View.LargeIcon:
3291 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * lines);
3294 Scroll (h_scroll, -ItemSize.Width * lines);
3298 if (!Application.VisualStylesEnabled)
3299 goto case View.LargeIcon;
3301 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * 2 * lines);
3307 private void ListView_SizeChanged (object sender, EventArgs e)
3312 private void SetFocusedItem (int display_index)
3314 if (display_index != -1)
3315 GetItemAtDisplayIndex (display_index).Focused = true;
3316 else if (focused_item_index != -1 && focused_item_index < items.Count) // Previous focused item
3317 GetItemAtDisplayIndex (focused_item_index).Focused = false;
3318 focused_item_index = display_index;
3320 if (display_index == -1)
3321 OnUIAFocusedItemChanged ();
3322 // otherwise the event will have been fired
3323 // when the ListViewItem's Focused was set
3327 private void HorizontalScroller (object sender, EventArgs e)
3329 item_control.EndEdit (item_control.edit_item);
3331 // Avoid unnecessary flickering, when button is
3332 // kept pressed at the end
3333 if (h_marker != h_scroll.Value) {
3335 int pixels = h_marker - h_scroll.Value;
3337 h_marker = h_scroll.Value;
3338 if (header_control.Visible)
3339 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
3341 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
3345 private void VerticalScroller (object sender, EventArgs e)
3347 item_control.EndEdit (item_control.edit_item);
3349 // Avoid unnecessary flickering, when button is
3350 // kept pressed at the end
3351 if (v_marker != v_scroll.Value) {
3352 int pixels = v_marker - v_scroll.Value;
3353 Rectangle area = item_control.ClientRectangle;
3354 if (header_control.Visible) {
3355 area.Y += header_control.Height;
3356 area.Height -= header_control.Height;
3359 v_marker = v_scroll.Value;
3360 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
3364 internal override bool IsInputCharInternal (char charCode)
3368 #endregion // Internal Methods Properties
3370 #region Protected Methods
3371 protected override void CreateHandle ()
3373 base.CreateHandle ();
3374 for (int i = 0; i < SelectedItems.Count; i++)
3375 OnSelectedIndexChanged (EventArgs.Empty);
3378 protected override void Dispose (bool disposing)
3381 h_scroll.Dispose ();
3382 v_scroll.Dispose ();
3384 large_image_list = null;
3385 small_image_list = null;
3386 state_image_list = null;
3388 foreach (ColumnHeader col in columns)
3389 col.SetListView (null);
3392 if (!virtual_mode) // In virtual mode we don't save the items
3394 foreach (ListViewItem item in items)
3398 base.Dispose (disposing);
3401 protected override bool IsInputKey (Keys keyData)
3418 return base.IsInputKey (keyData);
3421 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
3423 LabelEditEventHandler eh = (LabelEditEventHandler)(Events [AfterLabelEditEvent]);
3429 protected override void OnBackgroundImageChanged (EventArgs e)
3431 item_control.BackgroundImage = BackgroundImage;
3432 base.OnBackgroundImageChanged (e);
3436 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
3438 LabelEditEventHandler eh = (LabelEditEventHandler)(Events [BeforeLabelEditEvent]);
3443 protected internal virtual void OnColumnClick (ColumnClickEventArgs e)
3445 ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]);
3451 protected internal virtual void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
3453 DrawListViewColumnHeaderEventHandler eh = (DrawListViewColumnHeaderEventHandler)(Events[DrawColumnHeaderEvent]);
3458 protected internal virtual void OnDrawItem(DrawListViewItemEventArgs e)
3460 DrawListViewItemEventHandler eh = (DrawListViewItemEventHandler)(Events[DrawItemEvent]);
3465 protected internal virtual void OnDrawSubItem(DrawListViewSubItemEventArgs e)
3467 DrawListViewSubItemEventHandler eh = (DrawListViewSubItemEventHandler)(Events[DrawSubItemEvent]);
3473 protected override void OnEnabledChanged (EventArgs e)
3475 base.OnEnabledChanged (e);
3479 protected override void OnFontChanged (EventArgs e)
3481 base.OnFontChanged (e);
3485 protected override void OnHandleCreated (EventArgs e)
3487 base.OnHandleCreated (e);
3488 CalculateListView (alignment);
3490 if (!virtual_mode) // Sorting is not allowed in virtual mode
3495 protected override void OnHandleDestroyed (EventArgs e)
3497 base.OnHandleDestroyed (e);
3500 protected virtual void OnItemActivate (EventArgs e)
3502 EventHandler eh = (EventHandler)(Events [ItemActivateEvent]);
3507 protected internal virtual void OnItemCheck (ItemCheckEventArgs ice)
3509 ItemCheckEventHandler eh = (ItemCheckEventHandler)(Events [ItemCheckEvent]);
3515 protected internal virtual void OnItemChecked (ItemCheckedEventArgs e)
3517 ItemCheckedEventHandler eh = (ItemCheckedEventHandler)(Events [ItemCheckedEvent]);
3523 protected virtual void OnItemDrag (ItemDragEventArgs e)
3525 ItemDragEventHandler eh = (ItemDragEventHandler)(Events [ItemDragEvent]);
3531 protected virtual void OnItemMouseHover (ListViewItemMouseHoverEventArgs e)
3533 ListViewItemMouseHoverEventHandler eh = (ListViewItemMouseHoverEventHandler)(Events [ItemMouseHoverEvent]);
3538 protected internal virtual void OnItemSelectionChanged (ListViewItemSelectionChangedEventArgs e)
3540 ListViewItemSelectionChangedEventHandler eh =
3541 (ListViewItemSelectionChangedEventHandler) Events [ItemSelectionChangedEvent];
3546 protected override void OnMouseHover (EventArgs e)
3548 base.OnMouseHover (e);
3551 protected override void OnParentChanged (EventArgs e)
3553 base.OnParentChanged (e);
3557 protected virtual void OnSelectedIndexChanged (EventArgs e)
3559 EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
3564 protected override void OnSystemColorsChanged (EventArgs e)
3566 base.OnSystemColorsChanged (e);
3570 protected internal virtual void OnCacheVirtualItems (CacheVirtualItemsEventArgs e)
3572 CacheVirtualItemsEventHandler eh = (CacheVirtualItemsEventHandler)Events [CacheVirtualItemsEvent];
3577 protected virtual void OnRetrieveVirtualItem (RetrieveVirtualItemEventArgs e)
3579 RetrieveVirtualItemEventHandler eh = (RetrieveVirtualItemEventHandler)Events [RetrieveVirtualItemEvent];
3584 [EditorBrowsable (EditorBrowsableState.Advanced)]
3585 protected virtual void OnRightToLeftLayoutChanged (EventArgs e)
3587 EventHandler eh = (EventHandler)Events[RightToLeftLayoutChangedEvent];
3592 protected virtual void OnSearchForVirtualItem (SearchForVirtualItemEventArgs e)
3594 SearchForVirtualItemEventHandler eh = (SearchForVirtualItemEventHandler) Events [SearchForVirtualItemEvent];
3599 protected virtual void OnVirtualItemsSelectionRangeChanged (ListViewVirtualItemsSelectionRangeChangedEventArgs e)
3601 ListViewVirtualItemsSelectionRangeChangedEventHandler eh =
3602 (ListViewVirtualItemsSelectionRangeChangedEventHandler) Events [VirtualItemsSelectionRangeChangedEvent];
3608 protected void RealizeProperties ()
3613 protected void UpdateExtendedStyles ()
3618 bool refocusing = false;
3620 protected override void WndProc (ref Message m)
3622 switch ((Msg)m.Msg) {
3623 case Msg.WM_KILLFOCUS:
3624 Control receiver = Control.FromHandle (m.WParam);
3625 if (receiver == item_control) {
3631 case Msg.WM_SETFOCUS:
3641 base.WndProc (ref m);
3643 #endregion // Protected Methods
3645 #region Public Instance Methods
3646 public void ArrangeIcons ()
3648 ArrangeIcons (this.alignment);
3651 public void ArrangeIcons (ListViewAlignment value)
3653 // Icons are arranged only if view is set to LargeIcon or SmallIcon
3654 if (view == View.LargeIcon || view == View.SmallIcon)
3659 public void AutoResizeColumn (int columnIndex, ColumnHeaderAutoResizeStyle headerAutoResize)
3661 if (columnIndex < 0 || columnIndex >= columns.Count)
3662 throw new ArgumentOutOfRangeException ("columnIndex");
3664 columns [columnIndex].AutoResize (headerAutoResize);
3667 public void AutoResizeColumns (ColumnHeaderAutoResizeStyle headerAutoResize)
3670 foreach (ColumnHeader col in columns)
3671 col.AutoResize (headerAutoResize);
3676 public void BeginUpdate ()
3678 // flag to avoid painting
3682 public void Clear ()
3685 items.Clear (); // Redraw (true) called here
3688 public void EndUpdate ()
3690 // flag to avoid painting
3693 // probably, now we need a redraw with recalculations
3697 public void EnsureVisible (int index)
3699 if (index < 0 || index >= items.Count || scrollable == false || updating)
3702 Rectangle view_rect = item_control.ClientRectangle;
3704 // Avoid direct access to items in virtual mode, and use item bounds otherwise, since we could have reordered items
3705 Rectangle bounds = virtual_mode ? new Rectangle (GetItemLocation (index), ItemSize) : items [index].Bounds;
3707 Rectangle bounds = items [index].Bounds;
3710 if (view == View.Details && header_style != ColumnHeaderStyle.None) {
3711 view_rect.Y += header_control.Height;
3712 view_rect.Height -= header_control.Height;
3715 if (view_rect.Contains (bounds))
3718 if (View != View.Details) {
3719 if (bounds.Left < 0)
3720 h_scroll.Value += bounds.Left;
3721 else if (bounds.Right > view_rect.Right)
3722 h_scroll.Value += (bounds.Right - view_rect.Right);
3725 if (bounds.Top < view_rect.Y)
3726 v_scroll.Value += bounds.Top - view_rect.Y;
3727 else if (bounds.Bottom > view_rect.Bottom)
3728 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
3732 public ListViewItem FindItemWithText (string text)
3734 if (items.Count == 0)
3737 return FindItemWithText (text, true, 0, true);
3740 public ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex)
3742 return FindItemWithText (text, includeSubItemsInSearch, startIndex, true, false);
3745 public ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch)
3747 return FindItemWithText (text, includeSubItemsInSearch, startIndex, isPrefixSearch, false);
3751 internal ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch, bool roundtrip)
3753 if (startIndex < 0 || startIndex >= items.Count)
3754 throw new ArgumentOutOfRangeException ("startIndex");
3757 throw new ArgumentNullException ("text");
3761 SearchForVirtualItemEventArgs args = new SearchForVirtualItemEventArgs (true,
3762 isPrefixSearch, includeSubItemsInSearch, text, Point.Empty,
3763 SearchDirectionHint.Down, startIndex);
3765 OnSearchForVirtualItem (args);
3766 int idx = args.Index;
3767 if (idx >= 0 && idx < virtual_list_size)
3776 ListViewItem lvi = items [i];
3778 if (isPrefixSearch) { // prefix search
3779 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (lvi.Text, text, CompareOptions.IgnoreCase))
3781 } else if (String.Compare (lvi.Text, text, true) == 0) // match
3784 if (i + 1 >= items.Count) {
3792 if (i == startIndex)
3796 // Subitems have a minor priority, so we have to do a second linear search
3797 // Also, we don't need to to a roundtrip search for them by now
3798 if (includeSubItemsInSearch) {
3799 for (i = startIndex; i < items.Count; i++) {
3800 ListViewItem lvi = items [i];
3801 foreach (ListViewItem.ListViewSubItem sub_item in lvi.SubItems)
3802 if (isPrefixSearch) {
3803 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (sub_item.Text,
3804 text, CompareOptions.IgnoreCase))
3806 } else if (String.Compare (sub_item.Text, text, true) == 0)
3815 public ListViewItem FindNearestItem (SearchDirectionHint searchDirection, int x, int y)
3817 return FindNearestItem (searchDirection, new Point (x, y));
3820 public ListViewItem FindNearestItem (SearchDirectionHint dir, Point point)
3822 if (dir < SearchDirectionHint.Left || dir > SearchDirectionHint.Down)
3823 throw new ArgumentOutOfRangeException ("searchDirection");
3825 if (view != View.LargeIcon && view != View.SmallIcon)
3826 throw new InvalidOperationException ();
3829 SearchForVirtualItemEventArgs args = new SearchForVirtualItemEventArgs (false,
3830 false, false, String.Empty, point,
3833 OnSearchForVirtualItem (args);
3834 int idx = args.Index;
3835 if (idx >= 0 && idx < virtual_list_size)
3841 ListViewItem item = null;
3842 int min_dist = Int32.MaxValue;
3845 // It looks like .Net does a previous adjustment
3848 case SearchDirectionHint.Up:
3849 point.Y -= item_size.Height;
3851 case SearchDirectionHint.Down:
3852 point.Y += item_size.Height;
3854 case SearchDirectionHint.Left:
3855 point.X -= item_size.Width;
3857 case SearchDirectionHint.Right:
3858 point.X += item_size.Width;
3862 for (int i = 0; i < items.Count; i++) {
3863 Point item_loc = GetItemLocation (i);
3865 if (dir == SearchDirectionHint.Up) {
3866 if (point.Y < item_loc.Y)
3868 } else if (dir == SearchDirectionHint.Down) {
3869 if (point.Y > item_loc.Y)
3871 } else if (dir == SearchDirectionHint.Left) {
3872 if (point.X < item_loc.X)
3874 } else if (dir == SearchDirectionHint.Right) {
3875 if (point.X > item_loc.X)
3879 int x_dist = point.X - item_loc.X;
3880 int y_dist = point.Y - item_loc.Y;
3882 int dist = x_dist * x_dist + y_dist * y_dist;
3883 if (dist < min_dist) {
3893 public ListViewItem GetItemAt (int x, int y)
3895 Size item_size = ItemSize;
3896 for (int i = 0; i < items.Count; i++) {
3897 Point item_location = GetItemLocation (i);
3898 Rectangle item_rect = new Rectangle (item_location, item_size);
3899 if (item_rect.Contains (x, y))
3906 public Rectangle GetItemRect (int index)
3908 return GetItemRect (index, ItemBoundsPortion.Entire);
3911 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
3913 if (index < 0 || index >= items.Count)
3914 throw new IndexOutOfRangeException ("index");
3916 return items [index].GetBounds (portion);
3920 public ListViewHitTestInfo HitTest (Point point)
3922 return HitTest (point.X, point.Y);
3925 public ListViewHitTestInfo HitTest (int x, int y)
3928 throw new ArgumentOutOfRangeException ("x");
3930 throw new ArgumentOutOfRangeException ("y");
3932 ListViewItem item = GetItemAt (x, y);
3934 return new ListViewHitTestInfo (null, null, ListViewHitTestLocations.None);
3936 ListViewHitTestLocations locations = 0;
3937 if (item.GetBounds (ItemBoundsPortion.Label).Contains (x, y))
3938 locations |= ListViewHitTestLocations.Label;
3939 else if (item.GetBounds (ItemBoundsPortion.Icon).Contains (x, y))
3940 locations |= ListViewHitTestLocations.Image;
3941 else if (item.CheckRectReal.Contains (x, y))
3942 locations |= ListViewHitTestLocations.StateImage;
3944 ListViewItem.ListViewSubItem subitem = null;
3945 if (view == View.Details)
3946 foreach (ListViewItem.ListViewSubItem si in item.SubItems)
3947 if (si.Bounds.Contains (x, y)) {
3952 return new ListViewHitTestInfo (item, subitem, locations);
3955 [EditorBrowsable (EditorBrowsableState.Advanced)]
3956 public void RedrawItems (int startIndex, int endIndex, bool invalidateOnly)
3958 if (startIndex < 0 || startIndex >= items.Count)
3959 throw new ArgumentOutOfRangeException ("startIndex");
3960 if (endIndex < 0 || endIndex >= items.Count)
3961 throw new ArgumentOutOfRangeException ("endIndex");
3962 if (startIndex > endIndex)
3963 throw new ArgumentException ("startIndex");
3968 for (int i = startIndex; i <= endIndex; i++)
3969 items [i].Invalidate ();
3971 if (!invalidateOnly)
3980 throw new InvalidOperationException ();
3986 // we need this overload to reuse the logic for sorting, while allowing
3987 // redrawing to be done by caller or have it done by this method when
3988 // sorting is really performed
3990 // ListViewItemCollection's Add and AddRange methods call this overload
3991 // with redraw set to false, as they take care of redrawing themselves
3992 // (they even want to redraw the listview if no sort is performed, as
3993 // an item was added), while ListView.Sort () only wants to redraw if
3994 // sorting was actually performed
3995 private void Sort (bool redraw)
3997 if (!IsHandleCreated || item_sorter == null) {
4001 items.Sort (item_sorter);
4006 public override string ToString ()
4008 int count = this.Items.Count;
4011 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
4013 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
4015 #endregion // Public Instance Methods
4020 internal class HeaderControl : Control {
4023 bool column_resize_active = false;
4024 ColumnHeader resize_column;
4025 ColumnHeader clicked_column;
4026 ColumnHeader drag_column;
4028 int drag_to_index = -1;
4029 ColumnHeader entered_column_header;
4031 public HeaderControl (ListView owner)
4034 this.SetStyle (ControlStyles.DoubleBuffer, true);
4035 MouseDown += new MouseEventHandler (HeaderMouseDown);
4036 MouseMove += new MouseEventHandler (HeaderMouseMove);
4037 MouseUp += new MouseEventHandler (HeaderMouseUp);
4038 MouseLeave += new EventHandler (OnMouseLeave);
4041 internal ColumnHeader EnteredColumnHeader {
4042 get { return entered_column_header; }
4044 if (entered_column_header == value)
4046 if (ThemeEngine.Current.ListViewHasHotHeaderStyle) {
4047 Region region_to_invalidate = new Region ();
4048 region_to_invalidate.MakeEmpty ();
4049 if (entered_column_header != null)
4050 region_to_invalidate.Union (GetColumnHeaderInvalidateArea (entered_column_header));
4051 entered_column_header = value;
4052 if (entered_column_header != null)
4053 region_to_invalidate.Union (GetColumnHeaderInvalidateArea (entered_column_header));
4054 Invalidate (region_to_invalidate);
4055 region_to_invalidate.Dispose ();
4057 entered_column_header = value;
4061 void OnMouseLeave (object sender, EventArgs e)
4063 EnteredColumnHeader = null;
4066 private ColumnHeader ColumnAtX (int x)
4068 Point pt = new Point (x, 0);
4069 ColumnHeader result = null;
4070 foreach (ColumnHeader col in owner.Columns) {
4071 if (col.Rect.Contains (pt)) {
4079 private int GetReorderedIndex (ColumnHeader col)
4081 if (owner.reordered_column_indices == null)
4084 for (int i = 0; i < owner.Columns.Count; i++)
4085 if (owner.reordered_column_indices [i] == col.Index)
4087 throw new Exception ("Column index missing from reordered array");
4090 private void HeaderMouseDown (object sender, MouseEventArgs me)
4092 if (resize_column != null) {
4093 column_resize_active = true;
4098 clicked_column = ColumnAtX (me.X + owner.h_marker);
4100 if (clicked_column != null) {
4102 if (owner.AllowColumnReorder) {
4104 drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
4105 drag_column.Rect = clicked_column.Rect;
4106 drag_to_index = GetReorderedIndex (clicked_column);
4108 clicked_column.Pressed = true;
4109 Invalidate (clicked_column);
4114 void Invalidate (ColumnHeader columnHeader)
4116 Invalidate (GetColumnHeaderInvalidateArea (columnHeader));
4119 Rectangle GetColumnHeaderInvalidateArea (ColumnHeader columnHeader)
4121 Rectangle bounds = columnHeader.Rect;
4122 bounds.X -= owner.h_marker;
4128 column_resize_active = false;
4129 resize_column = null;
4131 Cursor = Cursors.Default;
4134 private void HeaderMouseMove (object sender, MouseEventArgs me)
4136 Point pt = new Point (me.X + owner.h_marker, me.Y);
4138 if (column_resize_active) {
4139 int width = pt.X - resize_column.X;
4143 if (!owner.CanProceedWithResize (resize_column, width)){
4147 resize_column.Width = width;
4151 resize_column = null;
4153 if (clicked_column != null) {
4154 if (owner.AllowColumnReorder) {
4157 r = drag_column.Rect;
4158 r.X = clicked_column.Rect.X + me.X - drag_x;
4159 drag_column.Rect = r;
4161 int x = me.X + owner.h_marker;
4162 ColumnHeader over = ColumnAtX (x);
4164 drag_to_index = owner.Columns.Count;
4165 else if (x < over.X + over.Width / 2)
4166 drag_to_index = GetReorderedIndex (over);
4168 drag_to_index = GetReorderedIndex (over) + 1;
4171 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
4172 bool pressed = clicked_column.Pressed;
4173 clicked_column.Pressed = over == clicked_column;
4174 if (clicked_column.Pressed ^ pressed)
4175 Invalidate (clicked_column);
4180 for (int i = 0; i < owner.Columns.Count; i++) {
4181 Rectangle zone = owner.Columns [i].Rect;
4182 if (zone.Contains (pt))
4183 EnteredColumnHeader = owner.Columns [i];
4184 zone.X = zone.Right - 5;
4186 if (zone.Contains (pt)) {
4187 if (i < owner.Columns.Count - 1 && owner.Columns [i + 1].Width == 0)
4189 resize_column = owner.Columns [i];
4194 if (resize_column == null)
4195 Cursor = Cursors.Default;
4197 Cursor = Cursors.VSplit;
4200 void HeaderMouseUp (object sender, MouseEventArgs me)
4204 if (column_resize_active) {
4205 int column_idx = resize_column.Index;
4207 owner.RaiseColumnWidthChanged (column_idx);
4211 if (clicked_column != null && clicked_column.Pressed) {
4212 clicked_column.Pressed = false;
4213 Invalidate (clicked_column);
4214 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
4217 if (drag_column != null && owner.AllowColumnReorder) {
4219 if (drag_to_index > GetReorderedIndex (clicked_column))
4221 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
4222 owner.ReorderColumn (clicked_column, drag_to_index, true);
4227 clicked_column = null;
4230 internal override void OnPaintInternal (PaintEventArgs pe)
4235 Theme theme = ThemeEngine.Current;
4236 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
4238 if (drag_column == null)
4242 if (drag_to_index == owner.Columns.Count)
4243 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
4245 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
4246 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
4249 protected override void WndProc (ref Message m)
4251 switch ((Msg)m.Msg) {
4252 case Msg.WM_SETFOCUS:
4256 base.WndProc (ref m);
4262 private class ItemComparer : IComparer {
4263 readonly SortOrder sort_order;
4265 public ItemComparer (SortOrder sortOrder)
4267 sort_order = sortOrder;
4270 public int Compare (object x, object y)
4272 ListViewItem item_x = x as ListViewItem;
4273 ListViewItem item_y = y as ListViewItem;
4274 if (sort_order == SortOrder.Ascending)
4275 return String.Compare (item_x.Text, item_y.Text);
4277 return String.Compare (item_y.Text, item_x.Text);
4282 [ListBindable (false)]
4284 public class CheckedIndexCollection : IList, ICollection, IEnumerable
4286 private readonly ListView owner;
4288 #region Public Constructor
4289 public CheckedIndexCollection (ListView owner)
4293 #endregion // Public Constructor
4295 #region Public Properties
4298 get { return owner.CheckedItems.Count; }
4301 public bool IsReadOnly {
4302 get { return true; }
4305 public int this [int index] {
4307 int [] indices = GetIndices ();
4308 if (index < 0 || index >= indices.Length)
4309 throw new ArgumentOutOfRangeException ("index");
4310 return indices [index];
4314 bool ICollection.IsSynchronized {
4315 get { return false; }
4318 object ICollection.SyncRoot {
4319 get { return this; }
4322 bool IList.IsFixedSize {
4323 get { return true; }
4326 object IList.this [int index] {
4327 get { return this [index]; }
4328 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4330 #endregion // Public Properties
4332 #region Public Methods
4333 public bool Contains (int checkedIndex)
4335 int [] indices = GetIndices ();
4336 for (int i = 0; i < indices.Length; i++) {
4337 if (indices [i] == checkedIndex)
4343 public IEnumerator GetEnumerator ()
4345 int [] indices = GetIndices ();
4346 return indices.GetEnumerator ();
4349 void ICollection.CopyTo (Array dest, int index)
4351 int [] indices = GetIndices ();
4352 Array.Copy (indices, 0, dest, index, indices.Length);
4355 int IList.Add (object value)
4357 throw new NotSupportedException ("Add operation is not supported.");
4362 throw new NotSupportedException ("Clear operation is not supported.");
4365 bool IList.Contains (object checkedIndex)
4367 if (!(checkedIndex is int))
4369 return Contains ((int) checkedIndex);
4372 int IList.IndexOf (object checkedIndex)
4374 if (!(checkedIndex is int))
4376 return IndexOf ((int) checkedIndex);
4379 void IList.Insert (int index, object value)
4381 throw new NotSupportedException ("Insert operation is not supported.");
4384 void IList.Remove (object value)
4386 throw new NotSupportedException ("Remove operation is not supported.");
4389 void IList.RemoveAt (int index)
4391 throw new NotSupportedException ("RemoveAt operation is not supported.");
4394 public int IndexOf (int checkedIndex)
4396 int [] indices = GetIndices ();
4397 for (int i = 0; i < indices.Length; i++) {
4398 if (indices [i] == checkedIndex)
4403 #endregion // Public Methods
4405 private int [] GetIndices ()
4407 ArrayList checked_items = owner.CheckedItems.List;
4408 int [] indices = new int [checked_items.Count];
4409 for (int i = 0; i < checked_items.Count; i++) {
4410 ListViewItem item = (ListViewItem) checked_items [i];
4411 indices [i] = item.Index;
4415 } // CheckedIndexCollection
4418 [ListBindable (false)]
4420 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
4422 private readonly ListView owner;
4423 private ArrayList list;
4425 #region Public Constructor
4426 public CheckedListViewItemCollection (ListView owner)
4429 this.owner.Items.Changed += new CollectionChangedHandler (
4430 ItemsCollection_Changed);
4432 #endregion // Public Constructor
4434 #region Public Properties
4438 if (!owner.CheckBoxes)
4444 public bool IsReadOnly {
4445 get { return true; }
4448 public ListViewItem this [int index] {
4451 if (owner.VirtualMode)
4452 throw new InvalidOperationException ();
4454 ArrayList checked_items = List;
4455 if (index < 0 || index >= checked_items.Count)
4456 throw new ArgumentOutOfRangeException ("index");
4457 return (ListViewItem) checked_items [index];
4462 public virtual ListViewItem this [string key] {
4464 int idx = IndexOfKey (key);
4465 return idx == -1 ? null : (ListViewItem) List [idx];
4470 bool ICollection.IsSynchronized {
4471 get { return false; }
4474 object ICollection.SyncRoot {
4475 get { return this; }
4478 bool IList.IsFixedSize {
4479 get { return true; }
4482 object IList.this [int index] {
4483 get { return this [index]; }
4484 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4486 #endregion // Public Properties
4488 #region Public Methods
4489 public bool Contains (ListViewItem item)
4491 if (!owner.CheckBoxes)
4493 return List.Contains (item);
4497 public virtual bool ContainsKey (string key)
4499 return IndexOfKey (key) != -1;
4503 public void CopyTo (Array dest, int index)
4506 if (owner.VirtualMode)
4507 throw new InvalidOperationException ();
4509 if (!owner.CheckBoxes)
4511 List.CopyTo (dest, index);
4514 public IEnumerator GetEnumerator ()
4517 if (owner.VirtualMode)
4518 throw new InvalidOperationException ();
4520 if (!owner.CheckBoxes)
4521 return (new ListViewItem [0]).GetEnumerator ();
4522 return List.GetEnumerator ();
4525 int IList.Add (object value)
4527 throw new NotSupportedException ("Add operation is not supported.");
4532 throw new NotSupportedException ("Clear operation is not supported.");
4535 bool IList.Contains (object item)
4537 if (!(item is ListViewItem))
4539 return Contains ((ListViewItem) item);
4542 int IList.IndexOf (object item)
4544 if (!(item is ListViewItem))
4546 return IndexOf ((ListViewItem) item);
4549 void IList.Insert (int index, object value)
4551 throw new NotSupportedException ("Insert operation is not supported.");
4554 void IList.Remove (object value)
4556 throw new NotSupportedException ("Remove operation is not supported.");
4559 void IList.RemoveAt (int index)
4561 throw new NotSupportedException ("RemoveAt operation is not supported.");
4564 public int IndexOf (ListViewItem item)
4567 if (owner.VirtualMode)
4568 throw new InvalidOperationException ();
4570 if (!owner.CheckBoxes)
4572 return List.IndexOf (item);
4576 public virtual int IndexOfKey (string key)
4579 if (owner.VirtualMode)
4580 throw new InvalidOperationException ();
4582 if (key == null || key.Length == 0)
4585 ArrayList checked_items = List;
4586 for (int i = 0; i < checked_items.Count; i++) {
4587 ListViewItem item = (ListViewItem) checked_items [i];
4588 if (String.Compare (key, item.Name, true) == 0)
4595 #endregion // Public Methods
4597 internal ArrayList List {
4600 list = new ArrayList ();
4601 foreach (ListViewItem item in owner.Items) {
4610 internal void Reset ()
4612 // force re-population of list
4616 private void ItemsCollection_Changed ()
4620 } // CheckedListViewItemCollection
4623 [ListBindable (false)]
4625 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
4627 internal ArrayList list;
4628 private ListView owner;
4630 #region UIA Framework Events
4633 // We are using Reflection to add/remove internal events.
4634 // Class ListViewProvider uses the events when View is Details.
4636 //Event used to generate UIA StructureChangedEvent
4637 static object UIACollectionChangedEvent = new object ();
4639 internal event CollectionChangeEventHandler UIACollectionChanged {
4642 owner.Events.AddHandler (UIACollectionChangedEvent, value);
4646 owner.Events.RemoveHandler (UIACollectionChangedEvent, value);
4650 internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args)
4655 CollectionChangeEventHandler eh
4656 = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
4662 #endregion UIA Framework Events
4664 #region Public Constructor
4665 public ColumnHeaderCollection (ListView owner)
4667 list = new ArrayList ();
4670 #endregion // Public Constructor
4672 #region Public Properties
4675 get { return list.Count; }
4678 public bool IsReadOnly {
4679 get { return false; }
4682 public virtual ColumnHeader this [int index] {
4684 if (index < 0 || index >= list.Count)
4685 throw new ArgumentOutOfRangeException ("index");
4686 return (ColumnHeader) list [index];
4691 public virtual ColumnHeader this [string key] {
4693 int idx = IndexOfKey (key);
4697 return (ColumnHeader) list [idx];
4702 bool ICollection.IsSynchronized {
4703 get { return true; }
4706 object ICollection.SyncRoot {
4707 get { return this; }
4710 bool IList.IsFixedSize {
4711 get { return list.IsFixedSize; }
4714 object IList.this [int index] {
4715 get { return this [index]; }
4716 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4718 #endregion // Public Properties
4720 #region Public Methods
4721 public virtual int Add (ColumnHeader value)
4723 int idx = list.Add (value);
4724 owner.AddColumn (value, idx, true);
4727 //UIA Framework event: Item Added
4728 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
4735 public virtual ColumnHeader Add (string text, int width, HorizontalAlignment textAlign)
4739 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
4742 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
4743 this.Add (colHeader);
4748 public virtual ColumnHeader Add (string text)
4750 return Add (String.Empty, text);
4753 public virtual ColumnHeader Add (string text, int width)
4755 return Add (String.Empty, text, width);
4758 public virtual ColumnHeader Add (string key, string text)
4760 ColumnHeader colHeader = new ColumnHeader ();
4761 colHeader.Name = key;
4762 colHeader.Text = text;
4767 public virtual ColumnHeader Add (string key, string text, int width)
4769 return Add (key, text, width, HorizontalAlignment.Left, -1);
4772 public virtual ColumnHeader Add (string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
4774 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4775 colHeader.ImageIndex = imageIndex;
4780 public virtual ColumnHeader Add (string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
4782 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4783 colHeader.ImageKey = imageKey;
4789 public virtual void AddRange (ColumnHeader [] values)
4791 foreach (ColumnHeader colHeader in values) {
4792 int idx = list.Add (colHeader);
4793 owner.AddColumn (colHeader, idx, false);
4796 owner.Redraw (true);
4799 public virtual void Clear ()
4801 foreach (ColumnHeader col in list)
4802 col.SetListView (null);
4804 owner.ReorderColumns (new int [0], true);
4807 //UIA Framework event: Items cleared
4808 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
4813 public bool Contains (ColumnHeader value)
4815 return list.Contains (value);
4819 public virtual bool ContainsKey (string key)
4821 return IndexOfKey (key) != -1;
4825 public IEnumerator GetEnumerator ()
4827 return list.GetEnumerator ();
4830 void ICollection.CopyTo (Array dest, int index)
4832 list.CopyTo (dest, index);
4835 int IList.Add (object value)
4837 if (! (value is ColumnHeader)) {
4838 throw new ArgumentException ("Not of type ColumnHeader", "value");
4841 return this.Add ((ColumnHeader) value);
4844 bool IList.Contains (object value)
4846 if (! (value is ColumnHeader)) {
4847 throw new ArgumentException ("Not of type ColumnHeader", "value");
4850 return this.Contains ((ColumnHeader) value);
4853 int IList.IndexOf (object value)
4855 if (! (value is ColumnHeader)) {
4856 throw new ArgumentException ("Not of type ColumnHeader", "value");
4859 return this.IndexOf ((ColumnHeader) value);
4862 void IList.Insert (int index, object value)
4864 if (! (value is ColumnHeader)) {
4865 throw new ArgumentException ("Not of type ColumnHeader", "value");
4868 this.Insert (index, (ColumnHeader) value);
4871 void IList.Remove (object value)
4873 if (! (value is ColumnHeader)) {
4874 throw new ArgumentException ("Not of type ColumnHeader", "value");
4877 this.Remove ((ColumnHeader) value);
4880 public int IndexOf (ColumnHeader value)
4882 return list.IndexOf (value);
4886 public virtual int IndexOfKey (string key)
4888 if (key == null || key.Length == 0)
4891 for (int i = 0; i < list.Count; i++) {
4892 ColumnHeader col = (ColumnHeader) list [i];
4893 if (String.Compare (key, col.Name, true) == 0)
4901 public void Insert (int index, ColumnHeader value)
4903 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
4904 // but it's really only greater.
4905 if (index < 0 || index > list.Count)
4906 throw new ArgumentOutOfRangeException ("index");
4908 list.Insert (index, value);
4909 owner.AddColumn (value, index, true);
4912 //UIA Framework event: Item added
4913 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
4918 public void Insert (int index, string text)
4920 Insert (index, String.Empty, text);
4923 public void Insert (int index, string text, int width)
4925 Insert (index, String.Empty, text, width);
4928 public void Insert (int index, string key, string text)
4930 ColumnHeader colHeader = new ColumnHeader ();
4931 colHeader.Name = key;
4932 colHeader.Text = text;
4933 Insert (index, colHeader);
4936 public void Insert (int index, string key, string text, int width)
4938 ColumnHeader colHeader = new ColumnHeader (key, text, width, HorizontalAlignment.Left);
4939 Insert (index, colHeader);
4942 public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
4944 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4945 colHeader.ImageIndex = imageIndex;
4946 Insert (index, colHeader);
4949 public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
4951 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4952 colHeader.ImageKey = imageKey;
4953 Insert (index, colHeader);
4958 public void Insert (int index, string text, int width, HorizontalAlignment textAlign)
4962 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
4965 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
4966 this.Insert (index, colHeader);
4969 public virtual void Remove (ColumnHeader column)
4971 if (!Contains (column))
4974 list.Remove (column);
4975 column.SetListView (null);
4977 int rem_display_index = column.InternalDisplayIndex;
4978 int [] display_indices = new int [list.Count];
4979 for (int i = 0; i < display_indices.Length; i++) {
4980 ColumnHeader col = (ColumnHeader) list [i];
4981 int display_index = col.InternalDisplayIndex;
4982 if (display_index < rem_display_index) {
4983 display_indices [i] = display_index;
4985 display_indices [i] = (display_index - 1);
4989 column.InternalDisplayIndex = -1;
4990 owner.ReorderColumns (display_indices, true);
4993 //UIA Framework event: Item Removed
4994 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, column));
4999 public virtual void RemoveByKey (string key)
5001 int idx = IndexOfKey (key);
5007 public virtual void RemoveAt (int index)
5009 if (index < 0 || index >= list.Count)
5010 throw new ArgumentOutOfRangeException ("index");
5012 ColumnHeader col = (ColumnHeader) list [index];
5015 #endregion // Public Methods
5018 } // ColumnHeaderCollection
5021 [ListBindable (false)]
5023 public class ListViewItemCollection : IList, ICollection, IEnumerable
5025 private readonly ArrayList list;
5026 private ListView owner;
5028 private ListViewGroup group;
5031 #region UIA Framework Events
5034 // We are using Reflection to add/remove internal events.
5035 // Class ListViewProvider uses the events.
5037 //Event used to generate UIA StructureChangedEvent
5038 static object UIACollectionChangedEvent = new object ();
5040 internal event CollectionChangeEventHandler UIACollectionChanged {
5043 owner.Events.AddHandler (UIACollectionChangedEvent, value);
5047 owner.Events.RemoveHandler (UIACollectionChangedEvent, value);
5051 internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args)
5056 CollectionChangeEventHandler eh
5057 = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
5063 #endregion UIA Framework Events
5065 // The collection can belong to a ListView (main) or to a ListViewGroup (sub-collection)
5066 // In the later case ListViewItem.ListView never gets modified
5067 private bool is_main_collection = true;
5069 #region Public Constructor
5070 public ListViewItemCollection (ListView owner)
5072 list = new ArrayList (0);
5075 #endregion // Public Constructor
5078 internal ListViewItemCollection (ListView owner, ListViewGroup group) : this (owner)
5081 is_main_collection = false;
5085 #region Public Properties
5090 if (owner != null && owner.VirtualMode)
5091 return owner.VirtualListSize;
5098 public bool IsReadOnly {
5099 get { return false; }
5103 public virtual ListViewItem this [int index] {
5105 public virtual ListViewItem this [int displayIndex] {
5109 int index = displayIndex;
5112 if (index < 0 || index >= Count)
5113 throw new ArgumentOutOfRangeException ("index");
5116 if (owner != null && owner.VirtualMode)
5117 return RetrieveVirtualItemFromOwner (index);
5119 return (ListViewItem) list [index];
5124 int index = displayIndex;
5127 if (index < 0 || index >= Count)
5128 throw new ArgumentOutOfRangeException ("index");
5131 if (owner != null && owner.VirtualMode)
5132 throw new InvalidOperationException ();
5135 if (list.Contains (value))
5136 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
5138 if (value.ListView != null && value.ListView != owner)
5139 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");
5141 if (is_main_collection)
5142 value.Owner = owner;
5145 if (value.Group != null)
5146 value.Group.Items.Remove (value);
5148 value.SetGroup (group);
5153 //UIA Framework event: Item Replaced
5154 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, list [index]));
5157 list [index] = value;
5159 CollectionChanged (true);
5162 //UIA Framework event: Item Replaced
5163 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
5170 public virtual ListViewItem this [string key] {
5172 int idx = IndexOfKey (key);
5181 bool ICollection.IsSynchronized {
5182 get { return true; }
5185 object ICollection.SyncRoot {
5186 get { return this; }
5189 bool IList.IsFixedSize {
5190 get { return list.IsFixedSize; }
5193 object IList.this [int index] {
5194 get { return this [index]; }
5197 //UIA Framework event: Item Replaced
5198 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, this [index]));
5201 if (value is ListViewItem)
5202 this [index] = (ListViewItem) value;
5204 this [index] = new ListViewItem (value.ToString ());
5208 //UIA Framework event: Item Replaced
5209 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
5213 #endregion // Public Properties
5215 #region Public Methods
5216 public virtual ListViewItem Add (ListViewItem value)
5219 if (owner != null && owner.VirtualMode)
5220 throw new InvalidOperationException ();
5225 // Item is ignored until it has been added to the ListView
5226 if (is_main_collection || value.ListView != null)
5227 CollectionChanged (true);
5230 //UIA Framework event: Item Added
5231 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
5237 public virtual ListViewItem Add (string text)
5239 ListViewItem item = new ListViewItem (text);
5240 return this.Add (item);
5243 public virtual ListViewItem Add (string text, int imageIndex)
5245 ListViewItem item = new ListViewItem (text, imageIndex);
5246 return this.Add (item);
5250 public virtual ListViewItem Add (string text, string imageKey)
5252 ListViewItem item = new ListViewItem (text, imageKey);
5253 return this.Add (item);
5256 public virtual ListViewItem Add (string key, string text, int imageIndex)
5258 ListViewItem item = new ListViewItem (text, imageIndex);
5260 return this.Add (item);
5263 public virtual ListViewItem Add (string key, string text, string imageKey)
5265 ListViewItem item = new ListViewItem (text, imageKey);
5267 return this.Add (item);
5272 public void AddRange (ListViewItem [] items)
5275 public void AddRange (ListViewItem [] values)
5277 ListViewItem [] items = values;
5280 throw new ArgumentNullException ("Argument cannot be null!", "items");
5282 if (owner != null && owner.VirtualMode)
5283 throw new InvalidOperationException ();
5286 owner.BeginUpdate ();
5288 foreach (ListViewItem item in items) {
5292 //UIA Framework event: Item Added
5293 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
5299 CollectionChanged (true);
5303 public void AddRange (ListViewItemCollection items)
5306 throw new ArgumentNullException ("Argument cannot be null!", "items");
5308 ListViewItem[] itemArray = new ListViewItem[items.Count];
5309 items.CopyTo (itemArray,0);
5310 this.AddRange (itemArray);
5314 public virtual void Clear ()
5317 if (owner != null && owner.VirtualMode)
5318 throw new InvalidOperationException ();
5320 if (is_main_collection && owner != null) {
5321 owner.SetFocusedItem (-1);
5322 owner.h_scroll.Value = owner.v_scroll.Value = 0;
5325 // first remove any item in the groups that *are* part of this LV too
5326 foreach (ListViewGroup group in owner.groups)
5327 group.Items.ClearItemsWithSameListView ();
5330 foreach (ListViewItem item in list) {
5331 owner.item_control.CancelEdit (item);
5337 foreach (ListViewItem item in list)
5338 item.SetGroup (null);
5342 CollectionChanged (false);
5345 //UIA Framework event: Items Removed
5346 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
5352 // This method is intended to be used from ListViewGroup.Items, not from ListView.Items,
5353 // added for performance reasons (avoid calling manually Remove for every item on ListViewGroup.Items)
5354 void ClearItemsWithSameListView ()
5356 if (is_main_collection)
5359 int counter = list.Count - 1;
5360 while (counter >= 0) {
5361 ListViewItem item = list [counter] as ListViewItem;
5363 // remove only if the items in group have being added to the ListView too
5364 if (item.ListView == group.ListView) {
5365 list.RemoveAt (counter);
5366 item.SetGroup (null);
5374 public bool Contains (ListViewItem item)
5376 return IndexOf (item) != -1;
5380 public virtual bool ContainsKey (string key)
5382 return IndexOfKey (key) != -1;
5386 public void CopyTo (Array dest, int index)
5388 list.CopyTo (dest, index);
5392 public ListViewItem [] Find (string key, bool searchAllSubItems)
5395 return new ListViewItem [0];
5397 List<ListViewItem> temp_list = new List<ListViewItem> ();
5399 for (int i = 0; i < list.Count; i++) {
5400 ListViewItem lvi = (ListViewItem) list [i];
5401 if (String.Compare (key, lvi.Name, true) == 0)
5402 temp_list.Add (lvi);
5405 ListViewItem [] retval = new ListViewItem [temp_list.Count];
5406 temp_list.CopyTo (retval);
5412 public IEnumerator GetEnumerator ()
5415 if (owner != null && owner.VirtualMode)
5416 throw new InvalidOperationException ();
5419 // This enumerator makes a copy of the collection so
5420 // it can be deleted from in a foreach
5421 return new Control.ControlCollection.ControlCollectionEnumerator (list);
5424 int IList.Add (object item)
5430 if (owner != null && owner.VirtualMode)
5431 throw new InvalidOperationException ();
5434 if (item is ListViewItem) {
5435 li = (ListViewItem) item;
5436 if (list.Contains (li))
5437 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
5439 if (li.ListView != null && li.ListView != owner)
5440 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");
5443 li = new ListViewItem (item.ToString ());
5448 result = list.Add (li);
5449 CollectionChanged (true);
5452 //UIA Framework event: Item Added
5453 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, li));
5459 bool IList.Contains (object item)
5461 return Contains ((ListViewItem) item);
5464 int IList.IndexOf (object item)
5466 return IndexOf ((ListViewItem) item);
5469 void IList.Insert (int index, object item)
5471 if (item is ListViewItem)
5472 this.Insert (index, (ListViewItem) item);
5474 this.Insert (index, item.ToString ());
5477 //UIA Framework event: Item Added
5478 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, this [index]));
5482 void IList.Remove (object item)
5484 Remove ((ListViewItem) item);
5487 public int IndexOf (ListViewItem item)
5490 if (owner != null && owner.VirtualMode) {
5491 for (int i = 0; i < Count; i++)
5492 if (RetrieveVirtualItemFromOwner (i) == item)
5499 return list.IndexOf (item);
5503 public virtual int IndexOfKey (string key)
5505 if (key == null || key.Length == 0)
5508 for (int i = 0; i < Count; i++) {
5509 ListViewItem lvi = this [i];
5510 if (String.Compare (key, lvi.Name, true) == 0)
5518 public ListViewItem Insert (int index, ListViewItem item)
5520 if (index < 0 || index > list.Count)
5521 throw new ArgumentOutOfRangeException ("index");
5524 if (owner != null && owner.VirtualMode)
5525 throw new InvalidOperationException ();
5528 if (list.Contains (item))
5529 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
5531 if (item.ListView != null && item.ListView != owner)
5532 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");
5534 if (is_main_collection)
5538 if (item.Group != null)
5539 item.Group.Items.Remove (item);
5541 item.SetGroup (group);
5545 list.Insert (index, item);
5547 if (is_main_collection || item.ListView != null)
5548 CollectionChanged (true);
5551 //UIA Framework event: Item Added
5552 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
5558 public ListViewItem Insert (int index, string text)
5560 return this.Insert (index, new ListViewItem (text));
5563 public ListViewItem Insert (int index, string text, int imageIndex)
5565 return this.Insert (index, new ListViewItem (text, imageIndex));
5569 public ListViewItem Insert (int index, string text, string imageKey)
5571 ListViewItem lvi = new ListViewItem (text, imageKey);
5572 return Insert (index, lvi);
5575 public virtual ListViewItem Insert (int index, string key, string text, int imageIndex)
5577 ListViewItem lvi = new ListViewItem (text, imageIndex);
5579 return Insert (index, lvi);
5582 public virtual ListViewItem Insert (int index, string key, string text, string imageKey)
5584 ListViewItem lvi = new ListViewItem (text, imageKey);
5586 return Insert (index, lvi);
5590 public virtual void Remove (ListViewItem item)
5593 if (owner != null && owner.VirtualMode)
5594 throw new InvalidOperationException ();
5597 int idx = list.IndexOf (item);
5602 public virtual void RemoveAt (int index)
5604 if (index < 0 || index >= Count)
5605 throw new ArgumentOutOfRangeException ("index");
5608 if (owner != null && owner.VirtualMode)
5609 throw new InvalidOperationException ();
5612 ListViewItem item = (ListViewItem) list [index];
5614 bool selection_changed = false;
5615 if (is_main_collection && owner != null) {
5617 int display_index = item.DisplayIndex;
5618 if (item.Focused && display_index + 1 == Count) // Last item
5619 owner.SetFocusedItem (display_index == 0 ? -1 : display_index - 1);
5621 selection_changed = owner.SelectedIndices.Contains (index);
5622 owner.item_control.CancelEdit (item);
5625 list.RemoveAt (index);
5628 if (is_main_collection) {
5630 if (item.Group != null)
5631 item.Group.Items.Remove (item);
5633 item.SetGroup (null);
5638 CollectionChanged (false);
5639 if (selection_changed && owner != null)
5640 owner.OnSelectedIndexChanged (EventArgs.Empty);
5644 //UIA Framework event: Item Removed
5645 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, item));
5650 public virtual void RemoveByKey (string key)
5652 int idx = IndexOfKey (key);
5658 #endregion // Public Methods
5660 internal ListView Owner {
5670 internal ListViewGroup Group {
5680 void AddItem (ListViewItem value)
5682 if (list.Contains (value))
5683 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
5685 if (value.ListView != null && value.ListView != owner)
5686 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");
5687 if (is_main_collection)
5688 value.Owner = owner;
5691 if (value.Group != null)
5692 value.Group.Items.Remove (value);
5694 value.SetGroup (group);
5702 void CollectionChanged (bool sort)
5704 if (owner != null) {
5709 owner.Redraw (true);
5714 ListViewItem RetrieveVirtualItemFromOwner (int displayIndex)
5716 RetrieveVirtualItemEventArgs args = new RetrieveVirtualItemEventArgs (displayIndex);
5718 owner.OnRetrieveVirtualItem (args);
5719 ListViewItem retval = args.Item;
5720 retval.Owner = owner;
5721 retval.DisplayIndex = displayIndex;
5727 internal event CollectionChangedHandler Changed;
5729 internal void Sort (IComparer comparer)
5731 list.Sort (comparer);
5735 internal void OnChange ()
5737 if (Changed != null)
5740 } // ListViewItemCollection
5743 // In normal mode, the selection information resides in the Items,
5744 // making SelectedIndexCollection.List read-only
5746 // In virtual mode, SelectedIndexCollection directly saves the selection
5747 // information, instead of getting it from Items, making List read-and-write
5749 [ListBindable (false)]
5751 public class SelectedIndexCollection : IList, ICollection, IEnumerable
5753 private readonly ListView owner;
5754 private ArrayList list;
5756 #region Public Constructor
5757 public SelectedIndexCollection (ListView owner)
5760 owner.Items.Changed += new CollectionChangedHandler (ItemsCollection_Changed);
5762 #endregion // Public Constructor
5764 #region Public Properties
5768 if (!owner.IsHandleCreated)
5775 public bool IsReadOnly {
5785 public int this [int index] {
5787 if (!owner.IsHandleCreated || index < 0 || index >= List.Count)
5788 throw new ArgumentOutOfRangeException ("index");
5790 return (int) List [index];
5794 bool ICollection.IsSynchronized {
5795 get { return false; }
5798 object ICollection.SyncRoot {
5799 get { return this; }
5802 bool IList.IsFixedSize {
5812 object IList.this [int index] {
5813 get { return this [index]; }
5814 set { throw new NotSupportedException ("SetItem operation is not supported."); }
5816 #endregion // Public Properties
5818 #region Public Methods
5820 public int Add (int itemIndex)
5822 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
5823 throw new ArgumentOutOfRangeException ("index");
5825 if (owner.virtual_mode && !owner.IsHandleCreated)
5828 owner.Items [itemIndex].Selected = true;
5830 if (!owner.IsHandleCreated)
5844 if (!owner.IsHandleCreated)
5847 int [] indexes = (int []) List.ToArray (typeof (int));
5848 foreach (int index in indexes)
5849 owner.Items [index].Selected = false;
5852 public bool Contains (int selectedIndex)
5854 return IndexOf (selectedIndex) != -1;
5857 public void CopyTo (Array dest, int index)
5859 List.CopyTo (dest, index);
5862 public IEnumerator GetEnumerator ()
5864 return List.GetEnumerator ();
5867 int IList.Add (object value)
5869 throw new NotSupportedException ("Add operation is not supported.");
5877 bool IList.Contains (object selectedIndex)
5879 if (!(selectedIndex is int))
5881 return Contains ((int) selectedIndex);
5884 int IList.IndexOf (object selectedIndex)
5886 if (!(selectedIndex is int))
5888 return IndexOf ((int) selectedIndex);
5891 void IList.Insert (int index, object value)
5893 throw new NotSupportedException ("Insert operation is not supported.");
5896 void IList.Remove (object value)
5898 throw new NotSupportedException ("Remove operation is not supported.");
5901 void IList.RemoveAt (int index)
5903 throw new NotSupportedException ("RemoveAt operation is not supported.");
5906 public int IndexOf (int selectedIndex)
5908 if (!owner.IsHandleCreated)
5911 return List.IndexOf (selectedIndex);
5915 public void Remove (int itemIndex)
5917 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
5918 throw new ArgumentOutOfRangeException ("itemIndex");
5920 owner.Items [itemIndex].Selected = false;
5923 #endregion // Public Methods
5925 internal ArrayList List {
5928 list = new ArrayList ();
5930 if (!owner.VirtualMode)
5932 for (int i = 0; i < owner.Items.Count; i++) {
5933 if (owner.Items [i].Selected)
5941 internal void Reset ()
5943 // force re-population of list
5947 private void ItemsCollection_Changed ()
5953 internal void RemoveIndex (int index)
5955 int idx = List.BinarySearch (index);
5957 List.RemoveAt (idx);
5960 // actually store index in the collection
5961 // also, keep the collection sorted, as .Net does
5962 internal void InsertIndex (int index)
5965 int iMax = List.Count - 1;
5966 while (iMin <= iMax) {
5967 int iMid = (iMin + iMax) / 2;
5968 int current_index = (int) List [iMid];
5970 if (current_index == index)
5971 return; // Already added
5972 if (current_index > index)
5978 List.Insert (iMin, index);
5982 } // SelectedIndexCollection
5985 [ListBindable (false)]
5987 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
5989 private readonly ListView owner;
5991 #region Public Constructor
5992 public SelectedListViewItemCollection (ListView owner)
5996 #endregion // Public Constructor
5998 #region Public Properties
6002 return owner.SelectedIndices.Count;
6006 public bool IsReadOnly {
6007 get { return true; }
6010 public ListViewItem this [int index] {
6012 if (!owner.IsHandleCreated || index < 0 || index >= Count)
6013 throw new ArgumentOutOfRangeException ("index");
6015 int item_index = owner.SelectedIndices [index];
6016 return owner.Items [item_index];
6021 public virtual ListViewItem this [string key] {
6023 int idx = IndexOfKey (key);
6032 bool ICollection.IsSynchronized {
6033 get { return false; }
6036 object ICollection.SyncRoot {
6037 get { return this; }
6040 bool IList.IsFixedSize {
6041 get { return true; }
6044 object IList.this [int index] {
6045 get { return this [index]; }
6046 set { throw new NotSupportedException ("SetItem operation is not supported."); }
6048 #endregion // Public Properties
6050 #region Public Methods
6051 public void Clear ()
6053 owner.SelectedIndices.Clear ();
6056 public bool Contains (ListViewItem item)
6058 return IndexOf (item) != -1;
6062 public virtual bool ContainsKey (string key)
6064 return IndexOfKey (key) != -1;
6068 public void CopyTo (Array dest, int index)
6070 if (!owner.IsHandleCreated)
6072 if (index > Count) // Throws ArgumentException instead of IOOR exception
6073 throw new ArgumentException ("index");
6075 for (int i = 0; i < Count; i++)
6076 dest.SetValue (this [i], index++);
6079 public IEnumerator GetEnumerator ()
6081 if (!owner.IsHandleCreated)
6082 return (new ListViewItem [0]).GetEnumerator ();
6084 ListViewItem [] items = new ListViewItem [Count];
6085 for (int i = 0; i < Count; i++)
6086 items [i] = this [i];
6088 return items.GetEnumerator ();
6091 int IList.Add (object value)
6093 throw new NotSupportedException ("Add operation is not supported.");
6096 bool IList.Contains (object item)
6098 if (!(item is ListViewItem))
6100 return Contains ((ListViewItem) item);
6103 int IList.IndexOf (object item)
6105 if (!(item is ListViewItem))
6107 return IndexOf ((ListViewItem) item);
6110 void IList.Insert (int index, object value)
6112 throw new NotSupportedException ("Insert operation is not supported.");
6115 void IList.Remove (object value)
6117 throw new NotSupportedException ("Remove operation is not supported.");
6120 void IList.RemoveAt (int index)
6122 throw new NotSupportedException ("RemoveAt operation is not supported.");
6125 public int IndexOf (ListViewItem item)
6127 if (!owner.IsHandleCreated)
6130 for (int i = 0; i < Count; i++)
6131 if (this [i] == item)
6138 public virtual int IndexOfKey (string key)
6140 if (!owner.IsHandleCreated || key == null || key.Length == 0)
6143 for (int i = 0; i < Count; i++) {
6144 ListViewItem item = this [i];
6145 if (String.Compare (item.Name, key, true) == 0)
6152 #endregion // Public Methods
6154 } // SelectedListViewItemCollection
6156 internal delegate void CollectionChangedHandler ();
6158 struct ItemMatrixLocation
6163 public ItemMatrixLocation (int row, int col)
6190 #endregion // Subclasses
6192 protected override void OnResize (EventArgs e)
6197 protected override void OnMouseLeave (EventArgs e)
6199 base.OnMouseLeave (e);
6203 // ColumnReorder event
6205 static object ColumnReorderedEvent = new object ();
6206 public event ColumnReorderedEventHandler ColumnReordered {
6207 add { Events.AddHandler (ColumnReorderedEvent, value); }
6208 remove { Events.RemoveHandler (ColumnReorderedEvent, value); }
6211 protected virtual void OnColumnReordered (ColumnReorderedEventArgs e)
6213 ColumnReorderedEventHandler creh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
6220 // ColumnWidthChanged
6222 static object ColumnWidthChangedEvent = new object ();
6223 public event ColumnWidthChangedEventHandler ColumnWidthChanged {
6224 add { Events.AddHandler (ColumnWidthChangedEvent, value); }
6225 remove { Events.RemoveHandler (ColumnWidthChangedEvent, value); }
6228 protected virtual void OnColumnWidthChanged (ColumnWidthChangedEventArgs e)
6230 ColumnWidthChangedEventHandler eh = (ColumnWidthChangedEventHandler) (Events[ColumnWidthChangedEvent]);
6235 void RaiseColumnWidthChanged (int resize_column)
6237 ColumnWidthChangedEventArgs n = new ColumnWidthChangedEventArgs (resize_column);
6239 OnColumnWidthChanged (n);
6243 // ColumnWidthChanging
6245 static object ColumnWidthChangingEvent = new object ();
6246 public event ColumnWidthChangingEventHandler ColumnWidthChanging {
6247 add { Events.AddHandler (ColumnWidthChangingEvent, value); }
6248 remove { Events.RemoveHandler (ColumnWidthChangingEvent, value); }
6251 protected virtual void OnColumnWidthChanging (ColumnWidthChangingEventArgs e)
6253 ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
6259 // 2.0 profile based implementation
6261 bool CanProceedWithResize (ColumnHeader col, int width)
6263 ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
6267 ColumnWidthChangingEventArgs changing = new ColumnWidthChangingEventArgs (col.Index, width);
6268 cwceh (this, changing);
6269 return !changing.Cancel;
6273 // 1.0 profile based implementation
6275 bool CanProceedWithResize (ColumnHeader col, int width)
6280 void RaiseColumnWidthChanged (int resize_column)
6285 internal void RaiseColumnWidthChanged (ColumnHeader column)
6287 int index = Columns.IndexOf (column);
6288 RaiseColumnWidthChanged (index);
6293 #region UIA Framework: Methods, Properties and Events
6295 static object UIALabelEditChangedEvent = new object ();
6296 static object UIAShowGroupsChangedEvent = new object ();
6297 static object UIAMultiSelectChangedEvent = new object ();
6298 static object UIAViewChangedEvent = new object ();
6299 static object UIACheckBoxesChangedEvent = new object ();
6300 static object UIAFocusedItemChangedEvent = new object ();
6302 internal Rectangle UIAHeaderControl {
6303 get { return header_control.Bounds; }
6306 internal int UIAColumns {
6307 get { return cols; }
6310 internal int UIARows {
6311 get { return rows; }
6314 internal ListViewGroup UIADefaultListViewGroup
6316 get { return groups.DefaultGroup; }
6319 internal ScrollBar UIAHScrollBar {
6320 get { return h_scroll; }
6323 internal ScrollBar UIAVScrollBar {
6324 get { return v_scroll; }
6327 internal event EventHandler UIAShowGroupsChanged {
6328 add { Events.AddHandler (UIAShowGroupsChangedEvent, value); }
6329 remove { Events.RemoveHandler (UIAShowGroupsChangedEvent, value); }
6332 internal event EventHandler UIACheckBoxesChanged {
6333 add { Events.AddHandler (UIACheckBoxesChangedEvent, value); }
6334 remove { Events.RemoveHandler (UIACheckBoxesChangedEvent, value); }
6337 internal event EventHandler UIAMultiSelectChanged {
6338 add { Events.AddHandler (UIAMultiSelectChangedEvent, value); }
6339 remove { Events.RemoveHandler (UIAMultiSelectChangedEvent, value); }
6342 internal event EventHandler UIALabelEditChanged {
6343 add { Events.AddHandler (UIALabelEditChangedEvent, value); }
6344 remove { Events.RemoveHandler (UIALabelEditChangedEvent, value); }
6347 internal event EventHandler UIAViewChanged {
6348 add { Events.AddHandler (UIAViewChangedEvent, value); }
6349 remove { Events.RemoveHandler (UIAViewChangedEvent, value); }
6352 internal event EventHandler UIAFocusedItemChanged {
6353 add { Events.AddHandler (UIAFocusedItemChangedEvent, value); }
6354 remove { Events.RemoveHandler (UIAFocusedItemChangedEvent, value); }
6357 internal Rectangle UIAGetHeaderBounds (ListViewGroup group)
6359 return group.HeaderBounds;
6362 internal int UIAItemsLocationLength
6364 get { return items_location.Length; }
6367 private void OnUIACheckBoxesChanged ()
6369 EventHandler eh = (EventHandler) Events [UIACheckBoxesChangedEvent];
6371 eh (this, EventArgs.Empty);
6374 private void OnUIAShowGroupsChanged ()
6376 EventHandler eh = (EventHandler) Events [UIAShowGroupsChangedEvent];
6378 eh (this, EventArgs.Empty);
6381 private void OnUIAMultiSelectChanged ()
6383 EventHandler eh = (EventHandler) Events [UIAMultiSelectChangedEvent];
6385 eh (this, EventArgs.Empty);
6388 private void OnUIALabelEditChanged ()
6390 EventHandler eh = (EventHandler) Events [UIALabelEditChangedEvent];
6392 eh (this, EventArgs.Empty);
6395 private void OnUIAViewChanged ()
6397 EventHandler eh = (EventHandler) Events [UIAViewChangedEvent];
6399 eh (this, EventArgs.Empty);
6402 internal void OnUIAFocusedItemChanged ()
6404 EventHandler eh = (EventHandler) Events [UIAFocusedItemChangedEvent];
6406 eh (this, EventArgs.Empty);
6409 #endregion // UIA Framework: Methods, Properties and Events