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.");
1080 if (VirtualMode && value == View.Tile)
1081 throw new NotSupportedException ("VirtualMode is"
1082 + " not supported in Tile view. Choose a different"
1083 + " view or set ViewMode to false.");
1086 h_scroll.Value = v_scroll.Value = 0;
1091 // UIA Framework: Event used to update UIA Tree.
1092 OnUIAViewChanged ();
1099 [DefaultValue (false)]
1100 [RefreshProperties (RefreshProperties.Repaint)]
1101 public bool VirtualMode {
1103 return virtual_mode;
1106 if (virtual_mode == value)
1109 if (!virtual_mode && items.Count > 0)
1110 throw new InvalidOperationException ();
1111 if (value && view == View.Tile)
1112 throw new NotSupportedException ("VirtualMode is"
1113 + " not supported in Tile view. Choose a different"
1114 + " view or set ViewMode to false.");
1116 virtual_mode = value;
1122 [RefreshProperties (RefreshProperties.Repaint)]
1123 public int VirtualListSize {
1125 return virtual_list_size;
1129 throw new ArgumentException ("value");
1131 if (virtual_list_size == value)
1134 virtual_list_size = value;
1136 selected_indices.Reset ();
1142 #endregion // Public Instance Properties
1144 #region Internal Methods Properties
1146 internal int FirstVisibleIndex {
1149 if (this.items.Count == 0)
1152 if (h_marker == 0 && v_marker == 0)
1155 Size item_size = ItemSize;
1156 for (int i = 0; i < items.Count; i++) {
1157 Rectangle item_rect = new Rectangle (GetItemLocation (i), item_size);
1158 if (item_rect.Right >= 0 && item_rect.Bottom >= 0)
1167 internal int LastVisibleIndex {
1169 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
1170 if (View == View.List || Alignment == ListViewAlignment.Left) {
1171 if (GetItemLocation (i).X > item_control.ClientRectangle.Right)
1174 if (GetItemLocation (i).Y > item_control.ClientRectangle.Bottom)
1179 return Items.Count - 1;
1183 internal void OnSelectedIndexChanged ()
1185 if (IsHandleCreated)
1186 OnSelectedIndexChanged (EventArgs.Empty);
1189 internal int TotalWidth {
1190 get { return Math.Max (this.Width, this.layout_wd); }
1193 internal int TotalHeight {
1194 get { return Math.Max (this.Height, this.layout_ht); }
1197 internal void Redraw (bool recalculate)
1199 // Avoid calculations when control is being updated
1203 // VirtualMode doesn't do any calculations until handle is created
1204 if (virtual_mode && !IsHandleCreated)
1210 CalculateListView (this.alignment);
1215 void InvalidateSelection ()
1217 foreach (int selected_index in SelectedIndices)
1218 items [selected_index].Invalidate ();
1221 const int text_padding = 15;
1223 internal Size GetChildColumnSize (int index)
1225 Size ret_size = Size.Empty;
1226 ColumnHeader col = this.columns [index];
1228 if (col.Width == -2) { // autosize = max(items, columnheader)
1229 Size size = Size.Ceiling (TextRenderer.MeasureString
1230 (col.Text, this.Font));
1231 size.Width += text_padding;
1232 ret_size = BiggestItem (index);
1233 if (size.Width > ret_size.Width)
1236 else { // -1 and all the values < -2 are put under one category
1237 ret_size = BiggestItem (index);
1238 // fall back to empty columns' width if no subitem is available for a column
1239 if (ret_size.IsEmpty) {
1240 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
1241 if (col.Text.Length > 0)
1242 ret_size.Height = Size.Ceiling (TextRenderer.MeasureString
1243 (col.Text, this.Font)).Height;
1245 ret_size.Height = this.Font.Height;
1249 ret_size.Height += text_padding;
1251 // adjust the size for icon and checkbox for 0th column
1253 ret_size.Width += (this.CheckBoxSize.Width + 4);
1254 if (this.small_image_list != null)
1255 ret_size.Width += this.small_image_list.ImageSize.Width;
1260 // Returns the size of biggest item text in a column
1261 // or the sum of the text and indent count if we are on 2.0
1262 private Size BiggestItem (int col)
1264 Size temp = Size.Empty;
1265 Size ret_size = Size.Empty;
1267 bool use_indent_count = small_image_list != null;
1269 // VirtualMode uses the first item text size
1270 if (virtual_mode && items.Count > 0) {
1271 ListViewItem item = items [0];
1272 ret_size = Size.Ceiling (TextRenderer.MeasureString (item.SubItems[col].Text,
1275 if (use_indent_count)
1276 ret_size.Width += item.IndentCount * small_image_list.ImageSize.Width;
1279 // 0th column holds the item text, we check the size of
1280 // the various subitems falling in that column and get
1281 // the biggest one's size.
1282 foreach (ListViewItem item in items) {
1283 if (col >= item.SubItems.Count)
1286 temp = Size.Ceiling (TextRenderer.MeasureString
1287 (item.SubItems [col].Text, Font));
1290 if (use_indent_count)
1291 temp.Width += item.IndentCount * small_image_list.ImageSize.Width;
1294 if (temp.Width > ret_size.Width)
1301 // adjustment for space in Details view
1302 if (!ret_size.IsEmpty && view == View.Details)
1303 ret_size.Width += ThemeEngine.Current.ListViewItemPaddingWidth;
1308 const int max_wrap_padding = 30;
1310 // Sets the size of the biggest item text as per the view
1311 private void CalcTextSize ()
1313 // clear the old value
1314 text_size = Size.Empty;
1316 if (items.Count == 0)
1319 text_size = BiggestItem (0);
1321 if (view == View.LargeIcon && this.label_wrap) {
1322 Size temp = Size.Empty;
1323 if (this.check_boxes)
1324 temp.Width += 2 * this.CheckBoxSize.Width;
1325 int icon_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1326 temp.Width += icon_w + max_wrap_padding;
1327 // wrapping is done for two lines only
1328 if (text_size.Width > temp.Width) {
1329 text_size.Width = temp.Width;
1330 text_size.Height *= 2;
1333 else if (view == View.List) {
1334 // in list view max text shown in determined by the
1335 // control width, even if scolling is enabled.
1336 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
1337 if (this.small_image_list != null)
1338 max_wd -= this.small_image_list.ImageSize.Width;
1340 if (text_size.Width > max_wd)
1341 text_size.Width = max_wd;
1344 // we do the default settings, if we have got 0's
1345 if (text_size.Height <= 0)
1346 text_size.Height = this.Font.Height;
1347 if (text_size.Width <= 0)
1348 text_size.Width = this.Width;
1350 // little adjustment
1351 text_size.Width += 2;
1352 text_size.Height += 2;
1355 private void Scroll (ScrollBar scrollbar, int delta)
1357 if (delta == 0 || !scrollbar.Visible)
1361 if (scrollbar == h_scroll)
1362 max = h_scroll.Maximum - item_control.Width;
1364 max = v_scroll.Maximum - item_control.Height;
1366 int val = scrollbar.Value + delta;
1369 else if (val < scrollbar.Minimum)
1370 val = scrollbar.Minimum;
1371 scrollbar.Value = val;
1374 private void CalculateScrollBars ()
1376 Rectangle client_area = ClientRectangle;
1377 int height = client_area.Height;
1378 int width = client_area.Width;
1381 h_scroll.Visible = false;
1382 v_scroll.Visible = false;
1383 item_control.Size = new Size (width, height);
1384 header_control.Width = width;
1388 // Don't calculate if the view is not displayable
1389 if (client_area.Height < 0 || client_area.Width < 0)
1392 // making a scroll bar visible might make
1393 // other scroll bar visible
1394 if (layout_wd > client_area.Right) {
1395 h_scroll.Visible = true;
1396 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
1397 v_scroll.Visible = true;
1399 v_scroll.Visible = false;
1400 } else if (layout_ht > client_area.Bottom) {
1401 v_scroll.Visible = true;
1402 if ((layout_wd + v_scroll.Width) > client_area.Right)
1403 h_scroll.Visible = true;
1405 h_scroll.Visible = false;
1407 h_scroll.Visible = false;
1408 v_scroll.Visible = false;
1412 if (h_scroll.is_visible) {
1413 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
1414 h_scroll.Minimum = 0;
1416 // if v_scroll is visible, adjust the maximum of the
1417 // h_scroll to account for the width of v_scroll
1418 if (v_scroll.Visible) {
1419 h_scroll.Maximum = layout_wd + v_scroll.Width;
1420 h_scroll.Width = client_area.Width - v_scroll.Width;
1423 h_scroll.Maximum = layout_wd;
1424 h_scroll.Width = client_area.Width;
1427 h_scroll.LargeChange = client_area.Width;
1428 h_scroll.SmallChange = item_size.Width + ThemeEngine.Current.ListViewHorizontalSpacing;
1429 height -= h_scroll.Height;
1432 if (v_scroll.is_visible) {
1433 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
1434 v_scroll.Minimum = 0;
1435 v_scroll.Maximum = layout_ht;
1437 // if h_scroll is visible, adjust the height of
1438 // v_scroll to account for the height of h_scroll
1439 if (h_scroll.Visible)
1440 v_scroll.Height = client_area.Height - h_scroll.Height;
1442 v_scroll.Height = client_area.Height;
1444 v_scroll.LargeChange = client_area.Height;
1445 v_scroll.SmallChange = Font.Height;
1446 width -= v_scroll.Width;
1449 item_control.Size = new Size (width, height);
1451 if (header_control.is_visible)
1452 header_control.Width = width;
1456 internal int GetReorderedColumnIndex (ColumnHeader column)
1458 if (reordered_column_indices == null)
1459 return column.Index;
1461 for (int i = 0; i < Columns.Count; i++)
1462 if (reordered_column_indices [i] == column.Index)
1469 internal ColumnHeader GetReorderedColumn (int index)
1471 if (reordered_column_indices == null)
1472 return Columns [index];
1474 return Columns [reordered_column_indices [index]];
1477 internal void ReorderColumn (ColumnHeader col, int index, bool fireEvent)
1481 ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
1483 ColumnReorderedEventArgs args = new ColumnReorderedEventArgs (col.Index, index, col);
1487 header_control.Invalidate ();
1488 item_control.Invalidate ();
1494 int column_count = Columns.Count;
1496 if (reordered_column_indices == null) {
1497 reordered_column_indices = new int [column_count];
1498 for (int i = 0; i < column_count; i++)
1499 reordered_column_indices [i] = i;
1502 if (reordered_column_indices [index] == col.Index)
1505 int[] curr = reordered_column_indices;
1506 int [] result = new int [column_count];
1508 for (int i = 0; i < column_count; i++) {
1509 if (curr_idx < column_count && curr [curr_idx] == col.Index)
1513 result [i] = col.Index;
1515 result [i] = curr [curr_idx++];
1518 ReorderColumns (result, true);
1521 internal void ReorderColumns (int [] display_indices, bool redraw)
1523 reordered_column_indices = display_indices;
1524 for (int i = 0; i < Columns.Count; i++) {
1525 ColumnHeader col = Columns [i];
1526 col.InternalDisplayIndex = reordered_column_indices [i];
1528 if (redraw && view == View.Details && IsHandleCreated) {
1530 header_control.Invalidate ();
1531 item_control.Invalidate ();
1535 internal void AddColumn (ColumnHeader newCol, int index, bool redraw)
1537 int column_count = Columns.Count;
1538 newCol.SetListView (this);
1540 int [] display_indices = new int [column_count];
1541 for (int i = 0; i < column_count; i++) {
1542 ColumnHeader col = Columns [i];
1544 display_indices [i] = index;
1546 int display_index = col.InternalDisplayIndex;
1547 if (display_index < index) {
1548 display_indices [i] = display_index;
1550 display_indices [i] = (display_index + 1);
1555 ReorderColumns (display_indices, redraw);
1559 Size LargeIconItemSize
1562 int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1563 int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
1564 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
1565 int w = Math.Max (text_size.Width, image_w);
1568 w += 2 + CheckBoxSize.Width;
1570 return new Size (w, h);
1574 Size SmallIconItemSize {
1576 int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
1577 int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1578 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
1579 int w = text_size.Width + image_w;
1582 w += 2 + CheckBoxSize.Width;
1584 return new Size (w, h);
1591 // Calculate tile size if needed
1592 // It appears that using Font.Size instead of a SizeF value can give us
1593 // a slightly better approach to the proportions defined in .Net
1594 if (tile_size == Size.Empty) {
1595 int image_w = LargeImageList == null ? 0 : LargeImageList.ImageSize.Width;
1596 int image_h = LargeImageList == null ? 0 : LargeImageList.ImageSize.Height;
1597 int w = (int)Font.Size * ThemeEngine.Current.ListViewTileWidthFactor + image_w + 4;
1598 int h = Math.Max ((int)Font.Size * ThemeEngine.Current.ListViewTileHeightFactor, image_h);
1600 tile_size = new Size (w, h);
1608 int GetDetailsItemHeight ()
1611 int checkbox_height = CheckBoxes ? CheckBoxSize.Height : 0;
1612 int small_image_height = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1613 item_height = Math.Max (checkbox_height, text_size.Height);
1614 item_height = Math.Max (item_height, small_image_height);
1618 void SetItemLocation (int index, int x, int y, int row, int col)
1620 Point old_location = items_location [index];
1621 if (old_location.X == x && old_location.Y == y)
1624 items_location [index] = new Point (x, y);
1625 items_matrix_location [index] = new ItemMatrixLocation (row, col);
1628 // Initial position matches item's position in ListViewItemCollection
1630 reordered_items_indices [index] = index;
1634 void ShiftItemsPositions (int from, int to, bool forward)
1637 for (int i = to + 1; i > from; i--) {
1638 reordered_items_indices [i] = reordered_items_indices [i - 1];
1640 ListViewItem item = items [reordered_items_indices [i]];
1642 item.DisplayIndex = i;
1646 for (int i = from - 1; i < to; i++) {
1647 reordered_items_indices [i] = reordered_items_indices [i + 1];
1649 ListViewItem item = items [reordered_items_indices [i]];
1651 item.DisplayIndex = i;
1657 internal void ChangeItemLocation (int display_index, Point new_pos)
1659 int new_display_index = GetDisplayIndexFromLocation (new_pos);
1660 if (new_display_index == display_index)
1663 int item_index = reordered_items_indices [display_index];
1664 ListViewItem item = items [item_index];
1666 bool forward = new_display_index < display_index;
1667 int index_from, index_to;
1669 index_from = new_display_index;
1670 index_to = display_index - 1;
1672 index_from = display_index + 1;
1673 index_to = new_display_index;
1676 ShiftItemsPositions (index_from, index_to, forward);
1678 reordered_items_indices [new_display_index] = item_index;
1681 item.DisplayIndex = new_display_index;
1685 int GetDisplayIndexFromLocation (Point loc)
1687 int display_index = -1;
1688 Rectangle item_area;
1691 if (loc.X < 0 || loc.Y < 0)
1694 // Adjustment to put in the next position refered by 'loc'
1695 loc.X -= item_size.Width / 2;
1699 for (int i = 0; i < items.Count; i++) {
1700 item_area = new Rectangle (GetItemLocation (i), item_size);
1701 item_area.Inflate (ThemeEngine.Current.ListViewHorizontalSpacing,
1702 ThemeEngine.Current.ListViewVerticalSpacing);
1704 if (item_area.Contains (loc)) {
1710 // Put in in last position
1711 if (display_index == -1)
1712 display_index = items.Count - 1;
1714 return display_index;
1717 // When using groups, the items with no group assigned
1718 // belong to the DefaultGroup
1719 int GetDefaultGroupItems ()
1722 foreach (ListViewItem item in items)
1723 if (item.Group == null)
1731 // cache the spacing to let virtualmode compute the positions on the fly
1737 int[,] item_index_matrix;
1739 void CalculateRowsAndCols (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1741 Rectangle area = ClientRectangle;
1743 if (UseCustomColumnWidth)
1744 CalculateCustomColumnWidth ();
1747 // When groups are used the alignment is always top-aligned
1752 groups.DefaultGroup.ItemCount = GetDefaultGroupItems ();
1753 for (int i = 0; i < groups.InternalCount; i++) {
1754 ListViewGroup group = groups.GetInternalGroup (i);
1755 int items_in_group = group.GetActualItemCount ();
1757 if (items_in_group == 0)
1760 int group_cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
1761 if (group_cols <= 0)
1763 int group_rows = (int) Math.Ceiling ((double)items_in_group / (double)group_cols);
1765 group.starting_row = rows;
1766 group.rows = group_rows;
1767 group.starting_item = items;
1768 group.current_item = 0; // Reset layout
1770 cols = Math.Max (group_cols, cols);
1772 items += items_in_group;
1777 // Simple matrix if no groups are used
1779 rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(item_size.Height + y_spacing));
1782 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
1784 if (UseCustomColumnWidth)
1785 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width) / (double)(custom_column_width));
1787 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
1792 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
1796 item_index_matrix = new int [rows, cols];
1799 // When using custom column width, we look for the minimum one
1800 void CalculateCustomColumnWidth ()
1802 int min_width = Int32.MaxValue;
1803 for (int i = 0; i < columns.Count; i++) {
1804 int col_width = columns [i].Width;
1806 if (col_width < min_width)
1807 min_width = col_width;
1810 custom_column_width = min_width;
1813 void LayoutIcons (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1815 header_control.Visible = false;
1816 header_control.Size = Size.Empty;
1817 item_control.Visible = true;
1818 item_control.Location = Point.Empty;
1819 ItemSize = item_size; // Cache item size
1821 this.x_spacing = x_spacing;
1822 this.y_spacing = y_spacing;
1825 if (items.Count == 0)
1828 Size sz = item_size;
1830 CalculateRowsAndCols (sz, left_aligned, x_spacing, y_spacing);
1832 layout_wd = UseCustomColumnWidth ? cols * custom_column_width : cols * (sz.Width + x_spacing) - x_spacing;
1833 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
1836 if (virtual_mode) { // no actual assignment is needed on items for virtual mode
1837 item_control.Size = new Size (layout_wd, layout_ht);
1841 bool using_groups = UsingGroups;
1842 if (using_groups) // the groups layout will override layout_ht
1843 CalculateGroupsLayout (sz, y_spacing, 0);
1846 int row = 0, col = 0;
1848 int display_index = 0;
1850 for (int i = 0; i < items.Count; i++) {
1851 ListViewItem item = items [i];
1854 ListViewGroup group = item.Group;
1856 group = groups.DefaultGroup;
1858 Point group_items_loc = group.items_area_location;
1859 int current_item = group.current_item++;
1860 int starting_row = group.starting_row;
1862 display_index = group.starting_item + current_item;
1863 row = (current_item / cols);
1864 col = current_item % cols;
1866 x = UseCustomColumnWidth ? col * custom_column_width : col * (item_size.Width + x_spacing);
1867 y = row * (item_size.Height + y_spacing) + group_items_loc.Y;
1869 SetItemLocation (display_index, x, y, row + starting_row, col);
1870 SetItemAtDisplayIndex (display_index, i);
1871 item_index_matrix [row + starting_row, col] = i;
1876 x = UseCustomColumnWidth ? col * custom_column_width : col * (item_size.Width + x_spacing);
1877 y = row * (item_size.Height + y_spacing);
1878 display_index = i; // Same as item index in Items
1880 SetItemLocation (i, x, y, row, col);
1881 item_index_matrix [row, col] = i;
1890 if (++col == cols) {
1898 item.DisplayIndex = display_index;
1900 item.SetPosition (new Point (x, y));
1904 item_control.Size = new Size (layout_wd, layout_ht);
1908 void CalculateGroupsLayout (Size item_size, int y_spacing, int y_origin)
1911 bool details = view == View.Details;
1913 for (int i = 0; i < groups.InternalCount; i++) {
1914 ListViewGroup group = groups.GetInternalGroup (i);
1915 if (group.ItemCount == 0)
1918 y += LayoutGroupHeader (group, y, item_size.Height, y_spacing, details ? group.ItemCount : group.rows);
1921 layout_ht = y; // Update height taking into account Groups' headers heights
1924 int LayoutGroupHeader (ListViewGroup group, int y_origin, int item_height, int y_spacing, int rows)
1926 Rectangle client_area = ClientRectangle;
1927 int header_height = Font.Height + 15; // one line height + some padding
1929 group.HeaderBounds = new Rectangle (0, y_origin, client_area.Width - v_scroll.Width, header_height);
1930 group.items_area_location = new Point (0, y_origin + header_height);
1932 int items_area_height = ((item_height + y_spacing) * rows);
1933 return header_height + items_area_height + 10; // Add a small bottom margin
1936 void CalculateDetailsGroupItemsCount ()
1940 groups.DefaultGroup.ItemCount = GetDefaultGroupItems ();
1941 for (int i = 0; i < groups.InternalCount; i++) {
1942 ListViewGroup group = groups.GetInternalGroup (i);
1943 int items_in_group = group.GetActualItemCount ();
1945 if (items_in_group == 0)
1948 group.starting_item = items;
1949 group.current_item = 0; // Reset layout.
1950 items += items_in_group;
1955 void LayoutHeader ()
1958 for (int i = 0; i < Columns.Count; i++) {
1959 ColumnHeader col = GetReorderedColumn (i);
1962 col.CalcColumnHeader ();
1968 if (x < ClientRectangle.Width)
1969 x = ClientRectangle.Width;
1971 if (header_style == ColumnHeaderStyle.None) {
1972 header_control.Visible = false;
1973 header_control.Size = Size.Empty;
1974 layout_wd = ClientRectangle.Width;
1976 header_control.Width = x;
1977 header_control.Height = columns.Count > 0 ? columns [0].Ht : ThemeEngine.Current.ListViewGetHeaderHeight (this, Font);
1978 header_control.Visible = true;
1982 void LayoutDetails ()
1986 if (columns.Count == 0) {
1987 item_control.Visible = false;
1988 layout_wd = ClientRectangle.Width;
1989 layout_ht = ClientRectangle.Height;
1993 item_control.Visible = true;
1994 item_control.Location = Point.Empty;
1995 item_control.Width = ClientRectangle.Width;
1997 int item_height = GetDetailsItemHeight ();
1998 ItemSize = new Size (0, item_height); // We only cache Height for details view
1999 int y = header_control.Height;
2000 layout_ht = y + (item_height * items.Count);
2001 if (items.Count > 0 && grid_lines) // some space for bottom gridline
2005 bool using_groups = UsingGroups;
2007 // Observe that this routines will override our layout_ht value
2008 CalculateDetailsGroupItemsCount ();
2009 CalculateGroupsLayout (ItemSize, 2, y);
2012 if (virtual_mode) // no assgination on items is needed
2016 for (int i = 0; i < items.Count; i++) {
2017 ListViewItem item = items [i];
2024 ListViewGroup group = item.Group;
2026 group = groups.DefaultGroup;
2028 int current_item = group.current_item++;
2029 Point group_items_loc = group.items_area_location;
2030 display_index = group.starting_item + current_item;
2032 y = item_y = current_item * (item_height + 2) + group_items_loc.Y;
2033 SetItemLocation (display_index, 0, item_y, 0, 0);
2034 SetItemAtDisplayIndex (display_index, i);
2040 SetItemLocation (i, 0, item_y, 0, 0);
2045 item.DisplayIndex = display_index;
2047 item.SetPosition (new Point (0, item_y));
2052 private void AdjustItemsPositionArray (int count)
2055 // In virtual mode we compute the positions on the fly.
2059 if (items_location.Length >= count)
2062 // items_location, items_matrix_location and reordered_items_indices must keep the same length
2063 count = Math.Max (count, items_location.Length * 2);
2064 items_location = new Point [count];
2065 items_matrix_location = new ItemMatrixLocation [count];
2066 reordered_items_indices = new int [count];
2069 private void CalculateListView (ListViewAlignment align)
2073 AdjustItemsPositionArray (items.Count);
2080 case View.SmallIcon:
2081 LayoutIcons (SmallIconItemSize, alignment == ListViewAlignment.Left,
2082 ThemeEngine.Current.ListViewHorizontalSpacing, 2);
2085 case View.LargeIcon:
2086 LayoutIcons (LargeIconItemSize, alignment == ListViewAlignment.Left,
2087 ThemeEngine.Current.ListViewHorizontalSpacing,
2088 ThemeEngine.Current.ListViewVerticalSpacing);
2092 LayoutIcons (SmallIconItemSize, true,
2093 ThemeEngine.Current.ListViewHorizontalSpacing, 2);
2097 if (!Application.VisualStylesEnabled)
2098 goto case View.LargeIcon;
2100 LayoutIcons (TileItemSize, alignment == ListViewAlignment.Left,
2101 ThemeEngine.Current.ListViewHorizontalSpacing,
2102 ThemeEngine.Current.ListViewVerticalSpacing);
2107 CalculateScrollBars ();
2110 internal Point GetItemLocation (int index)
2112 Point loc = Point.Empty;
2115 loc = GetFixedItemLocation (index);
2118 loc = items_location [index];
2120 loc.X -= h_marker; // Adjust to scroll
2127 Point GetFixedItemLocation (int index)
2129 Point loc = Point.Empty;
2132 case View.LargeIcon:
2133 case View.SmallIcon:
2134 loc.X = index % cols * (item_size.Width + x_spacing);
2135 loc.Y = index / cols * (item_size.Height + y_spacing);
2138 loc.X = index / rows * (item_size.Width + x_spacing);
2139 loc.Y = index % rows * (item_size.Height + y_spacing);
2142 loc.Y = header_control.Height + (index * item_size.Height);
2150 internal int GetItemIndex (int display_index)
2154 return display_index; // no reordering in virtual mode.
2156 return reordered_items_indices [display_index];
2159 internal ListViewItem GetItemAtDisplayIndex (int display_index)
2162 // in virtual mode there's no reordering at all.
2164 return items [display_index];
2166 return items [reordered_items_indices [display_index]];
2169 internal void SetItemAtDisplayIndex (int display_index, int index)
2171 reordered_items_indices [display_index] = index;
2174 private bool KeySearchString (KeyEventArgs ke)
2176 int current_tickcnt = Environment.TickCount;
2177 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
2178 keysearch_text = string.Empty;
2181 if (!Char.IsLetterOrDigit ((char)ke.KeyCode))
2184 keysearch_text += (char)ke.KeyCode;
2185 keysearch_tickcnt = current_tickcnt;
2187 int prev_focused = FocusedItem == null ? 0 : FocusedItem.DisplayIndex;
2188 int start = prev_focused + 1 < Items.Count ? prev_focused + 1 : 0;
2190 ListViewItem item = FindItemWithText (keysearch_text, false, start, true, true);
2191 if (item != null && prev_focused != item.DisplayIndex) {
2192 selected_indices.Clear ();
2194 SetFocusedItem (item.DisplayIndex);
2195 item.Selected = true;
2196 EnsureVisible (GetItemIndex (item.DisplayIndex));
2202 private void OnItemsChanged ()
2204 ResetSearchString ();
2207 private void ResetSearchString ()
2209 keysearch_text = String.Empty;
2212 int GetAdjustedIndex (Keys key)
2216 if (View == View.Details) {
2219 result = FocusedItem.DisplayIndex - 1;
2222 result = FocusedItem.DisplayIndex + 1;
2223 if (result == items.Count)
2227 int last_index = LastVisibleIndex;
2228 Rectangle item_rect = new Rectangle (GetItemLocation (last_index), ItemSize);
2229 if (item_rect.Bottom > item_control.ClientRectangle.Bottom)
2231 if (FocusedItem.DisplayIndex == last_index) {
2232 if (FocusedItem.DisplayIndex < Items.Count - 1) {
2233 int page_size = item_control.Height / ItemSize.Height - 1;
2234 result = FocusedItem.DisplayIndex + page_size - 1;
2235 if (result >= Items.Count)
2236 result = Items.Count - 1;
2239 result = last_index;
2242 int first_index = FirstVisibleIndex;
2243 if (GetItemLocation (first_index).Y < 0)
2245 if (FocusedItem.DisplayIndex == first_index) {
2246 if (first_index > 0) {
2247 int page_size = item_control.Height / ItemSize.Height - 1;
2248 result = first_index - page_size + 1;
2253 result = first_index;
2259 ItemMatrixLocation item_matrix_location = items_matrix_location [FocusedItem.DisplayIndex];
2260 int row = item_matrix_location.Row;
2261 int col = item_matrix_location.Col;
2263 int adjusted_index = -1;
2269 adjusted_index = item_index_matrix [row, col - 1];
2273 if (col == (cols - 1))
2275 while (item_index_matrix [row, col + 1] == 0) {
2280 adjusted_index = item_index_matrix [row, col + 1];
2286 while (item_index_matrix [row - 1, col] == 0 && row != 1) {
2291 adjusted_index = item_index_matrix [row - 1, col];
2295 if (row == (rows - 1) || row == Items.Count - 1)
2297 while (item_index_matrix [row + 1, col] == 0) {
2302 adjusted_index = item_index_matrix [row + 1, col];
2309 return items [adjusted_index].DisplayIndex;
2312 ListViewItem selection_start;
2314 private bool SelectItems (ArrayList sel_items)
2316 bool changed = false;
2317 foreach (ListViewItem item in SelectedItems)
2318 if (!sel_items.Contains (item)) {
2319 item.Selected = false;
2322 foreach (ListViewItem item in sel_items)
2323 if (!item.Selected) {
2324 item.Selected = true;
2330 private void UpdateMultiSelection (int index, bool reselect)
2332 bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
2333 bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
2334 ListViewItem item = GetItemAtDisplayIndex (index);
2336 if (shift_pressed && selection_start != null) {
2337 ArrayList list = new ArrayList ();
2338 int start_index = selection_start.DisplayIndex;
2339 int start = Math.Min (start_index, index);
2340 int end = Math.Max (start_index, index);
2341 if (View == View.Details) {
2342 for (int i = start; i <= end; i++)
2343 list.Add (GetItemAtDisplayIndex (i));
2345 ItemMatrixLocation start_item_matrix_location = items_matrix_location [start];
2346 ItemMatrixLocation end_item_matrix_location = items_matrix_location [end];
2347 int left = Math.Min (start_item_matrix_location.Col, end_item_matrix_location.Col);
2348 int right = Math.Max (start_item_matrix_location.Col, end_item_matrix_location.Col);
2349 int top = Math.Min (start_item_matrix_location.Row, end_item_matrix_location.Row);
2350 int bottom = Math.Max (start_item_matrix_location.Row, end_item_matrix_location.Row);
2352 for (int i = 0; i < items.Count; i++) {
2353 ItemMatrixLocation item_matrix_loc = items_matrix_location [i];
2355 if (item_matrix_loc.Row >= top && item_matrix_loc.Row <= bottom &&
2356 item_matrix_loc.Col >= left && item_matrix_loc.Col <= right)
2357 list.Add (GetItemAtDisplayIndex (i));
2361 } else if (ctrl_pressed) {
2362 item.Selected = !item.Selected;
2363 selection_start = item;
2366 // do not unselect, and reselect the item
2367 foreach (int itemIndex in SelectedIndices) {
2368 if (index == itemIndex)
2370 items [itemIndex].Selected = false;
2373 SelectedItems.Clear ();
2374 item.Selected = true;
2376 selection_start = item;
2380 internal override bool InternalPreProcessMessage (ref Message msg)
2382 if (msg.Msg == (int)Msg.WM_KEYDOWN) {
2383 Keys key_data = (Keys)msg.WParam.ToInt32();
2385 HandleNavKeys (key_data);
2388 return base.InternalPreProcessMessage (ref msg);
2391 bool HandleNavKeys (Keys key_data)
2393 if (Items.Count == 0 || !item_control.Visible)
2396 if (FocusedItem == null)
2401 SelectIndex (Items.Count - 1);
2414 SelectIndex (GetAdjustedIndex (key_data));
2418 SelectIndex (focused_item_index);
2419 ToggleItemsCheckState ();
2422 if (selected_indices.Count > 0)
2423 OnItemActivate (EventArgs.Empty);
2433 void ToggleItemsCheckState ()
2438 // Don't modify check state if StateImageList has less than 2 elements
2439 if (StateImageList != null && StateImageList.Images.Count < 2)
2442 if (SelectedIndices.Count > 0) {
2443 for (int i = 0; i < SelectedIndices.Count; i++) {
2444 ListViewItem item = Items [SelectedIndices [i]];
2445 item.Checked = !item.Checked;
2450 if (FocusedItem != null) {
2451 FocusedItem.Checked = !FocusedItem.Checked;
2452 SelectIndex (FocusedItem.Index);
2456 void SelectIndex (int display_index)
2458 if (display_index == -1)
2462 UpdateMultiSelection (display_index, true);
2463 else if (!GetItemAtDisplayIndex (display_index).Selected)
2464 GetItemAtDisplayIndex (display_index).Selected = true;
2466 SetFocusedItem (display_index);
2467 EnsureVisible (GetItemIndex (display_index)); // Index in Items collection, not display index
2470 private void ListView_KeyDown (object sender, KeyEventArgs ke)
2472 if (ke.Handled || Items.Count == 0 || !item_control.Visible)
2475 if (ke.Alt || ke.Control)
2478 ke.Handled = KeySearchString (ke);
2481 private MouseEventArgs TranslateMouseEventArgs (MouseEventArgs args)
2483 Point loc = PointToClient (Control.MousePosition);
2484 return new MouseEventArgs (args.Button, args.Clicks, loc.X, loc.Y, args.Delta);
2487 internal class ItemControl : Control {
2490 ListViewItem clicked_item;
2491 ListViewItem last_clicked_item;
2492 bool hover_processed = false;
2493 bool checking = false;
2494 ListViewItem prev_hovered_item;
2496 ListViewItem prev_tooltip_item;
2499 Point drag_begin = new Point (-1, -1);
2500 internal int dragged_item_index = -1;
2502 ListViewLabelEditTextBox edit_text_box;
2503 internal ListViewItem edit_item;
2504 LabelEditEventArgs edit_args;
2506 public ItemControl (ListView owner)
2509 this.SetStyle (ControlStyles.DoubleBuffer, true);
2510 DoubleClick += new EventHandler(ItemsDoubleClick);
2511 MouseDown += new MouseEventHandler(ItemsMouseDown);
2512 MouseMove += new MouseEventHandler(ItemsMouseMove);
2513 MouseHover += new EventHandler(ItemsMouseHover);
2514 MouseUp += new MouseEventHandler(ItemsMouseUp);
2517 void ItemsDoubleClick (object sender, EventArgs e)
2519 if (owner.activation == ItemActivation.Standard)
2520 owner.OnItemActivate (EventArgs.Empty);
2530 BoxSelect box_select_mode = BoxSelect.None;
2531 IList prev_selection;
2532 Point box_select_start;
2534 Rectangle box_select_rect;
2535 internal Rectangle BoxSelectRectangle {
2536 get { return box_select_rect; }
2538 if (box_select_rect == value)
2541 InvalidateBoxSelectRect ();
2542 box_select_rect = value;
2543 InvalidateBoxSelectRect ();
2547 void InvalidateBoxSelectRect ()
2549 if (BoxSelectRectangle.Size.IsEmpty)
2552 Rectangle edge = BoxSelectRectangle;
2558 edge.Y = BoxSelectRectangle.Bottom - 1;
2560 edge.Y = BoxSelectRectangle.Y - 1;
2562 edge.Height = BoxSelectRectangle.Height + 2;
2564 edge.X = BoxSelectRectangle.Right - 1;
2568 private Rectangle CalculateBoxSelectRectangle (Point pt)
2570 int left = Math.Min (box_select_start.X, pt.X);
2571 int right = Math.Max (box_select_start.X, pt.X);
2572 int top = Math.Min (box_select_start.Y, pt.Y);
2573 int bottom = Math.Max (box_select_start.Y, pt.Y);
2574 return Rectangle.FromLTRB (left, top, right, bottom);
2577 bool BoxIntersectsItem (int index)
2579 Rectangle r = new Rectangle (owner.GetItemLocation (index), owner.ItemSize);
2580 if (owner.View != View.Details) {
2582 r.Y += r.Height / 4;
2586 return BoxSelectRectangle.IntersectsWith (r);
2589 bool BoxIntersectsText (int index)
2591 Rectangle r = owner.GetItemAtDisplayIndex (index).TextBounds;
2592 return BoxSelectRectangle.IntersectsWith (r);
2595 ArrayList BoxSelectedItems {
2597 ArrayList result = new ArrayList ();
2598 for (int i = 0; i < owner.Items.Count; i++) {
2601 // Can't iterate over specific items properties in virtualmode
2602 if (owner.View == View.Details && !owner.FullRowSelect && !owner.VirtualMode)
2604 if (owner.View == View.Details && !owner.FullRowSelect)
2606 intersects = BoxIntersectsText (i);
2608 intersects = BoxIntersectsItem (i);
2611 result.Add (owner.GetItemAtDisplayIndex (i));
2617 private bool PerformBoxSelection (Point pt)
2619 if (box_select_mode == BoxSelect.None)
2622 BoxSelectRectangle = CalculateBoxSelectRectangle (pt);
2624 ArrayList box_items = BoxSelectedItems;
2628 switch (box_select_mode) {
2630 case BoxSelect.Normal:
2634 case BoxSelect.Control:
2635 items = new ArrayList ();
2636 foreach (int index in prev_selection)
2637 if (!box_items.Contains (owner.Items [index]))
2638 items.Add (owner.Items [index]);
2639 foreach (ListViewItem item in box_items)
2640 if (!prev_selection.Contains (item.Index))
2644 case BoxSelect.Shift:
2646 foreach (ListViewItem item in box_items)
2647 prev_selection.Remove (item.Index);
2648 foreach (int index in prev_selection)
2649 items.Add (owner.Items [index]);
2653 throw new Exception ("Unexpected Selection mode: " + box_select_mode);
2657 owner.SelectItems (items);
2663 private void ItemsMouseDown (object sender, MouseEventArgs me)
2665 owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
2666 if (owner.items.Count == 0)
2669 bool box_selecting = false;
2670 Size item_size = owner.ItemSize;
2671 Point pt = new Point (me.X, me.Y);
2672 for (int i = 0; i < owner.items.Count; i++) {
2673 Rectangle item_rect = new Rectangle (owner.GetItemLocation (i), item_size);
2674 if (!item_rect.Contains (pt))
2677 // Actual item in 'i' position
2678 ListViewItem item = owner.GetItemAtDisplayIndex (i);
2680 if (item.CheckRectReal.Contains (pt)) {
2681 // Don't modify check state if we have only one image
2682 // and if we are in 1.1 profile only take into account
2684 if (owner.StateImageList != null && owner.StateImageList.Images.Count < 2
2691 // Generate an extra ItemCheck event when we got two clicks
2692 // (Match weird .Net behaviour)
2694 item.Checked = !item.Checked;
2696 item.Checked = !item.Checked;
2701 if (owner.View == View.Details) {
2702 bool over_text = item.TextBounds.Contains (pt);
2703 if (owner.FullRowSelect) {
2704 clicked_item = item;
2705 bool over_item_column = (me.X > owner.Columns[0].X && me.X < owner.Columns[0].X + owner.Columns[0].Width);
2706 if (!over_text && over_item_column && owner.MultiSelect)
2707 box_selecting = true;
2708 } else if (over_text)
2709 clicked_item = item;
2711 owner.SetFocusedItem (i);
2713 clicked_item = item;
2719 if (clicked_item != null) {
2720 bool changed = !clicked_item.Selected;
2721 if (me.Button == MouseButtons.Left || (XplatUI.State.ModifierKeys == Keys.None && changed))
2722 owner.SetFocusedItem (clicked_item.DisplayIndex);
2724 if (owner.MultiSelect) {
2725 bool reselect = (!owner.LabelEdit || changed);
2726 if (me.Button == MouseButtons.Left || (XplatUI.State.ModifierKeys == Keys.None && changed))
2727 owner.UpdateMultiSelection (clicked_item.DisplayIndex, reselect);
2729 clicked_item.Selected = true;
2733 if (owner.VirtualMode && changed) {
2734 // Broken event - It's not fired from Item.Selected also
2735 ListViewVirtualItemsSelectionRangeChangedEventArgs args =
2736 new ListViewVirtualItemsSelectionRangeChangedEventArgs (0, owner.items.Count - 1, false);
2738 owner.OnVirtualItemsSelectionRangeChanged (args);
2741 // Report clicks only if the item was clicked. On MS the
2742 // clicks are only raised if you click an item
2744 if (me.Clicks > 1) {
2745 if (owner.CheckBoxes)
2746 clicked_item.Checked = !clicked_item.Checked;
2747 } else if (me.Clicks == 1) {
2748 if (owner.LabelEdit && !changed)
2749 BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
2752 if (owner.MultiSelect)
2753 box_selecting = true;
2754 else if (owner.SelectedItems.Count > 0)
2755 owner.SelectedItems.Clear ();
2758 if (box_selecting) {
2759 Keys mods = XplatUI.State.ModifierKeys;
2760 if ((mods & Keys.Shift) != 0)
2761 box_select_mode = BoxSelect.Shift;
2762 else if ((mods & Keys.Control) != 0)
2763 box_select_mode = BoxSelect.Control;
2765 box_select_mode = BoxSelect.Normal;
2766 box_select_start = pt;
2767 prev_selection = owner.SelectedIndices.List.Clone () as IList;
2771 private void ItemsMouseMove (object sender, MouseEventArgs me)
2773 bool done = PerformBoxSelection (new Point (me.X, me.Y));
2775 owner.OnMouseMove (owner.TranslateMouseEventArgs (me));
2779 if ((me.Button != MouseButtons.Left && me.Button != MouseButtons.Right) &&
2780 !hover_processed && owner.Activation != ItemActivation.OneClick
2782 && !owner.ShowItemToolTips
2787 Point pt = PointToClient (Control.MousePosition);
2788 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
2790 if (hover_processed && item != null && item != prev_hovered_item) {
2791 hover_processed = false;
2792 XplatUI.ResetMouseHover (Handle);
2795 // Need to invalidate the item in HotTracking to show/hide the underline style
2796 if (owner.Activation == ItemActivation.OneClick) {
2797 if (item == null && owner.HotItemIndex != -1) {
2799 if (owner.HotTracking)
2800 Invalidate (owner.Items [owner.HotItemIndex].Bounds); // Previous one
2803 Cursor = Cursors.Default;
2804 owner.HotItemIndex = -1;
2805 } else if (item != null && owner.HotItemIndex == -1) {
2807 if (owner.HotTracking)
2808 Invalidate (item.Bounds);
2811 Cursor = Cursors.Hand;
2812 owner.HotItemIndex = item.Index;
2816 if (me.Button == MouseButtons.Left || me.Button == MouseButtons.Right) {
2817 if (drag_begin.X == -1 && drag_begin.Y == -1) {
2819 drag_begin = new Point (me.X, me.Y);
2820 dragged_item_index = item.Index;
2824 Rectangle r = new Rectangle (drag_begin, SystemInformation.DragSize);
2825 if (!r.Contains (me.X, me.Y)) {
2826 ListViewItem dragged_item = owner.items [dragged_item_index];
2827 owner.OnItemDrag (new ItemDragEventArgs (me.Button, dragged_item));
2829 drag_begin = new Point (-1, -1);
2830 dragged_item_index = -1;
2836 if (owner.ShowItemToolTips) {
2838 owner.item_tooltip.Active = false;
2839 prev_tooltip_item = null;
2840 } else if (item != prev_tooltip_item && item.ToolTipText.Length > 0) {
2841 owner.item_tooltip.Active = true;
2842 owner.item_tooltip.SetToolTip (owner, item.ToolTipText);
2843 prev_tooltip_item = item;
2850 private void ItemsMouseHover (object sender, EventArgs e)
2852 if (owner.hover_pending) {
2853 owner.OnMouseHover (e);
2854 owner.hover_pending = false;
2860 hover_processed = true;
2861 Point pt = PointToClient (Control.MousePosition);
2862 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
2866 prev_hovered_item = item;
2868 if (owner.HoverSelection) {
2869 if (owner.MultiSelect)
2870 owner.UpdateMultiSelection (item.Index, true);
2872 item.Selected = true;
2874 owner.SetFocusedItem (item.DisplayIndex);
2875 Select (); // Make sure we have the focus, since MouseHover doesn't give it to us
2879 owner.OnItemMouseHover (new ListViewItemMouseHoverEventArgs (item));
2883 void HandleClicks (MouseEventArgs me)
2885 // if the click is not on an item,
2886 // clicks remains as 0
2889 owner.OnDoubleClick (EventArgs.Empty);
2890 } else if (clicks == 1) {
2891 owner.OnClick (EventArgs.Empty);
2893 owner.OnDoubleClick (EventArgs.Empty);
2894 owner.OnMouseDoubleClick (me);
2895 } else if (clicks == 1) {
2896 owner.OnClick (EventArgs.Empty);
2897 owner.OnMouseClick (me);
2904 private void ItemsMouseUp (object sender, MouseEventArgs me)
2906 MouseEventArgs owner_me = owner.TranslateMouseEventArgs (me);
2907 HandleClicks (owner_me);
2910 if (owner.Items.Count == 0) {
2912 owner.OnMouseUp (owner_me);
2916 Point pt = new Point (me.X, me.Y);
2918 Rectangle rect = Rectangle.Empty;
2919 if (clicked_item != null) {
2920 if (owner.view == View.Details && !owner.full_row_select)
2921 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
2923 rect = clicked_item.Bounds;
2925 if (rect.Contains (pt)) {
2926 switch (owner.activation) {
2927 case ItemActivation.OneClick:
2928 owner.OnItemActivate (EventArgs.Empty);
2931 case ItemActivation.TwoClick:
2932 if (last_clicked_item == clicked_item) {
2933 owner.OnItemActivate (EventArgs.Empty);
2934 last_clicked_item = null;
2936 last_clicked_item = clicked_item;
2939 // DoubleClick activation is handled in another handler
2943 } else if (!checking && owner.SelectedItems.Count > 0 && BoxSelectRectangle.Size.IsEmpty) {
2944 // Need this to clean up background clicks
2945 owner.SelectedItems.Clear ();
2949 owner.OnMouseUp (owner_me);
2952 private void ResetMouseState ()
2954 clicked_item = null;
2955 box_select_start = Point.Empty;
2956 BoxSelectRectangle = Rectangle.Empty;
2957 prev_selection = null;
2958 box_select_mode = BoxSelect.None;
2961 // Clean these bits in case the mouse buttons were
2962 // released before firing ItemDrag
2963 dragged_item_index = -1;
2964 drag_begin = new Point (-1, -1);
2967 private void LabelEditFinished (object sender, EventArgs e)
2969 EndEdit (edit_item);
2972 private void LabelEditCancelled (object sender, EventArgs e)
2974 edit_args.SetLabel (null);
2975 EndEdit (edit_item);
2978 private void LabelTextChanged (object sender, EventArgs e)
2980 if (edit_args != null)
2981 edit_args.SetLabel (edit_text_box.Text);
2984 internal void BeginEdit (ListViewItem item)
2986 if (edit_item != null)
2987 EndEdit (edit_item);
2989 if (edit_text_box == null) {
2990 edit_text_box = new ListViewLabelEditTextBox ();
2991 edit_text_box.BorderStyle = BorderStyle.FixedSingle;
2992 edit_text_box.EditingCancelled += new EventHandler (LabelEditCancelled);
2993 edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
2994 edit_text_box.TextChanged += new EventHandler (LabelTextChanged);
2995 edit_text_box.Visible = false;
2996 Controls.Add (edit_text_box);
2999 item.EnsureVisible();
3001 edit_text_box.Reset ();
3003 switch (owner.view) {
3005 case View.SmallIcon:
3007 edit_text_box.TextAlign = HorizontalAlignment.Left;
3008 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
3009 SizeF sizef = TextRenderer.MeasureString (item.Text, item.Font);
3010 edit_text_box.Width = (int)sizef.Width + 4;
3011 edit_text_box.MaxWidth = owner.ClientRectangle.Width - edit_text_box.Bounds.X;
3012 edit_text_box.WordWrap = false;
3013 edit_text_box.Multiline = false;
3015 case View.LargeIcon:
3016 edit_text_box.TextAlign = HorizontalAlignment.Center;
3017 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
3018 sizef = TextRenderer.MeasureString (item.Text, item.Font);
3019 edit_text_box.Width = (int)sizef.Width + 4;
3020 edit_text_box.MaxWidth = item.GetBounds(ItemBoundsPortion.Entire).Width;
3021 edit_text_box.MaxHeight = owner.ClientRectangle.Height - edit_text_box.Bounds.Y;
3022 edit_text_box.WordWrap = true;
3023 edit_text_box.Multiline = true;
3029 edit_text_box.Text = item.Text;
3030 edit_text_box.Font = item.Font;
3031 edit_text_box.Visible = true;
3032 edit_text_box.Focus ();
3033 edit_text_box.SelectAll ();
3035 edit_args = new LabelEditEventArgs (owner.Items.IndexOf (edit_item));
3036 owner.OnBeforeLabelEdit (edit_args);
3038 if (edit_args.CancelEdit)
3042 internal void CancelEdit (ListViewItem item)
3044 // do nothing if there's no item being edited, or if the
3045 // item being edited is not the one passed in
3046 if (edit_item == null || edit_item != item)
3049 edit_args.SetLabel (null);
3053 internal void EndEdit (ListViewItem item)
3055 // do nothing if there's no item being edited, or if the
3056 // item being edited is not the one passed in
3057 if (edit_item == null || edit_item != item)
3060 if (edit_text_box != null) {
3061 if (edit_text_box.Visible)
3062 edit_text_box.Visible = false;
3063 // ensure listview gets focus
3067 // Same as TreeView.EndEdit: need to have focus in synch
3068 Application.DoEvents ();
3071 // Create a new instance, since we could get a call to BeginEdit
3072 // from the handler and have fields out of synch
3074 LabelEditEventArgs args = new LabelEditEventArgs (item.Index, edit_args.Label);
3077 owner.OnAfterLabelEdit (args);
3078 if (!args.CancelEdit && args.Label != null)
3079 item.Text = args.Label;
3082 internal override void OnPaintInternal (PaintEventArgs pe)
3084 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
3087 protected override void WndProc (ref Message m)
3089 switch ((Msg)m.Msg) {
3090 case Msg.WM_KILLFOCUS:
3091 owner.Select (false, true);
3093 case Msg.WM_SETFOCUS:
3094 owner.Select (false, true);
3096 case Msg.WM_LBUTTONDOWN:
3098 owner.Select (false, true);
3100 case Msg.WM_RBUTTONDOWN:
3102 owner.Select (false, true);
3107 base.WndProc (ref m);
3111 internal class ListViewLabelEditTextBox : TextBox
3116 int max_height = -1;
3117 int min_height = -1;
3119 int old_number_lines = 1;
3121 SizeF text_size_one_char;
3123 public ListViewLabelEditTextBox ()
3125 min_height = DefaultSize.Height;
3126 text_size_one_char = TextRenderer.MeasureString ("B", Font);
3129 public int MaxWidth {
3131 if (value < min_width)
3132 max_width = min_width;
3138 public int MaxHeight {
3140 if (value < min_height)
3141 max_height = min_height;
3147 public new int Width {
3157 public override Font Font {
3163 text_size_one_char = TextRenderer.MeasureString ("B", Font);
3167 protected override void OnTextChanged (EventArgs e)
3169 SizeF text_size = TextRenderer.MeasureString (Text, Font);
3171 int new_width = (int)text_size.Width + 8;
3174 ResizeTextBoxWidth (new_width);
3176 if (Width != max_width)
3177 ResizeTextBoxWidth (new_width);
3179 int number_lines = Lines.Length;
3181 if (number_lines != old_number_lines) {
3182 int new_height = number_lines * (int)text_size_one_char.Height + 4;
3183 old_number_lines = number_lines;
3185 ResizeTextBoxHeight (new_height);
3189 base.OnTextChanged (e);
3192 protected override bool IsInputKey (Keys key_data)
3194 if ((key_data & Keys.Alt) == 0) {
3195 switch (key_data & Keys.KeyCode) {
3202 return base.IsInputKey (key_data);
3205 protected override void OnKeyDown (KeyEventArgs e)
3210 switch (e.KeyCode) {
3214 OnEditingFinished (e);
3219 OnEditingCancelled (e);
3224 protected override void OnLostFocus (EventArgs e)
3227 OnEditingFinished (e);
3231 protected void OnEditingCancelled (EventArgs e)
3233 EventHandler eh = (EventHandler)(Events [EditingCancelledEvent]);
3238 protected void OnEditingFinished (EventArgs e)
3240 EventHandler eh = (EventHandler)(Events [EditingFinishedEvent]);
3245 private void ResizeTextBoxWidth (int new_width)
3247 if (new_width > max_width)
3248 base.Width = max_width;
3250 if (new_width >= min_width)
3251 base.Width = new_width;
3253 base.Width = min_width;
3256 private void ResizeTextBoxHeight (int new_height)
3258 if (new_height > max_height)
3259 base.Height = max_height;
3261 if (new_height >= min_height)
3262 base.Height = new_height;
3264 base.Height = min_height;
3267 public void Reset ()
3274 old_number_lines = 1;
3276 Text = String.Empty;
3281 static object EditingCancelledEvent = new object ();
3282 public event EventHandler EditingCancelled {
3283 add { Events.AddHandler (EditingCancelledEvent, value); }
3284 remove { Events.RemoveHandler (EditingCancelledEvent, value); }
3287 static object EditingFinishedEvent = new object ();
3288 public event EventHandler EditingFinished {
3289 add { Events.AddHandler (EditingFinishedEvent, value); }
3290 remove { Events.RemoveHandler (EditingFinishedEvent, value); }
3294 internal override void OnPaintInternal (PaintEventArgs pe)
3299 CalculateScrollBars ();
3302 void FocusChanged (object o, EventArgs args)
3304 if (Items.Count == 0)
3307 if (FocusedItem == null)
3310 ListViewItem focused_item = FocusedItem;
3312 if (focused_item.ListView != null) {
3313 focused_item.Invalidate ();
3314 focused_item.Layout ();
3315 focused_item.Invalidate ();
3319 private void ListView_Invalidated (object sender, InvalidateEventArgs e)
3321 // When the ListView is invalidated, we need to invalidate
3322 // the child controls.
3323 header_control.Invalidate ();
3324 item_control.Invalidate ();
3327 private void ListView_MouseEnter (object sender, EventArgs args)
3329 hover_pending = true; // Need a hover event for every Enter/Leave cycle
3332 private void ListView_MouseWheel (object sender, MouseEventArgs me)
3334 if (Items.Count == 0)
3337 int lines = me.Delta / 120;
3344 case View.SmallIcon:
3345 Scroll (v_scroll, -ItemSize.Height * SystemInformation.MouseWheelScrollLines * lines);
3347 case View.LargeIcon:
3348 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * lines);
3351 Scroll (h_scroll, -ItemSize.Width * lines);
3355 if (!Application.VisualStylesEnabled)
3356 goto case View.LargeIcon;
3358 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * 2 * lines);
3364 private void ListView_SizeChanged (object sender, EventArgs e)
3369 private void SetFocusedItem (int display_index)
3371 if (display_index != -1)
3372 GetItemAtDisplayIndex (display_index).Focused = true;
3373 else if (focused_item_index != -1 && focused_item_index < items.Count) // Previous focused item
3374 GetItemAtDisplayIndex (focused_item_index).Focused = false;
3375 focused_item_index = display_index;
3377 if (display_index == -1)
3378 OnUIAFocusedItemChanged ();
3379 // otherwise the event will have been fired
3380 // when the ListViewItem's Focused was set
3384 private void HorizontalScroller (object sender, EventArgs e)
3386 item_control.EndEdit (item_control.edit_item);
3388 // Avoid unnecessary flickering, when button is
3389 // kept pressed at the end
3390 if (h_marker != h_scroll.Value) {
3392 int pixels = h_marker - h_scroll.Value;
3394 h_marker = h_scroll.Value;
3395 if (header_control.Visible)
3396 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
3398 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
3402 private void VerticalScroller (object sender, EventArgs e)
3404 item_control.EndEdit (item_control.edit_item);
3406 // Avoid unnecessary flickering, when button is
3407 // kept pressed at the end
3408 if (v_marker != v_scroll.Value) {
3409 int pixels = v_marker - v_scroll.Value;
3410 Rectangle area = item_control.ClientRectangle;
3411 if (header_control.Visible) {
3412 area.Y += header_control.Height;
3413 area.Height -= header_control.Height;
3416 v_marker = v_scroll.Value;
3417 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
3421 internal override bool IsInputCharInternal (char charCode)
3425 #endregion // Internal Methods Properties
3427 #region Protected Methods
3428 protected override void CreateHandle ()
3430 base.CreateHandle ();
3431 for (int i = 0; i < SelectedItems.Count; i++)
3432 OnSelectedIndexChanged (EventArgs.Empty);
3435 protected override void Dispose (bool disposing)
3438 h_scroll.Dispose ();
3439 v_scroll.Dispose ();
3441 large_image_list = null;
3442 small_image_list = null;
3443 state_image_list = null;
3445 foreach (ColumnHeader col in columns)
3446 col.SetListView (null);
3449 if (!virtual_mode) // In virtual mode we don't save the items
3451 foreach (ListViewItem item in items)
3455 base.Dispose (disposing);
3458 protected override bool IsInputKey (Keys keyData)
3475 return base.IsInputKey (keyData);
3478 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
3480 LabelEditEventHandler eh = (LabelEditEventHandler)(Events [AfterLabelEditEvent]);
3486 protected override void OnBackgroundImageChanged (EventArgs e)
3488 item_control.BackgroundImage = BackgroundImage;
3489 base.OnBackgroundImageChanged (e);
3493 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
3495 LabelEditEventHandler eh = (LabelEditEventHandler)(Events [BeforeLabelEditEvent]);
3500 protected internal virtual void OnColumnClick (ColumnClickEventArgs e)
3502 ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]);
3508 protected internal virtual void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e)
3510 DrawListViewColumnHeaderEventHandler eh = (DrawListViewColumnHeaderEventHandler)(Events[DrawColumnHeaderEvent]);
3515 protected internal virtual void OnDrawItem(DrawListViewItemEventArgs e)
3517 DrawListViewItemEventHandler eh = (DrawListViewItemEventHandler)(Events[DrawItemEvent]);
3522 protected internal virtual void OnDrawSubItem(DrawListViewSubItemEventArgs e)
3524 DrawListViewSubItemEventHandler eh = (DrawListViewSubItemEventHandler)(Events[DrawSubItemEvent]);
3530 protected override void OnEnabledChanged (EventArgs e)
3532 base.OnEnabledChanged (e);
3536 protected override void OnFontChanged (EventArgs e)
3538 base.OnFontChanged (e);
3542 protected override void OnHandleCreated (EventArgs e)
3544 base.OnHandleCreated (e);
3545 CalculateListView (alignment);
3547 if (!virtual_mode) // Sorting is not allowed in virtual mode
3552 protected override void OnHandleDestroyed (EventArgs e)
3554 base.OnHandleDestroyed (e);
3557 protected virtual void OnItemActivate (EventArgs e)
3559 EventHandler eh = (EventHandler)(Events [ItemActivateEvent]);
3564 protected internal virtual void OnItemCheck (ItemCheckEventArgs ice)
3566 ItemCheckEventHandler eh = (ItemCheckEventHandler)(Events [ItemCheckEvent]);
3572 protected internal virtual void OnItemChecked (ItemCheckedEventArgs e)
3574 ItemCheckedEventHandler eh = (ItemCheckedEventHandler)(Events [ItemCheckedEvent]);
3580 protected virtual void OnItemDrag (ItemDragEventArgs e)
3582 ItemDragEventHandler eh = (ItemDragEventHandler)(Events [ItemDragEvent]);
3588 protected virtual void OnItemMouseHover (ListViewItemMouseHoverEventArgs e)
3590 ListViewItemMouseHoverEventHandler eh = (ListViewItemMouseHoverEventHandler)(Events [ItemMouseHoverEvent]);
3595 protected internal virtual void OnItemSelectionChanged (ListViewItemSelectionChangedEventArgs e)
3597 ListViewItemSelectionChangedEventHandler eh =
3598 (ListViewItemSelectionChangedEventHandler) Events [ItemSelectionChangedEvent];
3603 protected override void OnMouseHover (EventArgs e)
3605 base.OnMouseHover (e);
3608 protected override void OnParentChanged (EventArgs e)
3610 base.OnParentChanged (e);
3614 protected virtual void OnSelectedIndexChanged (EventArgs e)
3616 EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
3621 protected override void OnSystemColorsChanged (EventArgs e)
3623 base.OnSystemColorsChanged (e);
3627 protected internal virtual void OnCacheVirtualItems (CacheVirtualItemsEventArgs e)
3629 CacheVirtualItemsEventHandler eh = (CacheVirtualItemsEventHandler)Events [CacheVirtualItemsEvent];
3634 protected virtual void OnRetrieveVirtualItem (RetrieveVirtualItemEventArgs e)
3636 RetrieveVirtualItemEventHandler eh = (RetrieveVirtualItemEventHandler)Events [RetrieveVirtualItemEvent];
3641 [EditorBrowsable (EditorBrowsableState.Advanced)]
3642 protected virtual void OnRightToLeftLayoutChanged (EventArgs e)
3644 EventHandler eh = (EventHandler)Events[RightToLeftLayoutChangedEvent];
3649 protected virtual void OnSearchForVirtualItem (SearchForVirtualItemEventArgs e)
3651 SearchForVirtualItemEventHandler eh = (SearchForVirtualItemEventHandler) Events [SearchForVirtualItemEvent];
3656 protected virtual void OnVirtualItemsSelectionRangeChanged (ListViewVirtualItemsSelectionRangeChangedEventArgs e)
3658 ListViewVirtualItemsSelectionRangeChangedEventHandler eh =
3659 (ListViewVirtualItemsSelectionRangeChangedEventHandler) Events [VirtualItemsSelectionRangeChangedEvent];
3665 protected void RealizeProperties ()
3670 protected void UpdateExtendedStyles ()
3675 bool refocusing = false;
3677 protected override void WndProc (ref Message m)
3679 switch ((Msg)m.Msg) {
3680 case Msg.WM_KILLFOCUS:
3681 Control receiver = Control.FromHandle (m.WParam);
3682 if (receiver == item_control) {
3688 case Msg.WM_SETFOCUS:
3698 base.WndProc (ref m);
3700 #endregion // Protected Methods
3702 #region Public Instance Methods
3703 public void ArrangeIcons ()
3705 ArrangeIcons (this.alignment);
3708 public void ArrangeIcons (ListViewAlignment value)
3710 // Icons are arranged only if view is set to LargeIcon or SmallIcon
3711 if (view == View.LargeIcon || view == View.SmallIcon)
3716 public void AutoResizeColumn (int columnIndex, ColumnHeaderAutoResizeStyle headerAutoResize)
3718 if (columnIndex < 0 || columnIndex >= columns.Count)
3719 throw new ArgumentOutOfRangeException ("columnIndex");
3721 columns [columnIndex].AutoResize (headerAutoResize);
3724 public void AutoResizeColumns (ColumnHeaderAutoResizeStyle headerAutoResize)
3727 foreach (ColumnHeader col in columns)
3728 col.AutoResize (headerAutoResize);
3733 public void BeginUpdate ()
3735 // flag to avoid painting
3739 public void Clear ()
3742 items.Clear (); // Redraw (true) called here
3745 public void EndUpdate ()
3747 // flag to avoid painting
3750 // probably, now we need a redraw with recalculations
3754 public void EnsureVisible (int index)
3756 if (index < 0 || index >= items.Count || scrollable == false || updating)
3759 Rectangle view_rect = item_control.ClientRectangle;
3761 // Avoid direct access to items in virtual mode, and use item bounds otherwise, since we could have reordered items
3762 Rectangle bounds = virtual_mode ? new Rectangle (GetItemLocation (index), ItemSize) : items [index].Bounds;
3764 Rectangle bounds = items [index].Bounds;
3767 if (view == View.Details && header_style != ColumnHeaderStyle.None) {
3768 view_rect.Y += header_control.Height;
3769 view_rect.Height -= header_control.Height;
3772 if (view_rect.Contains (bounds))
3775 if (View != View.Details) {
3776 if (bounds.Left < 0)
3777 h_scroll.Value += bounds.Left;
3778 else if (bounds.Right > view_rect.Right)
3779 h_scroll.Value += (bounds.Right - view_rect.Right);
3782 if (bounds.Top < view_rect.Y)
3783 v_scroll.Value += bounds.Top - view_rect.Y;
3784 else if (bounds.Bottom > view_rect.Bottom)
3785 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
3789 public ListViewItem FindItemWithText (string text)
3791 if (items.Count == 0)
3794 return FindItemWithText (text, true, 0, true);
3797 public ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex)
3799 return FindItemWithText (text, includeSubItemsInSearch, startIndex, true, false);
3802 public ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch)
3804 return FindItemWithText (text, includeSubItemsInSearch, startIndex, isPrefixSearch, false);
3808 internal ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch, bool roundtrip)
3810 if (startIndex < 0 || startIndex >= items.Count)
3811 throw new ArgumentOutOfRangeException ("startIndex");
3814 throw new ArgumentNullException ("text");
3818 SearchForVirtualItemEventArgs args = new SearchForVirtualItemEventArgs (true,
3819 isPrefixSearch, includeSubItemsInSearch, text, Point.Empty,
3820 SearchDirectionHint.Down, startIndex);
3822 OnSearchForVirtualItem (args);
3823 int idx = args.Index;
3824 if (idx >= 0 && idx < virtual_list_size)
3833 ListViewItem lvi = items [i];
3835 if (isPrefixSearch) { // prefix search
3836 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (lvi.Text, text, CompareOptions.IgnoreCase))
3838 } else if (String.Compare (lvi.Text, text, true) == 0) // match
3841 if (i + 1 >= items.Count) {
3849 if (i == startIndex)
3853 // Subitems have a minor priority, so we have to do a second linear search
3854 // Also, we don't need to to a roundtrip search for them by now
3855 if (includeSubItemsInSearch) {
3856 for (i = startIndex; i < items.Count; i++) {
3857 ListViewItem lvi = items [i];
3858 foreach (ListViewItem.ListViewSubItem sub_item in lvi.SubItems)
3859 if (isPrefixSearch) {
3860 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (sub_item.Text,
3861 text, CompareOptions.IgnoreCase))
3863 } else if (String.Compare (sub_item.Text, text, true) == 0)
3872 public ListViewItem FindNearestItem (SearchDirectionHint searchDirection, int x, int y)
3874 return FindNearestItem (searchDirection, new Point (x, y));
3877 public ListViewItem FindNearestItem (SearchDirectionHint dir, Point point)
3879 if (dir < SearchDirectionHint.Left || dir > SearchDirectionHint.Down)
3880 throw new ArgumentOutOfRangeException ("searchDirection");
3882 if (view != View.LargeIcon && view != View.SmallIcon)
3883 throw new InvalidOperationException ();
3886 SearchForVirtualItemEventArgs args = new SearchForVirtualItemEventArgs (false,
3887 false, false, String.Empty, point,
3890 OnSearchForVirtualItem (args);
3891 int idx = args.Index;
3892 if (idx >= 0 && idx < virtual_list_size)
3898 ListViewItem item = null;
3899 int min_dist = Int32.MaxValue;
3902 // It looks like .Net does a previous adjustment
3905 case SearchDirectionHint.Up:
3906 point.Y -= item_size.Height;
3908 case SearchDirectionHint.Down:
3909 point.Y += item_size.Height;
3911 case SearchDirectionHint.Left:
3912 point.X -= item_size.Width;
3914 case SearchDirectionHint.Right:
3915 point.X += item_size.Width;
3919 for (int i = 0; i < items.Count; i++) {
3920 Point item_loc = GetItemLocation (i);
3922 if (dir == SearchDirectionHint.Up) {
3923 if (point.Y < item_loc.Y)
3925 } else if (dir == SearchDirectionHint.Down) {
3926 if (point.Y > item_loc.Y)
3928 } else if (dir == SearchDirectionHint.Left) {
3929 if (point.X < item_loc.X)
3931 } else if (dir == SearchDirectionHint.Right) {
3932 if (point.X > item_loc.X)
3936 int x_dist = point.X - item_loc.X;
3937 int y_dist = point.Y - item_loc.Y;
3939 int dist = x_dist * x_dist + y_dist * y_dist;
3940 if (dist < min_dist) {
3950 public ListViewItem GetItemAt (int x, int y)
3952 Size item_size = ItemSize;
3953 for (int i = 0; i < items.Count; i++) {
3954 Point item_location = GetItemLocation (i);
3955 Rectangle item_rect = new Rectangle (item_location, item_size);
3956 if (item_rect.Contains (x, y))
3963 public Rectangle GetItemRect (int index)
3965 return GetItemRect (index, ItemBoundsPortion.Entire);
3968 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
3970 if (index < 0 || index >= items.Count)
3971 throw new IndexOutOfRangeException ("index");
3973 return items [index].GetBounds (portion);
3977 public ListViewHitTestInfo HitTest (Point point)
3979 return HitTest (point.X, point.Y);
3982 public ListViewHitTestInfo HitTest (int x, int y)
3985 throw new ArgumentOutOfRangeException ("x");
3987 throw new ArgumentOutOfRangeException ("y");
3989 ListViewItem item = GetItemAt (x, y);
3991 return new ListViewHitTestInfo (null, null, ListViewHitTestLocations.None);
3993 ListViewHitTestLocations locations = 0;
3994 if (item.GetBounds (ItemBoundsPortion.Label).Contains (x, y))
3995 locations |= ListViewHitTestLocations.Label;
3996 else if (item.GetBounds (ItemBoundsPortion.Icon).Contains (x, y))
3997 locations |= ListViewHitTestLocations.Image;
3998 else if (item.CheckRectReal.Contains (x, y))
3999 locations |= ListViewHitTestLocations.StateImage;
4001 ListViewItem.ListViewSubItem subitem = null;
4002 if (view == View.Details)
4003 foreach (ListViewItem.ListViewSubItem si in item.SubItems)
4004 if (si.Bounds.Contains (x, y)) {
4009 return new ListViewHitTestInfo (item, subitem, locations);
4012 [EditorBrowsable (EditorBrowsableState.Advanced)]
4013 public void RedrawItems (int startIndex, int endIndex, bool invalidateOnly)
4015 if (startIndex < 0 || startIndex >= items.Count)
4016 throw new ArgumentOutOfRangeException ("startIndex");
4017 if (endIndex < 0 || endIndex >= items.Count)
4018 throw new ArgumentOutOfRangeException ("endIndex");
4019 if (startIndex > endIndex)
4020 throw new ArgumentException ("startIndex");
4025 for (int i = startIndex; i <= endIndex; i++)
4026 items [i].Invalidate ();
4028 if (!invalidateOnly)
4037 throw new InvalidOperationException ();
4043 // we need this overload to reuse the logic for sorting, while allowing
4044 // redrawing to be done by caller or have it done by this method when
4045 // sorting is really performed
4047 // ListViewItemCollection's Add and AddRange methods call this overload
4048 // with redraw set to false, as they take care of redrawing themselves
4049 // (they even want to redraw the listview if no sort is performed, as
4050 // an item was added), while ListView.Sort () only wants to redraw if
4051 // sorting was actually performed
4052 private void Sort (bool redraw)
4054 if (!IsHandleCreated || item_sorter == null) {
4058 items.Sort (item_sorter);
4063 public override string ToString ()
4065 int count = this.Items.Count;
4068 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
4070 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
4072 #endregion // Public Instance Methods
4077 internal class HeaderControl : Control {
4080 bool column_resize_active = false;
4081 ColumnHeader resize_column;
4082 ColumnHeader clicked_column;
4083 ColumnHeader drag_column;
4085 int drag_to_index = -1;
4086 ColumnHeader entered_column_header;
4088 public HeaderControl (ListView owner)
4091 this.SetStyle (ControlStyles.DoubleBuffer, true);
4092 MouseDown += new MouseEventHandler (HeaderMouseDown);
4093 MouseMove += new MouseEventHandler (HeaderMouseMove);
4094 MouseUp += new MouseEventHandler (HeaderMouseUp);
4095 MouseLeave += new EventHandler (OnMouseLeave);
4098 internal ColumnHeader EnteredColumnHeader {
4099 get { return entered_column_header; }
4101 if (entered_column_header == value)
4103 if (ThemeEngine.Current.ListViewHasHotHeaderStyle) {
4104 Region region_to_invalidate = new Region ();
4105 region_to_invalidate.MakeEmpty ();
4106 if (entered_column_header != null)
4107 region_to_invalidate.Union (GetColumnHeaderInvalidateArea (entered_column_header));
4108 entered_column_header = value;
4109 if (entered_column_header != null)
4110 region_to_invalidate.Union (GetColumnHeaderInvalidateArea (entered_column_header));
4111 Invalidate (region_to_invalidate);
4112 region_to_invalidate.Dispose ();
4114 entered_column_header = value;
4118 void OnMouseLeave (object sender, EventArgs e)
4120 EnteredColumnHeader = null;
4123 private ColumnHeader ColumnAtX (int x)
4125 Point pt = new Point (x, 0);
4126 ColumnHeader result = null;
4127 foreach (ColumnHeader col in owner.Columns) {
4128 if (col.Rect.Contains (pt)) {
4136 private int GetReorderedIndex (ColumnHeader col)
4138 if (owner.reordered_column_indices == null)
4141 for (int i = 0; i < owner.Columns.Count; i++)
4142 if (owner.reordered_column_indices [i] == col.Index)
4144 throw new Exception ("Column index missing from reordered array");
4147 private void HeaderMouseDown (object sender, MouseEventArgs me)
4149 if (resize_column != null) {
4150 column_resize_active = true;
4155 clicked_column = ColumnAtX (me.X + owner.h_marker);
4157 if (clicked_column != null) {
4159 if (owner.AllowColumnReorder) {
4161 drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
4162 drag_column.Rect = clicked_column.Rect;
4163 drag_to_index = GetReorderedIndex (clicked_column);
4165 clicked_column.Pressed = true;
4166 Invalidate (clicked_column);
4171 void Invalidate (ColumnHeader columnHeader)
4173 Invalidate (GetColumnHeaderInvalidateArea (columnHeader));
4176 Rectangle GetColumnHeaderInvalidateArea (ColumnHeader columnHeader)
4178 Rectangle bounds = columnHeader.Rect;
4179 bounds.X -= owner.h_marker;
4185 column_resize_active = false;
4186 resize_column = null;
4188 Cursor = Cursors.Default;
4191 private void HeaderMouseMove (object sender, MouseEventArgs me)
4193 Point pt = new Point (me.X + owner.h_marker, me.Y);
4195 if (column_resize_active) {
4196 int width = pt.X - resize_column.X;
4200 if (!owner.CanProceedWithResize (resize_column, width)){
4204 resize_column.Width = width;
4208 resize_column = null;
4210 if (clicked_column != null) {
4211 if (owner.AllowColumnReorder) {
4214 r = drag_column.Rect;
4215 r.X = clicked_column.Rect.X + me.X - drag_x;
4216 drag_column.Rect = r;
4218 int x = me.X + owner.h_marker;
4219 ColumnHeader over = ColumnAtX (x);
4221 drag_to_index = owner.Columns.Count;
4222 else if (x < over.X + over.Width / 2)
4223 drag_to_index = GetReorderedIndex (over);
4225 drag_to_index = GetReorderedIndex (over) + 1;
4228 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
4229 bool pressed = clicked_column.Pressed;
4230 clicked_column.Pressed = over == clicked_column;
4231 if (clicked_column.Pressed ^ pressed)
4232 Invalidate (clicked_column);
4237 for (int i = 0; i < owner.Columns.Count; i++) {
4238 Rectangle zone = owner.Columns [i].Rect;
4239 if (zone.Contains (pt))
4240 EnteredColumnHeader = owner.Columns [i];
4241 zone.X = zone.Right - 5;
4243 if (zone.Contains (pt)) {
4244 if (i < owner.Columns.Count - 1 && owner.Columns [i + 1].Width == 0)
4246 resize_column = owner.Columns [i];
4251 if (resize_column == null)
4252 Cursor = Cursors.Default;
4254 Cursor = Cursors.VSplit;
4257 void HeaderMouseUp (object sender, MouseEventArgs me)
4261 if (column_resize_active) {
4262 int column_idx = resize_column.Index;
4264 owner.RaiseColumnWidthChanged (column_idx);
4268 if (clicked_column != null && clicked_column.Pressed) {
4269 clicked_column.Pressed = false;
4270 Invalidate (clicked_column);
4271 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
4274 if (drag_column != null && owner.AllowColumnReorder) {
4276 if (drag_to_index > GetReorderedIndex (clicked_column))
4278 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
4279 owner.ReorderColumn (clicked_column, drag_to_index, true);
4284 clicked_column = null;
4287 internal override void OnPaintInternal (PaintEventArgs pe)
4292 Theme theme = ThemeEngine.Current;
4293 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
4295 if (drag_column == null)
4299 if (drag_to_index == owner.Columns.Count)
4300 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
4302 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
4303 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
4306 protected override void WndProc (ref Message m)
4308 switch ((Msg)m.Msg) {
4309 case Msg.WM_SETFOCUS:
4313 base.WndProc (ref m);
4319 private class ItemComparer : IComparer {
4320 readonly SortOrder sort_order;
4322 public ItemComparer (SortOrder sortOrder)
4324 sort_order = sortOrder;
4327 public int Compare (object x, object y)
4329 ListViewItem item_x = x as ListViewItem;
4330 ListViewItem item_y = y as ListViewItem;
4331 if (sort_order == SortOrder.Ascending)
4332 return String.Compare (item_x.Text, item_y.Text);
4334 return String.Compare (item_y.Text, item_x.Text);
4339 [ListBindable (false)]
4341 public class CheckedIndexCollection : IList, ICollection, IEnumerable
4343 private readonly ListView owner;
4345 #region Public Constructor
4346 public CheckedIndexCollection (ListView owner)
4350 #endregion // Public Constructor
4352 #region Public Properties
4355 get { return owner.CheckedItems.Count; }
4358 public bool IsReadOnly {
4359 get { return true; }
4362 public int this [int index] {
4364 int [] indices = GetIndices ();
4365 if (index < 0 || index >= indices.Length)
4366 throw new ArgumentOutOfRangeException ("index");
4367 return indices [index];
4371 bool ICollection.IsSynchronized {
4372 get { return false; }
4375 object ICollection.SyncRoot {
4376 get { return this; }
4379 bool IList.IsFixedSize {
4380 get { return true; }
4383 object IList.this [int index] {
4384 get { return this [index]; }
4385 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4387 #endregion // Public Properties
4389 #region Public Methods
4390 public bool Contains (int checkedIndex)
4392 int [] indices = GetIndices ();
4393 for (int i = 0; i < indices.Length; i++) {
4394 if (indices [i] == checkedIndex)
4400 public IEnumerator GetEnumerator ()
4402 int [] indices = GetIndices ();
4403 return indices.GetEnumerator ();
4406 void ICollection.CopyTo (Array dest, int index)
4408 int [] indices = GetIndices ();
4409 Array.Copy (indices, 0, dest, index, indices.Length);
4412 int IList.Add (object value)
4414 throw new NotSupportedException ("Add operation is not supported.");
4419 throw new NotSupportedException ("Clear operation is not supported.");
4422 bool IList.Contains (object checkedIndex)
4424 if (!(checkedIndex is int))
4426 return Contains ((int) checkedIndex);
4429 int IList.IndexOf (object checkedIndex)
4431 if (!(checkedIndex is int))
4433 return IndexOf ((int) checkedIndex);
4436 void IList.Insert (int index, object value)
4438 throw new NotSupportedException ("Insert operation is not supported.");
4441 void IList.Remove (object value)
4443 throw new NotSupportedException ("Remove operation is not supported.");
4446 void IList.RemoveAt (int index)
4448 throw new NotSupportedException ("RemoveAt operation is not supported.");
4451 public int IndexOf (int checkedIndex)
4453 int [] indices = GetIndices ();
4454 for (int i = 0; i < indices.Length; i++) {
4455 if (indices [i] == checkedIndex)
4460 #endregion // Public Methods
4462 private int [] GetIndices ()
4464 ArrayList checked_items = owner.CheckedItems.List;
4465 int [] indices = new int [checked_items.Count];
4466 for (int i = 0; i < checked_items.Count; i++) {
4467 ListViewItem item = (ListViewItem) checked_items [i];
4468 indices [i] = item.Index;
4472 } // CheckedIndexCollection
4475 [ListBindable (false)]
4477 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
4479 private readonly ListView owner;
4480 private ArrayList list;
4482 #region Public Constructor
4483 public CheckedListViewItemCollection (ListView owner)
4486 this.owner.Items.Changed += new CollectionChangedHandler (
4487 ItemsCollection_Changed);
4489 #endregion // Public Constructor
4491 #region Public Properties
4495 if (!owner.CheckBoxes)
4501 public bool IsReadOnly {
4502 get { return true; }
4505 public ListViewItem this [int index] {
4508 if (owner.VirtualMode)
4509 throw new InvalidOperationException ();
4511 ArrayList checked_items = List;
4512 if (index < 0 || index >= checked_items.Count)
4513 throw new ArgumentOutOfRangeException ("index");
4514 return (ListViewItem) checked_items [index];
4519 public virtual ListViewItem this [string key] {
4521 int idx = IndexOfKey (key);
4522 return idx == -1 ? null : (ListViewItem) List [idx];
4527 bool ICollection.IsSynchronized {
4528 get { return false; }
4531 object ICollection.SyncRoot {
4532 get { return this; }
4535 bool IList.IsFixedSize {
4536 get { return true; }
4539 object IList.this [int index] {
4540 get { return this [index]; }
4541 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4543 #endregion // Public Properties
4545 #region Public Methods
4546 public bool Contains (ListViewItem item)
4548 if (!owner.CheckBoxes)
4550 return List.Contains (item);
4554 public virtual bool ContainsKey (string key)
4556 return IndexOfKey (key) != -1;
4560 public void CopyTo (Array dest, int index)
4563 if (owner.VirtualMode)
4564 throw new InvalidOperationException ();
4566 if (!owner.CheckBoxes)
4568 List.CopyTo (dest, index);
4571 public IEnumerator GetEnumerator ()
4574 if (owner.VirtualMode)
4575 throw new InvalidOperationException ();
4577 if (!owner.CheckBoxes)
4578 return (new ListViewItem [0]).GetEnumerator ();
4579 return List.GetEnumerator ();
4582 int IList.Add (object value)
4584 throw new NotSupportedException ("Add operation is not supported.");
4589 throw new NotSupportedException ("Clear operation is not supported.");
4592 bool IList.Contains (object item)
4594 if (!(item is ListViewItem))
4596 return Contains ((ListViewItem) item);
4599 int IList.IndexOf (object item)
4601 if (!(item is ListViewItem))
4603 return IndexOf ((ListViewItem) item);
4606 void IList.Insert (int index, object value)
4608 throw new NotSupportedException ("Insert operation is not supported.");
4611 void IList.Remove (object value)
4613 throw new NotSupportedException ("Remove operation is not supported.");
4616 void IList.RemoveAt (int index)
4618 throw new NotSupportedException ("RemoveAt operation is not supported.");
4621 public int IndexOf (ListViewItem item)
4624 if (owner.VirtualMode)
4625 throw new InvalidOperationException ();
4627 if (!owner.CheckBoxes)
4629 return List.IndexOf (item);
4633 public virtual int IndexOfKey (string key)
4636 if (owner.VirtualMode)
4637 throw new InvalidOperationException ();
4639 if (key == null || key.Length == 0)
4642 ArrayList checked_items = List;
4643 for (int i = 0; i < checked_items.Count; i++) {
4644 ListViewItem item = (ListViewItem) checked_items [i];
4645 if (String.Compare (key, item.Name, true) == 0)
4652 #endregion // Public Methods
4654 internal ArrayList List {
4657 list = new ArrayList ();
4658 foreach (ListViewItem item in owner.Items) {
4667 internal void Reset ()
4669 // force re-population of list
4673 private void ItemsCollection_Changed ()
4677 } // CheckedListViewItemCollection
4680 [ListBindable (false)]
4682 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
4684 internal ArrayList list;
4685 private ListView owner;
4687 #region UIA Framework Events
4690 // We are using Reflection to add/remove internal events.
4691 // Class ListViewProvider uses the events when View is Details.
4693 //Event used to generate UIA StructureChangedEvent
4694 static object UIACollectionChangedEvent = new object ();
4696 internal event CollectionChangeEventHandler UIACollectionChanged {
4699 owner.Events.AddHandler (UIACollectionChangedEvent, value);
4703 owner.Events.RemoveHandler (UIACollectionChangedEvent, value);
4707 internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args)
4712 CollectionChangeEventHandler eh
4713 = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
4719 #endregion UIA Framework Events
4721 #region Public Constructor
4722 public ColumnHeaderCollection (ListView owner)
4724 list = new ArrayList ();
4727 #endregion // Public Constructor
4729 #region Public Properties
4732 get { return list.Count; }
4735 public bool IsReadOnly {
4736 get { return false; }
4739 public virtual ColumnHeader this [int index] {
4741 if (index < 0 || index >= list.Count)
4742 throw new ArgumentOutOfRangeException ("index");
4743 return (ColumnHeader) list [index];
4748 public virtual ColumnHeader this [string key] {
4750 int idx = IndexOfKey (key);
4754 return (ColumnHeader) list [idx];
4759 bool ICollection.IsSynchronized {
4760 get { return true; }
4763 object ICollection.SyncRoot {
4764 get { return this; }
4767 bool IList.IsFixedSize {
4768 get { return list.IsFixedSize; }
4771 object IList.this [int index] {
4772 get { return this [index]; }
4773 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4775 #endregion // Public Properties
4777 #region Public Methods
4778 public virtual int Add (ColumnHeader value)
4780 int idx = list.Add (value);
4781 owner.AddColumn (value, idx, true);
4784 //UIA Framework event: Item Added
4785 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
4792 public virtual ColumnHeader Add (string text, int width, HorizontalAlignment textAlign)
4796 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
4799 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
4800 this.Add (colHeader);
4805 public virtual ColumnHeader Add (string text)
4807 return Add (String.Empty, text);
4810 public virtual ColumnHeader Add (string text, int width)
4812 return Add (String.Empty, text, width);
4815 public virtual ColumnHeader Add (string key, string text)
4817 ColumnHeader colHeader = new ColumnHeader ();
4818 colHeader.Name = key;
4819 colHeader.Text = text;
4824 public virtual ColumnHeader Add (string key, string text, int width)
4826 return Add (key, text, width, HorizontalAlignment.Left, -1);
4829 public virtual ColumnHeader Add (string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
4831 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4832 colHeader.ImageIndex = imageIndex;
4837 public virtual ColumnHeader Add (string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
4839 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
4840 colHeader.ImageKey = imageKey;
4846 public virtual void AddRange (ColumnHeader [] values)
4848 foreach (ColumnHeader colHeader in values) {
4849 int idx = list.Add (colHeader);
4850 owner.AddColumn (colHeader, idx, false);
4853 owner.Redraw (true);
4856 public virtual void Clear ()
4858 foreach (ColumnHeader col in list)
4859 col.SetListView (null);
4861 owner.ReorderColumns (new int [0], true);
4864 //UIA Framework event: Items cleared
4865 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
4870 public bool Contains (ColumnHeader value)
4872 return list.Contains (value);
4876 public virtual bool ContainsKey (string key)
4878 return IndexOfKey (key) != -1;
4882 public IEnumerator GetEnumerator ()
4884 return list.GetEnumerator ();
4887 void ICollection.CopyTo (Array dest, int index)
4889 list.CopyTo (dest, index);
4892 int IList.Add (object value)
4894 if (! (value is ColumnHeader)) {
4895 throw new ArgumentException ("Not of type ColumnHeader", "value");
4898 return this.Add ((ColumnHeader) value);
4901 bool IList.Contains (object value)
4903 if (! (value is ColumnHeader)) {
4904 throw new ArgumentException ("Not of type ColumnHeader", "value");
4907 return this.Contains ((ColumnHeader) value);
4910 int IList.IndexOf (object value)
4912 if (! (value is ColumnHeader)) {
4913 throw new ArgumentException ("Not of type ColumnHeader", "value");
4916 return this.IndexOf ((ColumnHeader) value);
4919 void IList.Insert (int index, object value)
4921 if (! (value is ColumnHeader)) {
4922 throw new ArgumentException ("Not of type ColumnHeader", "value");
4925 this.Insert (index, (ColumnHeader) value);
4928 void IList.Remove (object value)
4930 if (! (value is ColumnHeader)) {
4931 throw new ArgumentException ("Not of type ColumnHeader", "value");
4934 this.Remove ((ColumnHeader) value);
4937 public int IndexOf (ColumnHeader value)
4939 return list.IndexOf (value);
4943 public virtual int IndexOfKey (string key)
4945 if (key == null || key.Length == 0)
4948 for (int i = 0; i < list.Count; i++) {
4949 ColumnHeader col = (ColumnHeader) list [i];
4950 if (String.Compare (key, col.Name, true) == 0)
4958 public void Insert (int index, ColumnHeader value)
4960 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
4961 // but it's really only greater.
4962 if (index < 0 || index > list.Count)
4963 throw new ArgumentOutOfRangeException ("index");
4965 list.Insert (index, value);
4966 owner.AddColumn (value, index, true);
4969 //UIA Framework event: Item added
4970 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
4975 public void Insert (int index, string text)
4977 Insert (index, String.Empty, text);
4980 public void Insert (int index, string text, int width)
4982 Insert (index, String.Empty, text, width);
4985 public void Insert (int index, string key, string text)
4987 ColumnHeader colHeader = new ColumnHeader ();
4988 colHeader.Name = key;
4989 colHeader.Text = text;
4990 Insert (index, colHeader);
4993 public void Insert (int index, string key, string text, int width)
4995 ColumnHeader colHeader = new ColumnHeader (key, text, width, HorizontalAlignment.Left);
4996 Insert (index, colHeader);
4999 public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
5001 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
5002 colHeader.ImageIndex = imageIndex;
5003 Insert (index, colHeader);
5006 public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
5008 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
5009 colHeader.ImageKey = imageKey;
5010 Insert (index, colHeader);
5015 public void Insert (int index, string text, int width, HorizontalAlignment textAlign)
5019 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
5022 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
5023 this.Insert (index, colHeader);
5026 public virtual void Remove (ColumnHeader column)
5028 if (!Contains (column))
5031 list.Remove (column);
5032 column.SetListView (null);
5034 int rem_display_index = column.InternalDisplayIndex;
5035 int [] display_indices = new int [list.Count];
5036 for (int i = 0; i < display_indices.Length; i++) {
5037 ColumnHeader col = (ColumnHeader) list [i];
5038 int display_index = col.InternalDisplayIndex;
5039 if (display_index < rem_display_index) {
5040 display_indices [i] = display_index;
5042 display_indices [i] = (display_index - 1);
5046 column.InternalDisplayIndex = -1;
5047 owner.ReorderColumns (display_indices, true);
5050 //UIA Framework event: Item Removed
5051 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, column));
5056 public virtual void RemoveByKey (string key)
5058 int idx = IndexOfKey (key);
5064 public virtual void RemoveAt (int index)
5066 if (index < 0 || index >= list.Count)
5067 throw new ArgumentOutOfRangeException ("index");
5069 ColumnHeader col = (ColumnHeader) list [index];
5072 #endregion // Public Methods
5075 } // ColumnHeaderCollection
5078 [ListBindable (false)]
5080 public class ListViewItemCollection : IList, ICollection, IEnumerable
5082 private readonly ArrayList list;
5083 private ListView owner;
5085 private ListViewGroup group;
5088 #region UIA Framework Events
5091 // We are using Reflection to add/remove internal events.
5092 // Class ListViewProvider uses the events.
5094 //Event used to generate UIA StructureChangedEvent
5095 static object UIACollectionChangedEvent = new object ();
5097 internal event CollectionChangeEventHandler UIACollectionChanged {
5100 owner.Events.AddHandler (UIACollectionChangedEvent, value);
5104 owner.Events.RemoveHandler (UIACollectionChangedEvent, value);
5108 internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args)
5113 CollectionChangeEventHandler eh
5114 = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
5120 #endregion UIA Framework Events
5122 // The collection can belong to a ListView (main) or to a ListViewGroup (sub-collection)
5123 // In the later case ListViewItem.ListView never gets modified
5124 private bool is_main_collection = true;
5126 #region Public Constructor
5127 public ListViewItemCollection (ListView owner)
5129 list = new ArrayList (0);
5132 #endregion // Public Constructor
5135 internal ListViewItemCollection (ListView owner, ListViewGroup group) : this (owner)
5138 is_main_collection = false;
5142 #region Public Properties
5147 if (owner != null && owner.VirtualMode)
5148 return owner.VirtualListSize;
5155 public bool IsReadOnly {
5156 get { return false; }
5160 public virtual ListViewItem this [int index] {
5162 public virtual ListViewItem this [int displayIndex] {
5166 int index = displayIndex;
5169 if (index < 0 || index >= Count)
5170 throw new ArgumentOutOfRangeException ("index");
5173 if (owner != null && owner.VirtualMode)
5174 return RetrieveVirtualItemFromOwner (index);
5176 return (ListViewItem) list [index];
5181 int index = displayIndex;
5184 if (index < 0 || index >= Count)
5185 throw new ArgumentOutOfRangeException ("index");
5188 if (owner != null && owner.VirtualMode)
5189 throw new InvalidOperationException ();
5192 if (list.Contains (value))
5193 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
5195 if (value.ListView != null && value.ListView != owner)
5196 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");
5198 if (is_main_collection)
5199 value.Owner = owner;
5202 if (value.Group != null)
5203 value.Group.Items.Remove (value);
5205 value.SetGroup (group);
5210 //UIA Framework event: Item Replaced
5211 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, list [index]));
5214 list [index] = value;
5216 CollectionChanged (true);
5219 //UIA Framework event: Item Replaced
5220 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
5227 public virtual ListViewItem this [string key] {
5229 int idx = IndexOfKey (key);
5238 bool ICollection.IsSynchronized {
5239 get { return true; }
5242 object ICollection.SyncRoot {
5243 get { return this; }
5246 bool IList.IsFixedSize {
5247 get { return list.IsFixedSize; }
5250 object IList.this [int index] {
5251 get { return this [index]; }
5254 //UIA Framework event: Item Replaced
5255 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, this [index]));
5258 if (value is ListViewItem)
5259 this [index] = (ListViewItem) value;
5261 this [index] = new ListViewItem (value.ToString ());
5265 //UIA Framework event: Item Replaced
5266 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
5270 #endregion // Public Properties
5272 #region Public Methods
5273 public virtual ListViewItem Add (ListViewItem value)
5276 if (owner != null && owner.VirtualMode)
5277 throw new InvalidOperationException ();
5282 // Item is ignored until it has been added to the ListView
5283 if (is_main_collection || value.ListView != null)
5284 CollectionChanged (true);
5287 //UIA Framework event: Item Added
5288 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value));
5294 public virtual ListViewItem Add (string text)
5296 ListViewItem item = new ListViewItem (text);
5297 return this.Add (item);
5300 public virtual ListViewItem Add (string text, int imageIndex)
5302 ListViewItem item = new ListViewItem (text, imageIndex);
5303 return this.Add (item);
5307 public virtual ListViewItem Add (string text, string imageKey)
5309 ListViewItem item = new ListViewItem (text, imageKey);
5310 return this.Add (item);
5313 public virtual ListViewItem Add (string key, string text, int imageIndex)
5315 ListViewItem item = new ListViewItem (text, imageIndex);
5317 return this.Add (item);
5320 public virtual ListViewItem Add (string key, string text, string imageKey)
5322 ListViewItem item = new ListViewItem (text, imageKey);
5324 return this.Add (item);
5329 public void AddRange (ListViewItem [] items)
5332 public void AddRange (ListViewItem [] values)
5334 ListViewItem [] items = values;
5337 throw new ArgumentNullException ("Argument cannot be null!", "items");
5339 if (owner != null && owner.VirtualMode)
5340 throw new InvalidOperationException ();
5343 owner.BeginUpdate ();
5345 foreach (ListViewItem item in items) {
5349 //UIA Framework event: Item Added
5350 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
5356 CollectionChanged (true);
5360 public void AddRange (ListViewItemCollection items)
5363 throw new ArgumentNullException ("Argument cannot be null!", "items");
5365 ListViewItem[] itemArray = new ListViewItem[items.Count];
5366 items.CopyTo (itemArray,0);
5367 this.AddRange (itemArray);
5371 public virtual void Clear ()
5374 if (owner != null && owner.VirtualMode)
5375 throw new InvalidOperationException ();
5377 if (is_main_collection && owner != null) {
5378 owner.SetFocusedItem (-1);
5379 owner.h_scroll.Value = owner.v_scroll.Value = 0;
5382 // first remove any item in the groups that *are* part of this LV too
5383 foreach (ListViewGroup group in owner.groups)
5384 group.Items.ClearItemsWithSameListView ();
5387 foreach (ListViewItem item in list) {
5388 owner.item_control.CancelEdit (item);
5394 foreach (ListViewItem item in list)
5395 item.SetGroup (null);
5399 CollectionChanged (false);
5402 //UIA Framework event: Items Removed
5403 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
5409 // This method is intended to be used from ListViewGroup.Items, not from ListView.Items,
5410 // added for performance reasons (avoid calling manually Remove for every item on ListViewGroup.Items)
5411 void ClearItemsWithSameListView ()
5413 if (is_main_collection)
5416 int counter = list.Count - 1;
5417 while (counter >= 0) {
5418 ListViewItem item = list [counter] as ListViewItem;
5420 // remove only if the items in group have being added to the ListView too
5421 if (item.ListView == group.ListView) {
5422 list.RemoveAt (counter);
5423 item.SetGroup (null);
5431 public bool Contains (ListViewItem item)
5433 return IndexOf (item) != -1;
5437 public virtual bool ContainsKey (string key)
5439 return IndexOfKey (key) != -1;
5443 public void CopyTo (Array dest, int index)
5445 list.CopyTo (dest, index);
5449 public ListViewItem [] Find (string key, bool searchAllSubItems)
5452 return new ListViewItem [0];
5454 List<ListViewItem> temp_list = new List<ListViewItem> ();
5456 for (int i = 0; i < list.Count; i++) {
5457 ListViewItem lvi = (ListViewItem) list [i];
5458 if (String.Compare (key, lvi.Name, true) == 0)
5459 temp_list.Add (lvi);
5462 ListViewItem [] retval = new ListViewItem [temp_list.Count];
5463 temp_list.CopyTo (retval);
5469 public IEnumerator GetEnumerator ()
5472 if (owner != null && owner.VirtualMode)
5473 throw new InvalidOperationException ();
5476 // This enumerator makes a copy of the collection so
5477 // it can be deleted from in a foreach
5478 return new Control.ControlCollection.ControlCollectionEnumerator (list);
5481 int IList.Add (object item)
5487 if (owner != null && owner.VirtualMode)
5488 throw new InvalidOperationException ();
5491 if (item is ListViewItem) {
5492 li = (ListViewItem) item;
5493 if (list.Contains (li))
5494 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
5496 if (li.ListView != null && li.ListView != owner)
5497 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");
5500 li = new ListViewItem (item.ToString ());
5505 result = list.Add (li);
5506 CollectionChanged (true);
5509 //UIA Framework event: Item Added
5510 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, li));
5516 bool IList.Contains (object item)
5518 return Contains ((ListViewItem) item);
5521 int IList.IndexOf (object item)
5523 return IndexOf ((ListViewItem) item);
5526 void IList.Insert (int index, object item)
5528 if (item is ListViewItem)
5529 this.Insert (index, (ListViewItem) item);
5531 this.Insert (index, item.ToString ());
5534 //UIA Framework event: Item Added
5535 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, this [index]));
5539 void IList.Remove (object item)
5541 Remove ((ListViewItem) item);
5544 public int IndexOf (ListViewItem item)
5547 if (owner != null && owner.VirtualMode) {
5548 for (int i = 0; i < Count; i++)
5549 if (RetrieveVirtualItemFromOwner (i) == item)
5556 return list.IndexOf (item);
5560 public virtual int IndexOfKey (string key)
5562 if (key == null || key.Length == 0)
5565 for (int i = 0; i < Count; i++) {
5566 ListViewItem lvi = this [i];
5567 if (String.Compare (key, lvi.Name, true) == 0)
5575 public ListViewItem Insert (int index, ListViewItem item)
5577 if (index < 0 || index > list.Count)
5578 throw new ArgumentOutOfRangeException ("index");
5581 if (owner != null && owner.VirtualMode)
5582 throw new InvalidOperationException ();
5585 if (list.Contains (item))
5586 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
5588 if (item.ListView != null && item.ListView != owner)
5589 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");
5591 if (is_main_collection)
5595 if (item.Group != null)
5596 item.Group.Items.Remove (item);
5598 item.SetGroup (group);
5602 list.Insert (index, item);
5604 if (is_main_collection || item.ListView != null)
5605 CollectionChanged (true);
5608 //UIA Framework event: Item Added
5609 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item));
5615 public ListViewItem Insert (int index, string text)
5617 return this.Insert (index, new ListViewItem (text));
5620 public ListViewItem Insert (int index, string text, int imageIndex)
5622 return this.Insert (index, new ListViewItem (text, imageIndex));
5626 public ListViewItem Insert (int index, string text, string imageKey)
5628 ListViewItem lvi = new ListViewItem (text, imageKey);
5629 return Insert (index, lvi);
5632 public virtual ListViewItem Insert (int index, string key, string text, int imageIndex)
5634 ListViewItem lvi = new ListViewItem (text, imageIndex);
5636 return Insert (index, lvi);
5639 public virtual ListViewItem Insert (int index, string key, string text, string imageKey)
5641 ListViewItem lvi = new ListViewItem (text, imageKey);
5643 return Insert (index, lvi);
5647 public virtual void Remove (ListViewItem item)
5650 if (owner != null && owner.VirtualMode)
5651 throw new InvalidOperationException ();
5654 int idx = list.IndexOf (item);
5659 public virtual void RemoveAt (int index)
5661 if (index < 0 || index >= Count)
5662 throw new ArgumentOutOfRangeException ("index");
5665 if (owner != null && owner.VirtualMode)
5666 throw new InvalidOperationException ();
5669 ListViewItem item = (ListViewItem) list [index];
5671 bool selection_changed = false;
5672 if (is_main_collection && owner != null) {
5674 int display_index = item.DisplayIndex;
5675 if (item.Focused && display_index + 1 == Count) // Last item
5676 owner.SetFocusedItem (display_index == 0 ? -1 : display_index - 1);
5678 selection_changed = owner.SelectedIndices.Contains (index);
5679 owner.item_control.CancelEdit (item);
5682 list.RemoveAt (index);
5685 if (is_main_collection) {
5687 if (item.Group != null)
5688 item.Group.Items.Remove (item);
5690 item.SetGroup (null);
5695 CollectionChanged (false);
5696 if (selection_changed && owner != null)
5697 owner.OnSelectedIndexChanged (EventArgs.Empty);
5701 //UIA Framework event: Item Removed
5702 OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, item));
5707 public virtual void RemoveByKey (string key)
5709 int idx = IndexOfKey (key);
5715 #endregion // Public Methods
5717 internal ListView Owner {
5727 internal ListViewGroup Group {
5737 void AddItem (ListViewItem value)
5739 if (list.Contains (value))
5740 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
5742 if (value.ListView != null && value.ListView != owner)
5743 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");
5744 if (is_main_collection)
5745 value.Owner = owner;
5748 if (value.Group != null)
5749 value.Group.Items.Remove (value);
5751 value.SetGroup (group);
5759 void CollectionChanged (bool sort)
5761 if (owner != null) {
5766 owner.Redraw (true);
5771 ListViewItem RetrieveVirtualItemFromOwner (int displayIndex)
5773 RetrieveVirtualItemEventArgs args = new RetrieveVirtualItemEventArgs (displayIndex);
5775 owner.OnRetrieveVirtualItem (args);
5776 ListViewItem retval = args.Item;
5777 retval.Owner = owner;
5778 retval.DisplayIndex = displayIndex;
5784 internal event CollectionChangedHandler Changed;
5786 internal void Sort (IComparer comparer)
5788 list.Sort (comparer);
5792 internal void OnChange ()
5794 if (Changed != null)
5797 } // ListViewItemCollection
5800 // In normal mode, the selection information resides in the Items,
5801 // making SelectedIndexCollection.List read-only
5803 // In virtual mode, SelectedIndexCollection directly saves the selection
5804 // information, instead of getting it from Items, making List read-and-write
5806 [ListBindable (false)]
5808 public class SelectedIndexCollection : IList, ICollection, IEnumerable
5810 private readonly ListView owner;
5811 private ArrayList list;
5813 #region Public Constructor
5814 public SelectedIndexCollection (ListView owner)
5817 owner.Items.Changed += new CollectionChangedHandler (ItemsCollection_Changed);
5819 #endregion // Public Constructor
5821 #region Public Properties
5825 if (!owner.IsHandleCreated)
5832 public bool IsReadOnly {
5842 public int this [int index] {
5844 if (!owner.IsHandleCreated || index < 0 || index >= List.Count)
5845 throw new ArgumentOutOfRangeException ("index");
5847 return (int) List [index];
5851 bool ICollection.IsSynchronized {
5852 get { return false; }
5855 object ICollection.SyncRoot {
5856 get { return this; }
5859 bool IList.IsFixedSize {
5869 object IList.this [int index] {
5870 get { return this [index]; }
5871 set { throw new NotSupportedException ("SetItem operation is not supported."); }
5873 #endregion // Public Properties
5875 #region Public Methods
5877 public int Add (int itemIndex)
5879 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
5880 throw new ArgumentOutOfRangeException ("index");
5882 if (owner.virtual_mode && !owner.IsHandleCreated)
5885 owner.Items [itemIndex].Selected = true;
5887 if (!owner.IsHandleCreated)
5901 if (!owner.IsHandleCreated)
5904 int [] indexes = (int []) List.ToArray (typeof (int));
5905 foreach (int index in indexes)
5906 owner.Items [index].Selected = false;
5909 public bool Contains (int selectedIndex)
5911 return IndexOf (selectedIndex) != -1;
5914 public void CopyTo (Array dest, int index)
5916 List.CopyTo (dest, index);
5919 public IEnumerator GetEnumerator ()
5921 return List.GetEnumerator ();
5924 int IList.Add (object value)
5926 throw new NotSupportedException ("Add operation is not supported.");
5934 bool IList.Contains (object selectedIndex)
5936 if (!(selectedIndex is int))
5938 return Contains ((int) selectedIndex);
5941 int IList.IndexOf (object selectedIndex)
5943 if (!(selectedIndex is int))
5945 return IndexOf ((int) selectedIndex);
5948 void IList.Insert (int index, object value)
5950 throw new NotSupportedException ("Insert operation is not supported.");
5953 void IList.Remove (object value)
5955 throw new NotSupportedException ("Remove operation is not supported.");
5958 void IList.RemoveAt (int index)
5960 throw new NotSupportedException ("RemoveAt operation is not supported.");
5963 public int IndexOf (int selectedIndex)
5965 if (!owner.IsHandleCreated)
5968 return List.IndexOf (selectedIndex);
5972 public void Remove (int itemIndex)
5974 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
5975 throw new ArgumentOutOfRangeException ("itemIndex");
5977 owner.Items [itemIndex].Selected = false;
5980 #endregion // Public Methods
5982 internal ArrayList List {
5985 list = new ArrayList ();
5987 if (!owner.VirtualMode)
5989 for (int i = 0; i < owner.Items.Count; i++) {
5990 if (owner.Items [i].Selected)
5998 internal void Reset ()
6000 // force re-population of list
6004 private void ItemsCollection_Changed ()
6010 internal void RemoveIndex (int index)
6012 int idx = List.BinarySearch (index);
6014 List.RemoveAt (idx);
6017 // actually store index in the collection
6018 // also, keep the collection sorted, as .Net does
6019 internal void InsertIndex (int index)
6022 int iMax = List.Count - 1;
6023 while (iMin <= iMax) {
6024 int iMid = (iMin + iMax) / 2;
6025 int current_index = (int) List [iMid];
6027 if (current_index == index)
6028 return; // Already added
6029 if (current_index > index)
6035 List.Insert (iMin, index);
6039 } // SelectedIndexCollection
6042 [ListBindable (false)]
6044 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
6046 private readonly ListView owner;
6048 #region Public Constructor
6049 public SelectedListViewItemCollection (ListView owner)
6053 #endregion // Public Constructor
6055 #region Public Properties
6059 return owner.SelectedIndices.Count;
6063 public bool IsReadOnly {
6064 get { return true; }
6067 public ListViewItem this [int index] {
6069 if (!owner.IsHandleCreated || index < 0 || index >= Count)
6070 throw new ArgumentOutOfRangeException ("index");
6072 int item_index = owner.SelectedIndices [index];
6073 return owner.Items [item_index];
6078 public virtual ListViewItem this [string key] {
6080 int idx = IndexOfKey (key);
6089 bool ICollection.IsSynchronized {
6090 get { return false; }
6093 object ICollection.SyncRoot {
6094 get { return this; }
6097 bool IList.IsFixedSize {
6098 get { return true; }
6101 object IList.this [int index] {
6102 get { return this [index]; }
6103 set { throw new NotSupportedException ("SetItem operation is not supported."); }
6105 #endregion // Public Properties
6107 #region Public Methods
6108 public void Clear ()
6110 owner.SelectedIndices.Clear ();
6113 public bool Contains (ListViewItem item)
6115 return IndexOf (item) != -1;
6119 public virtual bool ContainsKey (string key)
6121 return IndexOfKey (key) != -1;
6125 public void CopyTo (Array dest, int index)
6127 if (!owner.IsHandleCreated)
6129 if (index > Count) // Throws ArgumentException instead of IOOR exception
6130 throw new ArgumentException ("index");
6132 for (int i = 0; i < Count; i++)
6133 dest.SetValue (this [i], index++);
6136 public IEnumerator GetEnumerator ()
6138 if (!owner.IsHandleCreated)
6139 return (new ListViewItem [0]).GetEnumerator ();
6141 ListViewItem [] items = new ListViewItem [Count];
6142 for (int i = 0; i < Count; i++)
6143 items [i] = this [i];
6145 return items.GetEnumerator ();
6148 int IList.Add (object value)
6150 throw new NotSupportedException ("Add operation is not supported.");
6153 bool IList.Contains (object item)
6155 if (!(item is ListViewItem))
6157 return Contains ((ListViewItem) item);
6160 int IList.IndexOf (object item)
6162 if (!(item is ListViewItem))
6164 return IndexOf ((ListViewItem) item);
6167 void IList.Insert (int index, object value)
6169 throw new NotSupportedException ("Insert operation is not supported.");
6172 void IList.Remove (object value)
6174 throw new NotSupportedException ("Remove operation is not supported.");
6177 void IList.RemoveAt (int index)
6179 throw new NotSupportedException ("RemoveAt operation is not supported.");
6182 public int IndexOf (ListViewItem item)
6184 if (!owner.IsHandleCreated)
6187 for (int i = 0; i < Count; i++)
6188 if (this [i] == item)
6195 public virtual int IndexOfKey (string key)
6197 if (!owner.IsHandleCreated || key == null || key.Length == 0)
6200 for (int i = 0; i < Count; i++) {
6201 ListViewItem item = this [i];
6202 if (String.Compare (item.Name, key, true) == 0)
6209 #endregion // Public Methods
6211 } // SelectedListViewItemCollection
6213 internal delegate void CollectionChangedHandler ();
6215 struct ItemMatrixLocation
6220 public ItemMatrixLocation (int row, int col)
6247 #endregion // Subclasses
6249 protected override void OnResize (EventArgs e)
6254 protected override void OnMouseLeave (EventArgs e)
6256 base.OnMouseLeave (e);
6260 // ColumnReorder event
6262 static object ColumnReorderedEvent = new object ();
6263 public event ColumnReorderedEventHandler ColumnReordered {
6264 add { Events.AddHandler (ColumnReorderedEvent, value); }
6265 remove { Events.RemoveHandler (ColumnReorderedEvent, value); }
6268 protected virtual void OnColumnReordered (ColumnReorderedEventArgs e)
6270 ColumnReorderedEventHandler creh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
6277 // ColumnWidthChanged
6279 static object ColumnWidthChangedEvent = new object ();
6280 public event ColumnWidthChangedEventHandler ColumnWidthChanged {
6281 add { Events.AddHandler (ColumnWidthChangedEvent, value); }
6282 remove { Events.RemoveHandler (ColumnWidthChangedEvent, value); }
6285 protected virtual void OnColumnWidthChanged (ColumnWidthChangedEventArgs e)
6287 ColumnWidthChangedEventHandler eh = (ColumnWidthChangedEventHandler) (Events[ColumnWidthChangedEvent]);
6292 void RaiseColumnWidthChanged (int resize_column)
6294 ColumnWidthChangedEventArgs n = new ColumnWidthChangedEventArgs (resize_column);
6296 OnColumnWidthChanged (n);
6300 // ColumnWidthChanging
6302 static object ColumnWidthChangingEvent = new object ();
6303 public event ColumnWidthChangingEventHandler ColumnWidthChanging {
6304 add { Events.AddHandler (ColumnWidthChangingEvent, value); }
6305 remove { Events.RemoveHandler (ColumnWidthChangingEvent, value); }
6308 protected virtual void OnColumnWidthChanging (ColumnWidthChangingEventArgs e)
6310 ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
6316 // 2.0 profile based implementation
6318 bool CanProceedWithResize (ColumnHeader col, int width)
6320 ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
6324 ColumnWidthChangingEventArgs changing = new ColumnWidthChangingEventArgs (col.Index, width);
6325 cwceh (this, changing);
6326 return !changing.Cancel;
6330 // 1.0 profile based implementation
6332 bool CanProceedWithResize (ColumnHeader col, int width)
6337 void RaiseColumnWidthChanged (int resize_column)
6342 internal void RaiseColumnWidthChanged (ColumnHeader column)
6344 int index = Columns.IndexOf (column);
6345 RaiseColumnWidthChanged (index);
6350 #region UIA Framework: Methods, Properties and Events
6352 static object UIALabelEditChangedEvent = new object ();
6353 static object UIAShowGroupsChangedEvent = new object ();
6354 static object UIAMultiSelectChangedEvent = new object ();
6355 static object UIAViewChangedEvent = new object ();
6356 static object UIACheckBoxesChangedEvent = new object ();
6357 static object UIAFocusedItemChangedEvent = new object ();
6359 internal Rectangle UIAHeaderControl {
6360 get { return header_control.Bounds; }
6363 internal int UIAColumns {
6364 get { return cols; }
6367 internal int UIARows {
6368 get { return rows; }
6371 internal ListViewGroup UIADefaultListViewGroup
6373 get { return groups.DefaultGroup; }
6376 internal ScrollBar UIAHScrollBar {
6377 get { return h_scroll; }
6380 internal ScrollBar UIAVScrollBar {
6381 get { return v_scroll; }
6384 internal event EventHandler UIAShowGroupsChanged {
6385 add { Events.AddHandler (UIAShowGroupsChangedEvent, value); }
6386 remove { Events.RemoveHandler (UIAShowGroupsChangedEvent, value); }
6389 internal event EventHandler UIACheckBoxesChanged {
6390 add { Events.AddHandler (UIACheckBoxesChangedEvent, value); }
6391 remove { Events.RemoveHandler (UIACheckBoxesChangedEvent, value); }
6394 internal event EventHandler UIAMultiSelectChanged {
6395 add { Events.AddHandler (UIAMultiSelectChangedEvent, value); }
6396 remove { Events.RemoveHandler (UIAMultiSelectChangedEvent, value); }
6399 internal event EventHandler UIALabelEditChanged {
6400 add { Events.AddHandler (UIALabelEditChangedEvent, value); }
6401 remove { Events.RemoveHandler (UIALabelEditChangedEvent, value); }
6404 internal event EventHandler UIAViewChanged {
6405 add { Events.AddHandler (UIAViewChangedEvent, value); }
6406 remove { Events.RemoveHandler (UIAViewChangedEvent, value); }
6409 internal event EventHandler UIAFocusedItemChanged {
6410 add { Events.AddHandler (UIAFocusedItemChangedEvent, value); }
6411 remove { Events.RemoveHandler (UIAFocusedItemChangedEvent, value); }
6414 internal Rectangle UIAGetHeaderBounds (ListViewGroup group)
6416 return group.HeaderBounds;
6419 internal int UIAItemsLocationLength
6421 get { return items_location.Length; }
6424 private void OnUIACheckBoxesChanged ()
6426 EventHandler eh = (EventHandler) Events [UIACheckBoxesChangedEvent];
6428 eh (this, EventArgs.Empty);
6431 private void OnUIAShowGroupsChanged ()
6433 EventHandler eh = (EventHandler) Events [UIAShowGroupsChangedEvent];
6435 eh (this, EventArgs.Empty);
6438 private void OnUIAMultiSelectChanged ()
6440 EventHandler eh = (EventHandler) Events [UIAMultiSelectChangedEvent];
6442 eh (this, EventArgs.Empty);
6445 private void OnUIALabelEditChanged ()
6447 EventHandler eh = (EventHandler) Events [UIALabelEditChangedEvent];
6449 eh (this, EventArgs.Empty);
6452 private void OnUIAViewChanged ()
6454 EventHandler eh = (EventHandler) Events [UIAViewChangedEvent];
6456 eh (this, EventArgs.Empty);
6459 internal void OnUIAFocusedItemChanged ()
6461 EventHandler eh = (EventHandler) Events [UIAFocusedItemChangedEvent];
6463 eh (this, EventArgs.Empty);
6466 #endregion // UIA Framework: Methods, Properties and Events