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)
29 // - Feedback for item activation, change in cursor types as mouse moves.
36 using System.Collections;
37 using System.ComponentModel;
38 using System.ComponentModel.Design;
40 using System.Runtime.InteropServices;
41 using System.Globalization;
43 using System.Collections.Generic;
46 namespace System.Windows.Forms
48 [DefaultEvent ("SelectedIndexChanged")]
49 [DefaultProperty ("Items")]
50 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
52 [ClassInterface (ClassInterfaceType.AutoDispatch)]
54 [Docking (DockingBehavior.Ask)]
56 public class ListView : Control
58 private ItemActivation activation = ItemActivation.Standard;
59 private ListViewAlignment alignment = ListViewAlignment.Top;
60 private bool allow_column_reorder;
61 private bool auto_arrange = true;
62 private bool check_boxes;
63 private readonly CheckedIndexCollection checked_indices;
64 private readonly CheckedListViewItemCollection checked_items;
65 private readonly ColumnHeaderCollection columns;
66 internal ListViewItem focused_item;
67 private bool full_row_select;
68 private bool grid_lines;
69 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
70 private bool hide_selection = true;
71 private bool hover_selection;
72 private IComparer item_sorter;
73 private readonly ListViewItemCollection items;
75 private readonly ListViewGroupCollection groups;
76 private bool show_groups = true;
78 private bool label_edit;
79 private bool label_wrap = true;
80 private bool multiselect = true;
81 private bool scrollable = true;
82 private readonly SelectedIndexCollection selected_indices;
83 private readonly SelectedListViewItemCollection selected_items;
84 private SortOrder sort_order = SortOrder.None;
85 private ImageList state_image_list;
86 private 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 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 Point [] items_location;
101 private ItemMatrixLocation [] items_matrix_location;
102 private Size item_size; // used for caching item size
104 private Size tile_size;
107 // internal variables
108 internal ImageList large_image_list;
109 internal ImageList small_image_list;
110 internal Size text_size = Size.Empty;
113 static object AfterLabelEditEvent = new object ();
114 static object BeforeLabelEditEvent = new object ();
115 static object ColumnClickEvent = new object ();
116 static object ItemActivateEvent = new object ();
117 static object ItemCheckEvent = new object ();
118 static object ItemDragEvent = new object ();
119 static object SelectedIndexChangedEvent = new object ();
121 public event LabelEditEventHandler AfterLabelEdit {
122 add { Events.AddHandler (AfterLabelEditEvent, value); }
123 remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
127 [EditorBrowsable (EditorBrowsableState.Never)]
128 public new event EventHandler BackgroundImageChanged {
129 add { base.BackgroundImageChanged += value; }
130 remove { base.BackgroundImageChanged -= value; }
133 public event LabelEditEventHandler BeforeLabelEdit {
134 add { Events.AddHandler (BeforeLabelEditEvent, value); }
135 remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
138 public event ColumnClickEventHandler ColumnClick {
139 add { Events.AddHandler (ColumnClickEvent, value); }
140 remove { Events.RemoveHandler (ColumnClickEvent, value); }
143 public event EventHandler ItemActivate {
144 add { Events.AddHandler (ItemActivateEvent, value); }
145 remove { Events.RemoveHandler (ItemActivateEvent, value); }
148 public event ItemCheckEventHandler ItemCheck {
149 add { Events.AddHandler (ItemCheckEvent, value); }
150 remove { Events.RemoveHandler (ItemCheckEvent, value); }
153 public event ItemDragEventHandler ItemDrag {
154 add { Events.AddHandler (ItemDragEvent, value); }
155 remove { Events.RemoveHandler (ItemDragEvent, value); }
159 [EditorBrowsable (EditorBrowsableState.Never)]
160 public new event PaintEventHandler Paint {
161 add { base.Paint += value; }
162 remove { base.Paint -= value; }
165 public event EventHandler SelectedIndexChanged {
166 add { Events.AddHandler (SelectedIndexChangedEvent, value); }
167 remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
171 [EditorBrowsable (EditorBrowsableState.Never)]
172 public new event EventHandler TextChanged {
173 add { base.TextChanged += value; }
174 remove { base.TextChanged -= value; }
179 #region Public Constructors
182 background_color = ThemeEngine.Current.ColorWindow;
183 items = new ListViewItemCollection (this);
185 groups = new ListViewGroupCollection (this);
187 checked_indices = new CheckedIndexCollection (this);
188 checked_items = new CheckedListViewItemCollection (this);
189 columns = new ColumnHeaderCollection (this);
190 foreground_color = SystemColors.WindowText;
191 selected_indices = new SelectedIndexCollection (this);
192 selected_items = new SelectedListViewItemCollection (this);
193 items_location = new Point [16];
194 items_matrix_location = new ItemMatrixLocation [16];
196 border_style = BorderStyle.Fixed3D;
198 header_control = new HeaderControl (this);
199 header_control.Visible = false;
200 Controls.AddImplicit (header_control);
202 item_control = new ItemControl (this);
203 Controls.AddImplicit (item_control);
205 h_scroll = new ImplicitHScrollBar ();
206 Controls.AddImplicit (this.h_scroll);
208 v_scroll = new ImplicitVScrollBar ();
209 Controls.AddImplicit (this.v_scroll);
211 h_marker = v_marker = 0;
212 keysearch_tickcnt = 0;
214 // scroll bars are disabled initially
215 h_scroll.Visible = false;
216 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
217 v_scroll.Visible = false;
218 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
221 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
222 SizeChanged += new EventHandler (ListView_SizeChanged);
223 GotFocus += new EventHandler (FocusChanged);
224 LostFocus += new EventHandler (FocusChanged);
225 MouseWheel += new MouseEventHandler(ListView_MouseWheel);
227 this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
229 | ControlStyles.UseTextForAccessibility
233 #endregion // Public Constructors
235 #region Private Internal Properties
236 internal Size CheckBoxSize {
238 if (this.check_boxes) {
239 if (this.state_image_list != null)
240 return this.state_image_list.ImageSize;
242 return ThemeEngine.Current.ListViewCheckBoxSize;
248 internal Size ItemSize {
250 if (view != View.Details)
253 Size size = new Size ();
254 size.Height = item_size.Height;
255 for (int i = 0; i < columns.Count; i++)
256 size.Width += columns [i].Wd;
265 #endregion // Private Internal Properties
267 #region Protected Properties
268 protected override CreateParams CreateParams {
269 get { return base.CreateParams; }
272 protected override Size DefaultSize {
273 get { return ThemeEngine.Current.ListViewDefaultSize; }
275 #endregion // Protected Properties
277 #region Public Instance Properties
278 [DefaultValue (ItemActivation.Standard)]
279 public ItemActivation Activation {
280 get { return activation; }
282 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
283 value != ItemActivation.TwoClick) {
284 throw new InvalidEnumArgumentException (string.Format
285 ("Enum argument value '{0}' is not valid for Activation", value));
292 [DefaultValue (ListViewAlignment.Top)]
294 public ListViewAlignment Alignment {
295 get { return alignment; }
297 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
298 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
299 throw new InvalidEnumArgumentException (string.Format
300 ("Enum argument value '{0}' is not valid for Alignment", value));
303 if (this.alignment != value) {
305 // alignment does not matter in Details/List views
306 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
312 [DefaultValue (false)]
313 public bool AllowColumnReorder {
314 get { return allow_column_reorder; }
315 set { allow_column_reorder = value; }
318 [DefaultValue (true)]
319 public bool AutoArrange {
320 get { return auto_arrange; }
322 if (auto_arrange != value) {
323 auto_arrange = value;
324 // autoarrange does not matter in Details/List views
325 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
331 public override Color BackColor {
333 if (background_color.IsEmpty)
334 return ThemeEngine.Current.ColorWindow;
336 return background_color;
338 set { background_color = value; }
342 [EditorBrowsable (EditorBrowsableState.Never)]
343 public override Image BackgroundImage {
344 get { return base.BackgroundImage; }
345 set { base.BackgroundImage = value; }
348 [DefaultValue (BorderStyle.Fixed3D)]
350 public BorderStyle BorderStyle {
351 get { return InternalBorderStyle; }
352 set { InternalBorderStyle = value; }
355 [DefaultValue (false)]
356 public bool CheckBoxes {
357 get { return check_boxes; }
359 if (check_boxes != value) {
361 if (value && View == View.Tile)
362 throw new NotSupportedException ("CheckBoxes are not"
363 + " supported in Tile view. Choose a different"
364 + " view or set CheckBoxes to false.");
374 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
375 public CheckedIndexCollection CheckedIndices {
376 get { return checked_indices; }
380 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
381 public CheckedListViewItemCollection CheckedItems {
382 get { return checked_items; }
385 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
387 [MergableProperty (false)]
388 public ColumnHeaderCollection Columns {
389 get { return columns; }
393 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
394 public ListViewItem FocusedItem {
400 throw new NotImplementedException ();
405 public override Color ForeColor {
407 if (foreground_color.IsEmpty)
408 return ThemeEngine.Current.ColorWindowText;
410 return foreground_color;
412 set { foreground_color = value; }
415 [DefaultValue (false)]
416 public bool FullRowSelect {
417 get { return full_row_select; }
418 set { full_row_select = value; }
421 [DefaultValue (false)]
422 public bool GridLines {
423 get { return grid_lines; }
425 if (grid_lines != value) {
432 [DefaultValue (ColumnHeaderStyle.Clickable)]
433 public ColumnHeaderStyle HeaderStyle {
434 get { return header_style; }
436 if (header_style == value)
440 case ColumnHeaderStyle.Clickable:
441 case ColumnHeaderStyle.Nonclickable:
442 case ColumnHeaderStyle.None:
445 throw new InvalidEnumArgumentException (string.Format
446 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
449 header_style = value;
450 if (view == View.Details)
455 [DefaultValue (true)]
456 public bool HideSelection {
457 get { return hide_selection; }
459 if (hide_selection != value) {
460 hide_selection = value;
466 [DefaultValue (false)]
467 public bool HoverSelection {
468 get { return hover_selection; }
469 set { hover_selection = value; }
472 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
474 [MergableProperty (false)]
475 public ListViewItemCollection Items {
476 get { return items; }
479 [DefaultValue (false)]
480 public bool LabelEdit {
481 get { return label_edit; }
482 set { label_edit = value; }
485 [DefaultValue (true)]
487 public bool LabelWrap {
488 get { return label_wrap; }
490 if (label_wrap != value) {
497 [DefaultValue (null)]
498 public ImageList LargeImageList {
499 get { return large_image_list; }
501 large_image_list = value;
507 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
508 public IComparer ListViewItemSorter {
510 if (View != View.SmallIcon && View != View.LargeIcon && item_sorter is ItemComparer)
515 if (item_sorter != value) {
522 [DefaultValue (true)]
523 public bool MultiSelect {
524 get { return multiselect; }
525 set { multiselect = value; }
528 [DefaultValue (true)]
529 public bool Scrollable {
530 get { return scrollable; }
532 if (scrollable != value) {
540 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
541 public SelectedIndexCollection SelectedIndices {
542 get { return selected_indices; }
546 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
547 public SelectedListViewItemCollection SelectedItems {
548 get { return selected_items; }
553 public bool ShowGroups {
554 get { return show_groups; }
556 if (show_groups != value) {
563 [LocalizableAttribute (true)]
564 [MergableProperty (false)]
565 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
566 public ListViewGroupCollection Groups {
567 get { return groups; }
571 [DefaultValue (null)]
572 public ImageList SmallImageList {
573 get { return small_image_list; }
575 small_image_list = value;
580 [DefaultValue (SortOrder.None)]
581 public SortOrder Sorting {
582 get { return sort_order; }
584 if (!Enum.IsDefined (typeof (SortOrder), value)) {
585 throw new InvalidEnumArgumentException ("value", (int) value,
589 if (sort_order == value)
594 if (value == SortOrder.None) {
595 if (item_sorter != null) {
596 // ListViewItemSorter should never be reset for SmallIcon
597 // and LargeIcon view
598 if (View != View.SmallIcon && View != View.LargeIcon)
602 // in .NET 1.1, only internal IComparer would be
604 if (item_sorter is ItemComparer)
610 if (item_sorter == null)
611 item_sorter = new ItemComparer (value);
612 if (item_sorter is ItemComparer) {
614 item_sorter = new ItemComparer (value);
616 // in .NET 1.1, the sort order is not updated for
617 // SmallIcon and LargeIcon views if no custom IComparer
619 if (View != View.SmallIcon && View != View.LargeIcon)
620 item_sorter = new ItemComparer (value);
628 [DefaultValue (null)]
629 public ImageList StateImageList {
630 get { return state_image_list; }
632 state_image_list = value;
639 [EditorBrowsable (EditorBrowsableState.Never)]
640 public override string Text {
641 get { return base.Text; }
643 if (value == base.Text)
653 public Size TileSize {
658 if (value.Width <= 0 || value.Height <= 0)
659 throw new ArgumentOutOfRangeException ("value");
668 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
669 public ListViewItem TopItem {
672 if (this.items.Count == 0)
674 // if contents are not scrolled
675 // it is the first item
676 else if (h_marker == 0 && v_marker == 0)
677 return this.items [0];
678 // do a hit test for the scrolled position
680 for (int i = 0; i < items.Count; i++) {
681 Point item_loc = GetItemLocation (i);
682 if (item_loc.X >= 0 && item_loc.Y >= 0)
690 throw new NotImplementedException ();
696 [EditorBrowsable (EditorBrowsableState.Advanced)]
697 [DefaultValue (true)]
699 [MonoInternalNote ("Stub, not implemented")]
700 public bool UseCompatibleStateImageBehavior {
709 [DefaultValue (View.LargeIcon)]
713 if (!Enum.IsDefined (typeof (View), value))
714 throw new InvalidEnumArgumentException ("value", (int) value,
719 if (CheckBoxes && value == View.Tile)
720 throw new NotSupportedException ("CheckBoxes are not"
721 + " supported in Tile view. Choose a different"
722 + " view or set CheckBoxes to false.");
725 h_scroll.Value = v_scroll.Value = 0;
731 #endregion // Public Instance Properties
733 #region Internal Methods Properties
735 internal int FirstVisibleIndex {
738 if (this.items.Count == 0)
741 if (h_marker == 0 && v_marker == 0)
744 Size item_size = ItemSize;
745 for (int i = 0; i < items.Count; i++) {
746 Rectangle item_rect = new Rectangle (GetItemLocation (i), item_size);
747 if (item_rect.Right >= 0 && item_rect.Bottom >= 0)
756 internal int LastVisibleIndex {
758 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
759 if (View == View.List || Alignment == ListViewAlignment.Left) {
760 if (GetItemLocation (i).X > item_control.ClientRectangle.Right)
763 if (GetItemLocation (i).Y > item_control.ClientRectangle.Bottom)
768 return Items.Count - 1;
772 internal void OnSelectedIndexChanged ()
775 OnSelectedIndexChanged (EventArgs.Empty);
778 internal int TotalWidth {
779 get { return Math.Max (this.Width, this.layout_wd); }
782 internal int TotalHeight {
783 get { return Math.Max (this.Height, this.layout_ht); }
786 internal void Redraw (bool recalculate)
788 // Avoid calculations when control is being updated
793 CalculateListView (this.alignment);
798 const int text_padding = 15;
800 internal Size GetChildColumnSize (int index)
802 Size ret_size = Size.Empty;
803 ColumnHeader col = this.columns [index];
805 if (col.Width == -2) { // autosize = max(items, columnheader)
806 Size size = Size.Ceiling (this.DeviceContext.MeasureString
807 (col.Text, this.Font));
808 size.Width += text_padding;
809 ret_size = BiggestItem (index);
810 if (size.Width > ret_size.Width)
813 else { // -1 and all the values < -2 are put under one category
814 ret_size = BiggestItem (index);
815 // fall back to empty columns' width if no subitem is available for a column
816 if (ret_size.IsEmpty) {
817 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
818 if (col.Text.Length > 0)
819 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
820 (col.Text, this.Font)).Height;
822 ret_size.Height = this.Font.Height;
826 ret_size.Height += text_padding;
828 // adjust the size for icon and checkbox for 0th column
830 ret_size.Width += (this.CheckBoxSize.Width + 4);
831 if (this.small_image_list != null)
832 ret_size.Width += this.small_image_list.ImageSize.Width;
837 // Returns the size of biggest item text in a column.
838 private Size BiggestItem (int col)
840 Size temp = Size.Empty;
841 Size ret_size = Size.Empty;
843 // 0th column holds the item text, we check the size of
844 // the various subitems falling in that column and get
845 // the biggest one's size.
846 foreach (ListViewItem item in items) {
847 if (col >= item.SubItems.Count)
850 temp = Size.Ceiling (this.DeviceContext.MeasureString
851 (item.SubItems [col].Text, this.Font));
852 if (temp.Width > ret_size.Width)
856 // adjustment for space
857 if (!ret_size.IsEmpty)
863 const int max_wrap_padding = 38;
865 // Sets the size of the biggest item text as per the view
866 private void CalcTextSize ()
868 // clear the old value
869 text_size = Size.Empty;
871 if (items.Count == 0)
874 text_size = BiggestItem (0);
876 if (view == View.LargeIcon && this.label_wrap) {
877 Size temp = Size.Empty;
878 if (this.check_boxes)
879 temp.Width += 2 * this.CheckBoxSize.Width;
880 int icon_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
881 temp.Width += icon_w + max_wrap_padding;
882 // wrapping is done for two lines only
883 if (text_size.Width > temp.Width) {
884 text_size.Width = temp.Width;
885 text_size.Height *= 2;
888 else if (view == View.List) {
889 // in list view max text shown in determined by the
890 // control width, even if scolling is enabled.
891 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
892 if (this.small_image_list != null)
893 max_wd -= this.small_image_list.ImageSize.Width;
895 if (text_size.Width > max_wd)
896 text_size.Width = max_wd;
899 // we do the default settings, if we have got 0's
900 if (text_size.Height <= 0)
901 text_size.Height = this.Font.Height;
902 if (text_size.Width <= 0)
903 text_size.Width = this.Width;
906 text_size.Width += 4;
907 text_size.Height += 2;
910 private void Scroll (ScrollBar scrollbar, int delta)
912 if (delta == 0 || !scrollbar.Visible)
916 if (scrollbar == h_scroll)
917 max = h_scroll.Maximum - item_control.Width;
919 max = v_scroll.Maximum - item_control.Height;
921 int val = scrollbar.Value + delta;
924 else if (val < scrollbar.Minimum)
925 val = scrollbar.Minimum;
926 scrollbar.Value = val;
929 private void CalculateScrollBars ()
931 Rectangle client_area = ClientRectangle;
933 if (!this.scrollable || this.items.Count <= 0) {
934 h_scroll.Visible = false;
935 v_scroll.Visible = false;
936 item_control.Location = new Point (0, header_control.Height);
937 item_control.Height = ClientRectangle.Width - header_control.Height;
938 item_control.Width = ClientRectangle.Width;
939 header_control.Width = ClientRectangle.Width;
943 // Don't calculate if the view is not displayable
944 if (client_area.Height < 0 || client_area.Width < 0)
947 // making a scroll bar visible might make
948 // other scroll bar visible
949 if (layout_wd > client_area.Right) {
950 h_scroll.Visible = true;
951 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
952 v_scroll.Visible = true;
954 v_scroll.Visible = false;
955 } else if (layout_ht > client_area.Bottom) {
956 v_scroll.Visible = true;
957 if ((layout_wd + v_scroll.Width) > client_area.Right)
958 h_scroll.Visible = true;
960 h_scroll.Visible = false;
962 h_scroll.Visible = false;
963 v_scroll.Visible = false;
966 item_control.Height = ClientRectangle.Height - header_control.Height;
968 if (h_scroll.is_visible) {
969 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
970 h_scroll.Minimum = 0;
972 // if v_scroll is visible, adjust the maximum of the
973 // h_scroll to account for the width of v_scroll
974 if (v_scroll.Visible) {
975 h_scroll.Maximum = layout_wd + v_scroll.Width;
976 h_scroll.Width = client_area.Width - v_scroll.Width;
979 h_scroll.Maximum = layout_wd;
980 h_scroll.Width = client_area.Width;
983 h_scroll.LargeChange = client_area.Width;
984 h_scroll.SmallChange = Font.Height;
985 item_control.Height -= h_scroll.Height;
988 if (header_control.is_visible)
989 header_control.Width = ClientRectangle.Width;
990 item_control.Width = ClientRectangle.Width;
992 if (v_scroll.is_visible) {
993 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
994 v_scroll.Minimum = 0;
996 // if h_scroll is visible, adjust the maximum of the
997 // v_scroll to account for the height of h_scroll
998 if (h_scroll.Visible) {
999 v_scroll.Maximum = layout_ht + h_scroll.Height;
1000 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
1002 v_scroll.Maximum = layout_ht;
1003 v_scroll.Height = client_area.Height;
1006 v_scroll.LargeChange = client_area.Height;
1007 v_scroll.SmallChange = Font.Height;
1008 if (header_control.Visible)
1009 header_control.Width -= v_scroll.Width;
1010 item_control.Width -= v_scroll.Width;
1015 internal int GetReorderedColumnIndex (ColumnHeader column)
1017 if (reordered_column_indices == null)
1018 return column.Index;
1020 for (int i = 0; i < Columns.Count; i++)
1021 if (reordered_column_indices [i] == column.Index)
1028 internal ColumnHeader GetReorderedColumn (int index)
1030 if (reordered_column_indices == null)
1031 return Columns [index];
1033 return Columns [reordered_column_indices [index]];
1036 internal void ReorderColumn (ColumnHeader col, int index)
1039 ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
1041 ColumnReorderedEventArgs args = new ColumnReorderedEventArgs (col.Index, index, col);
1045 header_control.Invalidate ();
1046 item_control.Invalidate ();
1051 if (reordered_column_indices == null) {
1052 reordered_column_indices = new int [Columns.Count];
1053 for (int i = 0; i < Columns.Count; i++)
1054 reordered_column_indices [i] = i;
1057 if (reordered_column_indices [index] == col.Index)
1060 int[] curr = reordered_column_indices;
1061 int[] result = new int [Columns.Count];
1063 for (int i = 0; i < Columns.Count; i++) {
1064 if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
1068 result [i] = col.Index;
1070 result [i] = curr [curr_idx++];
1073 reordered_column_indices = result;
1075 header_control.Invalidate ();
1076 item_control.Invalidate ();
1079 Size LargeIconItemSize {
1081 int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
1082 int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
1083 int w = CheckBoxSize.Width + 2 + Math.Max (text_size.Width, image_w);
1084 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
1085 return new Size (w, h);
1089 Size SmallIconItemSize {
1091 int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
1092 int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1093 int w = text_size.Width + 2 + CheckBoxSize.Width + image_w;
1094 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
1095 return new Size (w, h);
1102 // Calculate tile size if needed
1103 // It appears that using Font.Size instead of a SizeF value can give us
1104 // a slightly better approach to the proportions defined in .Net
1105 if (tile_size == Size.Empty) {
1106 int image_w = LargeImageList == null ? 0 : LargeImageList.ImageSize.Width;
1107 int image_h = LargeImageList == null ? 0 : LargeImageList.ImageSize.Height;
1108 int w = (int)Font.Size * ThemeEngine.Current.ListViewTileWidthFactor + image_w + 4;
1109 int h = Math.Max ((int)Font.Size * ThemeEngine.Current.ListViewTileHeightFactor, image_h);
1111 tile_size = new Size (w, h);
1119 int GetDetailsItemHeight ()
1122 int checkbox_height = CheckBoxes ? CheckBoxSize.Height : 0;
1123 int small_image_height = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
1124 item_height = Math.Max (checkbox_height, text_size.Height);
1125 item_height = Math.Max (item_height, small_image_height);
1130 void SetItemLocation (int index, int x, int y, int row, int col)
1132 Point old_location = items_location [index];
1133 if (old_location.X == x && old_location.Y == y)
1136 Size item_size = ItemSize;
1137 Rectangle old_rect = new Rectangle (GetItemLocation (index), item_size);
1139 items_location [index] = new Point (x, y);
1140 items_matrix_location [index] = new ItemMatrixLocation (row, col);
1142 // Invalidate both previous and new bounds
1143 item_control.Invalidate (old_rect);
1144 item_control.Invalidate (new Rectangle (GetItemLocation (index), item_size));
1149 int[,] item_index_matrix;
1151 void LayoutIcons (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
1153 header_control.Visible = false;
1154 header_control.Size = Size.Empty;
1155 item_control.Visible = true;
1156 item_control.Location = Point.Empty;
1157 ItemSize = item_size; // Cache item size
1159 if (items.Count == 0)
1162 Size sz = item_size;
1163 Rectangle area = ClientRectangle;
1166 rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(sz.Height + y_spacing));
1169 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
1171 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(sz.Width + x_spacing));
1174 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
1177 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
1178 layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
1179 item_index_matrix = new int [rows, cols];
1182 for (int i = 0; i < items.Count; i++) {
1183 int x = col * (sz.Width + x_spacing);
1184 int y = row * (sz.Height + y_spacing);
1185 SetItemLocation (i, x, y, row, col);
1186 item_index_matrix [row, col] = i;
1187 items [i].Layout ();
1189 if (++row == rows) {
1194 if (++col == cols) {
1201 item_control.Size = new Size (layout_wd, layout_ht);
1204 void LayoutHeader ()
1207 for (int i = 0; i < Columns.Count; i++) {
1208 ColumnHeader col = GetReorderedColumn (i);
1211 col.CalcColumnHeader ();
1215 if (x < ClientRectangle.Width)
1216 x = ClientRectangle.Width;
1218 if (header_style == ColumnHeaderStyle.None) {
1219 header_control.Visible = false;
1220 header_control.Size = Size.Empty;
1222 header_control.Width = x;
1223 header_control.Height = columns [0].Ht;
1224 header_control.Visible = true;
1228 void LayoutDetails ()
1230 if (columns.Count == 0) {
1231 header_control.Visible = false;
1232 item_control.Visible = false;
1238 item_control.Visible = true;
1239 item_control.Location = new Point (0, header_control.Height);
1241 int item_height = GetDetailsItemHeight ();
1242 ItemSize = new Size (0, item_height); // We only cache Height for details view
1245 if (items.Count > 0) {
1246 for (int i = 0; i < items.Count; i++) {
1247 SetItemLocation (i, 0, y, 0, 0);
1248 items [i].Layout ();
1249 y += item_height + 2;
1252 // some space for bottom gridline
1257 layout_wd = Math.Max (header_control.Width, item_control.Width);
1258 layout_ht = y + header_control.Height;
1261 private void AdjustItemsPositionArray (int count)
1263 if (items_location.Length >= count)
1266 // items_location and items_matrix_location must keep the same length
1267 count = Math.Max (count, items_location.Length * 2);
1268 items_location = new Point [count];
1269 items_matrix_location = new ItemMatrixLocation [count];
1272 private void CalculateListView (ListViewAlignment align)
1276 AdjustItemsPositionArray (items.Count);
1283 case View.SmallIcon:
1284 LayoutIcons (SmallIconItemSize, alignment == ListViewAlignment.Left, 4, 2);
1287 case View.LargeIcon:
1288 LayoutIcons (LargeIconItemSize, alignment == ListViewAlignment.Left,
1289 ThemeEngine.Current.ListViewHorizontalSpacing,
1290 ThemeEngine.Current.ListViewVerticalSpacing);
1294 LayoutIcons (SmallIconItemSize, true, 4, 2);
1298 LayoutIcons (TileItemSize, alignment == ListViewAlignment.Left,
1299 ThemeEngine.Current.ListViewHorizontalSpacing,
1300 ThemeEngine.Current.ListViewVerticalSpacing);
1305 CalculateScrollBars ();
1308 internal Point GetItemLocation (int index)
1310 Point loc = items_location [index];
1311 loc.X -= h_marker; // Adjust to scroll
1317 private bool KeySearchString (KeyEventArgs ke)
1319 int current_tickcnt = Environment.TickCount;
1320 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
1321 keysearch_text = string.Empty;
1324 keysearch_text += (char) ke.KeyData;
1325 keysearch_tickcnt = current_tickcnt;
1327 int start = FocusedItem == null ? 0 : FocusedItem.Index;
1330 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1331 CompareOptions.IgnoreCase)) {
1332 SetFocusedItem (Items [i]);
1333 items [i].Selected = true;
1337 i = (i + 1 < Items.Count) ? i+1 : 0;
1345 int GetAdjustedIndex (Keys key)
1349 if (View == View.Details) {
1352 result = FocusedItem.Index - 1;
1355 result = FocusedItem.Index + 1;
1356 if (result == items.Count)
1360 int last_index = LastVisibleIndex;
1361 Rectangle item_rect = new Rectangle (GetItemLocation (last_index), ItemSize);
1362 if (item_rect.Bottom > item_control.ClientRectangle.Bottom)
1364 if (FocusedItem.Index == last_index) {
1365 if (FocusedItem.Index < Items.Count - 1) {
1366 int page_size = item_control.Height / ItemSize.Height - 1;
1367 result = FocusedItem.Index + page_size - 1;
1368 if (result >= Items.Count)
1369 result = Items.Count - 1;
1372 result = last_index;
1375 int first_index = FirstVisibleIndex;
1376 if (GetItemLocation (first_index).Y < 0)
1378 if (FocusedItem.Index == first_index) {
1379 if (first_index > 0) {
1380 int page_size = item_control.Height / ItemSize.Height - 1;
1381 result = first_index - page_size + 1;
1386 result = first_index;
1392 ItemMatrixLocation item_matrix_location = items_matrix_location [FocusedItem.Index];
1393 int row = item_matrix_location.Row;
1394 int col = item_matrix_location.Col;
1400 return item_index_matrix [row, col - 1];
1403 if (col == (cols - 1))
1405 while (item_index_matrix [row, col + 1] == 0) {
1410 return item_index_matrix [row, col + 1];
1415 return item_index_matrix [row - 1, col];
1418 if (row == (rows - 1) || row == Items.Count - 1)
1420 while (item_index_matrix [row + 1, col] == 0) {
1425 return item_index_matrix [row + 1, col];
1432 ListViewItem selection_start;
1434 private bool SelectItems (ArrayList sel_items)
1436 bool changed = false;
1437 ArrayList curr_items = SelectedItems.List;
1438 foreach (ListViewItem item in curr_items)
1439 if (!sel_items.Contains (item)) {
1440 item.Selected = false;
1443 foreach (ListViewItem item in sel_items)
1444 if (!item.Selected) {
1445 item.Selected = true;
1451 private void UpdateMultiSelection (int index, bool reselect)
1453 bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
1454 bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
1455 ListViewItem item = items [index];
1457 if (shift_pressed && selection_start != null) {
1458 ArrayList list = new ArrayList ();
1459 int start_index = selection_start.Index;
1460 int start = Math.Min (start_index, index);
1461 int end = Math.Max (start_index, index);
1462 if (View == View.Details) {
1463 for (int i = start; i <= end; i++)
1464 list.Add (items [i]);
1466 ItemMatrixLocation start_item_matrix_location = items_matrix_location [start];
1467 ItemMatrixLocation end_item_matrix_location = items_matrix_location [end];
1468 int left = Math.Min (start_item_matrix_location.Col, end_item_matrix_location.Col);
1469 int right = Math.Max (start_item_matrix_location.Col, end_item_matrix_location.Col);
1470 int top = Math.Min (start_item_matrix_location.Row, end_item_matrix_location.Row);
1471 int bottom = Math.Max (start_item_matrix_location.Row, end_item_matrix_location.Row);
1473 for (int i = 0; i < items.Count; i++) {
1474 ItemMatrixLocation item_matrix_loc = items_matrix_location [i];
1476 if (item_matrix_loc.Row >= top && item_matrix_loc.Row <= bottom &&
1477 item_matrix_loc.Col >= left && item_matrix_loc.Col <= right)
1478 list.Add (items [i]);
1482 } else if (ctrl_pressed) {
1483 item.Selected = !item.Selected;
1484 selection_start = item;
1487 // do not unselect, and reselect the item
1488 foreach (int itemIndex in SelectedIndices) {
1489 if (index == itemIndex)
1491 items [itemIndex].Selected = false;
1494 SelectedItems.Clear ();
1495 item.Selected = true;
1497 selection_start = item;
1501 internal override bool InternalPreProcessMessage (ref Message msg)
1503 if (msg.Msg == (int)Msg.WM_KEYDOWN) {
1504 Keys key_data = (Keys)msg.WParam.ToInt32();
1505 if (HandleNavKeys (key_data))
1508 return base.InternalPreProcessMessage (ref msg);
1511 bool HandleNavKeys (Keys key_data)
1513 if (Items.Count == 0 || !item_control.Visible)
1516 if (FocusedItem == null)
1517 SetFocusedItem (Items [0]);
1521 SelectIndex (Items.Count - 1);
1534 SelectIndex (GetAdjustedIndex (key_data));
1544 void SelectIndex (int index)
1550 UpdateMultiSelection (index, true);
1551 else if (!items [index].Selected)
1552 items [index].Selected = true;
1554 SetFocusedItem (items [index]);
1555 EnsureVisible (index);
1558 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1560 if (ke.Handled || Items.Count == 0 || !item_control.Visible)
1563 ke.Handled = KeySearchString (ke);
1566 private MouseEventArgs TranslateMouseEventArgs (MouseEventArgs args)
1568 Point loc = PointToClient (Control.MousePosition);
1569 return new MouseEventArgs (args.Button, args.Clicks, loc.X, loc.Y, args.Delta);
1572 internal class ItemControl : Control {
1575 ListViewItem clicked_item;
1576 ListViewItem last_clicked_item;
1577 bool hover_processed = false;
1578 bool checking = false;
1580 ListViewLabelEditTextBox edit_text_box;
1581 internal ListViewItem edit_item;
1582 LabelEditEventArgs edit_args;
1584 public ItemControl (ListView owner)
1587 DoubleClick += new EventHandler(ItemsDoubleClick);
1588 MouseDown += new MouseEventHandler(ItemsMouseDown);
1589 MouseMove += new MouseEventHandler(ItemsMouseMove);
1590 MouseHover += new EventHandler(ItemsMouseHover);
1591 MouseUp += new MouseEventHandler(ItemsMouseUp);
1594 void ItemsDoubleClick (object sender, EventArgs e)
1596 if (owner.activation == ItemActivation.Standard)
1597 owner.OnItemActivate (EventArgs.Empty);
1607 BoxSelect box_select_mode = BoxSelect.None;
1608 ArrayList prev_selection;
1609 Point box_select_start;
1611 Rectangle box_select_rect;
1612 internal Rectangle BoxSelectRectangle {
1613 get { return box_select_rect; }
1615 if (box_select_rect == value)
1618 InvalidateBoxSelectRect ();
1619 box_select_rect = value;
1620 InvalidateBoxSelectRect ();
1624 void InvalidateBoxSelectRect ()
1626 if (BoxSelectRectangle.Size.IsEmpty)
1629 Rectangle edge = BoxSelectRectangle;
1635 edge.Y = BoxSelectRectangle.Bottom - 1;
1637 edge.Y = BoxSelectRectangle.Y - 1;
1639 edge.Height = BoxSelectRectangle.Height + 2;
1641 edge.X = BoxSelectRectangle.Right - 1;
1645 private Rectangle CalculateBoxSelectRectangle (Point pt)
1647 int left = Math.Min (box_select_start.X, pt.X);
1648 int right = Math.Max (box_select_start.X, pt.X);
1649 int top = Math.Min (box_select_start.Y, pt.Y);
1650 int bottom = Math.Max (box_select_start.Y, pt.Y);
1651 return Rectangle.FromLTRB (left, top, right, bottom);
1654 ArrayList BoxSelectedItems {
1656 ArrayList result = new ArrayList ();
1657 Size item_size = owner.ItemSize;
1658 for (int i = 0; i < owner.Items.Count; i++) {
1659 Rectangle r = new Rectangle (owner.GetItemLocation (i), item_size);
1661 r.Y += r.Height / 4;
1664 if (BoxSelectRectangle.IntersectsWith (r))
1665 result.Add (owner.Items [i]);
1671 private bool PerformBoxSelection (Point pt)
1673 if (box_select_mode == BoxSelect.None)
1676 BoxSelectRectangle = CalculateBoxSelectRectangle (pt);
1678 ArrayList box_items = BoxSelectedItems;
1682 switch (box_select_mode) {
1684 case BoxSelect.Normal:
1688 case BoxSelect.Control:
1689 items = new ArrayList ();
1690 foreach (ListViewItem item in prev_selection)
1691 if (!box_items.Contains (item))
1693 foreach (ListViewItem item in box_items)
1694 if (!prev_selection.Contains (item))
1698 case BoxSelect.Shift:
1700 foreach (ListViewItem item in box_items)
1701 prev_selection.Remove (item);
1702 foreach (ListViewItem item in prev_selection)
1707 throw new Exception ("Unexpected Selection mode: " + box_select_mode);
1711 owner.SelectItems (items);
1717 private void ToggleCheckState (ListViewItem item)
1719 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1720 item.Checked = !item.Checked;
1721 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1723 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1724 owner.OnItemCheck (ice);
1727 private void ItemsMouseDown (object sender, MouseEventArgs me)
1729 if (owner.items.Count == 0) {
1730 owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
1734 Size item_size = owner.ItemSize;
1735 Point pt = new Point (me.X, me.Y);
1736 for (int i = 0; i < owner.items.Count; i++) {
1737 Rectangle item_rect = new Rectangle (owner.GetItemLocation (i), item_size);
1738 if (!item_rect.Contains (pt))
1741 if (me.Clicks == 1 && owner.items [i].CheckRectReal.Contains (pt)) {
1743 ToggleCheckState (owner.items [i]);
1744 owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
1748 if (owner.View == View.Details && !owner.FullRowSelect) {
1749 if (owner.items [i].GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1750 clicked_item = owner.items [i];
1754 clicked_item = owner.items [i];
1758 if (clicked_item != null) {
1759 owner.SetFocusedItem (clicked_item);
1760 bool changed = !clicked_item.Selected;
1762 if (owner.MultiSelect) {
1763 bool reselect = (!owner.LabelEdit || changed);
1764 owner.UpdateMultiSelection (clicked_item.Index, reselect);
1766 clicked_item.Selected = true;
1769 // Raise double click if the item was clicked. On MS the
1770 // double click is only raised if you double click an item
1771 if (me.Clicks > 1) {
1772 owner.OnDoubleClick (EventArgs.Empty);
1773 if (owner.CheckBoxes)
1774 ToggleCheckState (clicked_item);
1775 } else if (me.Clicks == 1) {
1776 owner.OnClick (EventArgs.Empty);
1777 if (owner.LabelEdit && !changed)
1778 BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit
1781 if (owner.MultiSelect) {
1782 Keys mods = XplatUI.State.ModifierKeys;
1783 if ((mods & Keys.Shift) != 0)
1784 box_select_mode = BoxSelect.Shift;
1785 else if ((mods & Keys.Control) != 0)
1786 box_select_mode = BoxSelect.Control;
1788 box_select_mode = BoxSelect.Normal;
1789 box_select_start = pt;
1790 prev_selection = owner.SelectedItems.List;
1791 } else if (owner.SelectedItems.Count > 0) {
1792 owner.SelectedItems.Clear ();
1796 owner.OnMouseDown (owner.TranslateMouseEventArgs (me));
1799 private void ItemsMouseMove (object sender, MouseEventArgs me)
1801 bool done = PerformBoxSelection (new Point (me.X, me.Y));
1803 if (!done && owner.HoverSelection && hover_processed) {
1805 Point pt = PointToClient (Control.MousePosition);
1806 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1807 if (item != null && !item.Selected) {
1808 hover_processed = false;
1809 XplatUI.ResetMouseHover (Handle);
1813 owner.OnMouseMove (owner.TranslateMouseEventArgs (me));
1817 private void ItemsMouseHover (object sender, EventArgs e)
1819 owner.OnMouseHover(e);
1821 if (Capture || !owner.HoverSelection)
1824 hover_processed = true;
1825 Point pt = PointToClient (Control.MousePosition);
1826 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1831 item.Selected = true;
1834 private void ItemsMouseUp (object sender, MouseEventArgs me)
1837 if (owner.Items.Count == 0) {
1838 owner.OnMouseUp (owner.TranslateMouseEventArgs (me));
1842 Point pt = new Point (me.X, me.Y);
1844 Rectangle rect = Rectangle.Empty;
1845 if (clicked_item != null) {
1846 if (owner.view == View.Details && !owner.full_row_select)
1847 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1849 rect = clicked_item.Bounds;
1851 if (rect.Contains (pt)) {
1852 switch (owner.activation) {
1853 case ItemActivation.OneClick:
1854 owner.OnItemActivate (EventArgs.Empty);
1857 case ItemActivation.TwoClick:
1858 if (last_clicked_item == clicked_item) {
1859 owner.OnItemActivate (EventArgs.Empty);
1860 last_clicked_item = null;
1862 last_clicked_item = clicked_item;
1865 // DoubleClick activation is handled in another handler
1869 } else if (!checking && owner.SelectedItems.Count > 0 && BoxSelectRectangle.Size.IsEmpty) {
1870 // Need this to clean up background clicks
1871 owner.SelectedItems.Clear ();
1874 clicked_item = null;
1875 box_select_start = Point.Empty;
1876 BoxSelectRectangle = Rectangle.Empty;
1877 prev_selection = null;
1878 box_select_mode = BoxSelect.None;
1880 owner.OnMouseUp (owner.TranslateMouseEventArgs (me));
1883 private void LabelEditFinished (object sender, EventArgs e)
1885 EndEdit (edit_item);
1888 private void LabelEditCancelled (object sender, EventArgs e)
1890 edit_args.SetLabel (null);
1891 EndEdit (edit_item);
1894 private void LabelTextChanged (object sender, EventArgs e)
1896 if (edit_args != null)
1897 edit_args.SetLabel (edit_text_box.Text);
1900 internal void BeginEdit (ListViewItem item)
1902 if (edit_item != null)
1903 EndEdit (edit_item);
1905 if (edit_text_box == null) {
1906 edit_text_box = new ListViewLabelEditTextBox ();
1907 edit_text_box.BorderStyle = BorderStyle.FixedSingle;
1908 edit_text_box.EditingCancelled += new EventHandler (LabelEditCancelled);
1909 edit_text_box.EditingFinished += new EventHandler (LabelEditFinished);
1910 edit_text_box.TextChanged += new EventHandler (LabelTextChanged);
1911 edit_text_box.Visible = false;
1912 Controls.Add (edit_text_box);
1915 item.EnsureVisible();
1917 edit_text_box.Reset ();
1919 switch (owner.view) {
1921 case View.SmallIcon:
1923 edit_text_box.TextAlign = HorizontalAlignment.Left;
1924 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
1925 SizeF sizef = DeviceContext.MeasureString (item.Text, item.Font);
1926 edit_text_box.Width = (int)sizef.Width + 4;
1927 edit_text_box.MaxWidth = owner.ClientRectangle.Width - edit_text_box.Bounds.X;
1928 edit_text_box.WordWrap = false;
1929 edit_text_box.Multiline = false;
1931 case View.LargeIcon:
1932 edit_text_box.TextAlign = HorizontalAlignment.Center;
1933 edit_text_box.Bounds = item.GetBounds (ItemBoundsPortion.Label);
1934 sizef = DeviceContext.MeasureString (item.Text, item.Font);
1935 edit_text_box.Width = (int)sizef.Width + 4;
1936 edit_text_box.MaxWidth = item.GetBounds(ItemBoundsPortion.Entire).Width;
1937 edit_text_box.MaxHeight = owner.ClientRectangle.Height - edit_text_box.Bounds.Y;
1938 edit_text_box.WordWrap = true;
1939 edit_text_box.Multiline = true;
1945 edit_text_box.Text = item.Text;
1946 edit_text_box.Font = item.Font;
1947 edit_text_box.Visible = true;
1948 edit_text_box.Focus ();
1949 edit_text_box.SelectAll ();
1951 edit_args = new LabelEditEventArgs (owner.Items.IndexOf (edit_item));
1952 owner.OnBeforeLabelEdit (edit_args);
1954 if (edit_args.CancelEdit)
1958 internal void CancelEdit (ListViewItem item)
1960 // do nothing if there's no item being edited, or if the
1961 // item being edited is not the one passed in
1962 if (edit_item == null || edit_item != item)
1965 edit_args.SetLabel (null);
1969 internal void EndEdit (ListViewItem item)
1971 // do nothing if there's no item being edited, or if the
1972 // item being edited is not the one passed in
1973 if (edit_item == null || edit_item != item)
1976 owner.OnAfterLabelEdit (edit_args);
1977 if (!edit_args.CancelEdit && edit_args.Label != null)
1978 edit_item.Text = edit_text_box.Text;
1980 if (edit_text_box != null) {
1981 if (edit_text_box.Visible)
1982 edit_text_box.Visible = false;
1983 // ensure listview gets focus
1990 internal override void OnPaintInternal (PaintEventArgs pe)
1992 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1995 protected override void WndProc (ref Message m)
1997 switch ((Msg)m.Msg) {
1998 case Msg.WM_KILLFOCUS:
1999 owner.Select (false, true);
2001 case Msg.WM_SETFOCUS:
2002 owner.Select (false, true);
2004 case Msg.WM_RBUTTONDOWN:
2005 owner.Select (false, true);
2010 base.WndProc (ref m);
2014 internal class ListViewLabelEditTextBox : TextBox
2019 int max_height = -1;
2020 int min_height = -1;
2022 int old_number_lines = 1;
2024 SizeF text_size_one_char;
2026 public ListViewLabelEditTextBox ()
2028 min_height = DefaultSize.Height;
2029 text_size_one_char = DeviceContext.MeasureString ("B", Font);
2032 public int MaxWidth {
2034 if (value < min_width)
2035 max_width = min_width;
2041 public int MaxHeight {
2043 if (value < min_height)
2044 max_height = min_height;
2050 public new int Width {
2060 public override Font Font {
2066 text_size_one_char = DeviceContext.MeasureString ("B", Font);
2070 protected override void OnTextChanged (EventArgs e)
2072 SizeF text_size = DeviceContext.MeasureString (Text, Font);
2074 int new_width = (int)text_size.Width + 8;
2077 ResizeTextBoxWidth (new_width);
2079 if (Width != max_width)
2080 ResizeTextBoxWidth (new_width);
2082 int number_lines = Lines.Length;
2084 if (number_lines != old_number_lines) {
2085 int new_height = number_lines * (int)text_size_one_char.Height + 4;
2086 old_number_lines = number_lines;
2088 ResizeTextBoxHeight (new_height);
2092 base.OnTextChanged (e);
2095 protected override bool IsInputKey (Keys key_data)
2097 if ((key_data & Keys.Alt) == 0) {
2098 switch (key_data & Keys.KeyCode) {
2105 return base.IsInputKey (key_data);
2108 protected override void OnKeyDown (KeyEventArgs e)
2113 switch (e.KeyCode) {
2117 OnEditingFinished (e);
2122 OnEditingCancelled (e);
2127 protected override void OnLostFocus (EventArgs e)
2130 OnEditingFinished (e);
2134 protected void OnEditingCancelled (EventArgs e)
2136 EventHandler eh = (EventHandler)(Events [EditingCancelledEvent]);
2141 protected void OnEditingFinished (EventArgs e)
2143 EventHandler eh = (EventHandler)(Events [EditingFinishedEvent]);
2148 private void ResizeTextBoxWidth (int new_width)
2150 if (new_width > max_width)
2151 base.Width = max_width;
2153 if (new_width >= min_width)
2154 base.Width = new_width;
2156 base.Width = min_width;
2159 private void ResizeTextBoxHeight (int new_height)
2161 if (new_height > max_height)
2162 base.Height = max_height;
2164 if (new_height >= min_height)
2165 base.Height = new_height;
2167 base.Height = min_height;
2170 public void Reset ()
2177 old_number_lines = 1;
2179 Text = String.Empty;
2184 static object EditingCancelledEvent = new object ();
2185 public event EventHandler EditingCancelled {
2186 add { Events.AddHandler (EditingCancelledEvent, value); }
2187 remove { Events.RemoveHandler (EditingCancelledEvent, value); }
2190 static object EditingFinishedEvent = new object ();
2191 public event EventHandler EditingFinished {
2192 add { Events.AddHandler (EditingFinishedEvent, value); }
2193 remove { Events.RemoveHandler (EditingFinishedEvent, value); }
2197 internal override void OnPaintInternal (PaintEventArgs pe)
2202 CalculateScrollBars ();
2205 void FocusChanged (object o, EventArgs args)
2207 if (Items.Count == 0)
2210 if (FocusedItem == null)
2211 SetFocusedItem (Items [0]);
2213 item_control.Invalidate (FocusedItem.Bounds);
2216 private void ListView_MouseWheel (object sender, MouseEventArgs me)
2218 if (Items.Count == 0)
2221 int lines = me.Delta / 120;
2228 case View.SmallIcon:
2229 Scroll (v_scroll, -ItemSize.Height * SystemInformation.MouseWheelScrollLines * lines);
2231 case View.LargeIcon:
2232 Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * lines);
2235 Scroll (h_scroll, -ItemSize.Width * lines);
2240 private void ListView_SizeChanged (object sender, EventArgs e)
2242 CalculateListView (alignment);
2245 private void SetFocusedItem (ListViewItem item)
2247 if (focused_item != null)
2248 focused_item.Focused = false;
2251 item.Focused = true;
2253 focused_item = item;
2256 private void HorizontalScroller (object sender, EventArgs e)
2258 item_control.EndEdit (item_control.edit_item);
2260 // Avoid unnecessary flickering, when button is
2261 // kept pressed at the end
2262 if (h_marker != h_scroll.Value) {
2264 int pixels = h_marker - h_scroll.Value;
2266 h_marker = h_scroll.Value;
2267 if (header_control.Visible)
2268 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
2270 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
2274 private void VerticalScroller (object sender, EventArgs e)
2276 item_control.EndEdit (item_control.edit_item);
2278 // Avoid unnecessary flickering, when button is
2279 // kept pressed at the end
2280 if (v_marker != v_scroll.Value) {
2281 int pixels = v_marker - v_scroll.Value;
2282 Rectangle area = item_control.ClientRectangle;
2283 v_marker = v_scroll.Value;
2284 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
2287 #endregion // Internal Methods Properties
2289 #region Protected Methods
2290 protected override void CreateHandle ()
2292 base.CreateHandle ();
2293 for (int i = 0; i < SelectedItems.Count; i++)
2294 OnSelectedIndexChanged (EventArgs.Empty);
2297 protected override void Dispose (bool disposing)
2300 h_scroll.Dispose ();
2301 v_scroll.Dispose ();
2303 large_image_list = null;
2304 small_image_list = null;
2305 state_image_list = null;
2307 foreach (ColumnHeader col in columns)
2308 col.SetListView (null);
2310 foreach (ListViewItem item in items)
2314 base.Dispose (disposing);
2317 protected override bool IsInputKey (Keys keyData)
2334 return base.IsInputKey (keyData);
2337 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
2339 LabelEditEventHandler eh = (LabelEditEventHandler)(Events [AfterLabelEditEvent]);
2344 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
2346 LabelEditEventHandler eh = (LabelEditEventHandler)(Events [BeforeLabelEditEvent]);
2351 protected virtual void OnColumnClick (ColumnClickEventArgs e)
2353 ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]);
2358 protected override void OnEnabledChanged (EventArgs e)
2360 base.OnEnabledChanged (e);
2363 protected override void OnFontChanged (EventArgs e)
2365 base.OnFontChanged (e);
2369 protected override void OnHandleCreated (EventArgs e)
2371 base.OnHandleCreated (e);
2375 protected override void OnHandleDestroyed (EventArgs e)
2377 base.OnHandleDestroyed (e);
2380 protected virtual void OnItemActivate (EventArgs e)
2382 EventHandler eh = (EventHandler)(Events [ItemActivateEvent]);
2387 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
2389 EventHandler eh = (EventHandler)(Events [ItemCheckEvent]);
2394 protected virtual void OnItemDrag (ItemDragEventArgs e)
2396 EventHandler eh = (EventHandler)(Events [ItemDragEvent]);
2401 protected virtual void OnSelectedIndexChanged (EventArgs e)
2403 EventHandler eh = (EventHandler)(Events [SelectedIndexChangedEvent]);
2408 protected override void OnSystemColorsChanged (EventArgs e)
2410 base.OnSystemColorsChanged (e);
2413 protected void RealizeProperties ()
2418 protected void UpdateExtendedStyles ()
2423 bool refocusing = false;
2425 protected override void WndProc (ref Message m)
2427 switch ((Msg)m.Msg) {
2428 case Msg.WM_KILLFOCUS:
2429 Control receiver = Control.FromHandle (m.WParam);
2430 if (receiver == item_control) {
2436 case Msg.WM_SETFOCUS:
2446 base.WndProc (ref m);
2448 #endregion // Protected Methods
2450 #region Public Instance Methods
2451 public void ArrangeIcons ()
2453 ArrangeIcons (this.alignment);
2456 public void ArrangeIcons (ListViewAlignment alignment)
2458 // Icons are arranged only if view is set to LargeIcon or SmallIcon
2459 if (view == View.LargeIcon || view == View.SmallIcon) {
2460 this.CalculateListView (alignment);
2461 // we have done the calculations already
2462 this.Redraw (false);
2467 public void AutoResizeColumn (int columnIndex, ColumnHeaderAutoResizeStyle headerAutoResize)
2469 if (columnIndex < 0 || columnIndex >= columns.Count)
2470 throw new ArgumentOutOfRangeException ("columnIndex");
2472 columns [columnIndex].AutoResize (headerAutoResize);
2475 public void AutoResizeColumns (ColumnHeaderAutoResizeStyle headerAutoResize)
2478 foreach (ColumnHeader col in columns)
2479 col.AutoResize (headerAutoResize);
2484 public void BeginUpdate ()
2486 // flag to avoid painting
2490 public void Clear ()
2493 items.Clear (); // Redraw (true) called here
2496 public void EndUpdate ()
2498 // flag to avoid painting
2501 // probably, now we need a redraw with recalculations
2505 public void EnsureVisible (int index)
2507 if (index < 0 || index >= items.Count || scrollable == false)
2510 Rectangle view_rect = item_control.ClientRectangle;
2511 Rectangle bounds = new Rectangle (GetItemLocation (index), ItemSize);
2513 if (view_rect.Contains (bounds))
2516 if (View != View.Details) {
2517 if (bounds.Left < 0)
2518 h_scroll.Value += bounds.Left;
2519 else if (bounds.Right > view_rect.Right)
2520 h_scroll.Value += (bounds.Right - view_rect.Right);
2524 v_scroll.Value += bounds.Top;
2525 else if (bounds.Bottom > view_rect.Bottom)
2526 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
2530 public ListViewItem FindItemWithText (string text)
2532 if (items.Count == 0)
2535 return FindItemWithText (text, true, 0, true);
2538 public ListViewItem FindItemWithText (string text, bool includeSubItems, int startIndex)
2540 return FindItemWithText (text, includeSubItems, startIndex, true);
2543 public ListViewItem FindItemWithText (string text, bool includeSubItems, int startIndex, bool prefixSearch)
2545 if (startIndex < 0 || startIndex >= items.Count)
2546 throw new ArgumentOutOfRangeException ("startIndex");
2549 throw new ArgumentNullException ("text");
2551 for (int i = startIndex; i < items.Count; i++) {
2552 ListViewItem lvi = items [i];
2554 if ((prefixSearch && lvi.Text.StartsWith (text, true, CultureInfo.CurrentCulture)) // prefix search
2555 || String.Compare (lvi.Text, text, true) == 0) // match
2559 if (includeSubItems) {
2560 for (int i = startIndex; i < items.Count; i++) {
2561 ListViewItem lvi = items [i];
2562 foreach (ListViewItem.ListViewSubItem sub_item in lvi.SubItems)
2563 if ((prefixSearch && sub_item.Text.StartsWith (text, true, CultureInfo.CurrentCulture))
2564 || String.Compare (sub_item.Text, text, true) == 0)
2573 public ListViewItem GetItemAt (int x, int y)
2575 Size item_size = ItemSize;
2576 for (int i = 0; i < items.Count; i++) {
2577 Point item_location = GetItemLocation (i);
2578 Rectangle item_rect = new Rectangle (item_location, item_size);
2579 if (item_rect.Contains (x, y))
2586 public Rectangle GetItemRect (int index)
2588 return GetItemRect (index, ItemBoundsPortion.Entire);
2591 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
2593 if (index < 0 || index >= items.Count)
2594 throw new IndexOutOfRangeException ("index");
2596 return items [index].GetBounds (portion);
2604 // we need this overload to reuse the logic for sorting, while allowing
2605 // redrawing to be done by caller or have it done by this method when
2606 // sorting is really performed
2608 // ListViewItemCollection's Add and AddRange methods call this overload
2609 // with redraw set to false, as they take care of redrawing themselves
2610 // (they even want to redraw the listview if no sort is performed, as
2611 // an item was added), while ListView.Sort () only wants to redraw if
2612 // sorting was actually performed
2613 private void Sort (bool redraw)
2615 if (!IsHandleCreated || item_sorter == null) {
2619 items.Sort (item_sorter);
2624 public override string ToString ()
2626 int count = this.Items.Count;
2629 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
2631 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
2633 #endregion // Public Instance Methods
2638 class HeaderControl : Control {
2641 bool column_resize_active = false;
2642 ColumnHeader resize_column;
2643 ColumnHeader clicked_column;
2644 ColumnHeader drag_column;
2646 int drag_to_index = -1;
2648 public HeaderControl (ListView owner)
2651 MouseDown += new MouseEventHandler (HeaderMouseDown);
2652 MouseMove += new MouseEventHandler (HeaderMouseMove);
2653 MouseUp += new MouseEventHandler (HeaderMouseUp);
2656 private ColumnHeader ColumnAtX (int x)
2658 Point pt = new Point (x, 0);
2659 ColumnHeader result = null;
2660 foreach (ColumnHeader col in owner.Columns) {
2661 if (col.Rect.Contains (pt)) {
2669 private int GetReorderedIndex (ColumnHeader col)
2671 if (owner.reordered_column_indices == null)
2674 for (int i = 0; i < owner.Columns.Count; i++)
2675 if (owner.reordered_column_indices [i] == col.Index)
2677 throw new Exception ("Column index missing from reordered array");
2680 private void HeaderMouseDown (object sender, MouseEventArgs me)
2682 if (resize_column != null) {
2683 column_resize_active = true;
2688 clicked_column = ColumnAtX (me.X + owner.h_marker);
2690 if (clicked_column != null) {
2692 if (owner.AllowColumnReorder) {
2694 drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
2695 drag_column.Rect = clicked_column.Rect;
2696 drag_to_index = GetReorderedIndex (clicked_column);
2698 clicked_column.Pressed = true;
2699 Rectangle bounds = clicked_column.Rect;
2700 bounds.X -= owner.h_marker;
2701 Invalidate (bounds);
2708 column_resize_active = false;
2709 resize_column = null;
2711 Cursor = Cursors.Default;
2714 private void HeaderMouseMove (object sender, MouseEventArgs me)
2716 Point pt = new Point (me.X + owner.h_marker, me.Y);
2718 if (column_resize_active) {
2719 int width = pt.X - resize_column.X;
2723 if (!owner.CanProceedWithResize (resize_column, width)){
2727 resize_column.Width = width;
2731 resize_column = null;
2733 if (clicked_column != null) {
2734 if (owner.AllowColumnReorder) {
2737 r = drag_column.Rect;
2738 r.X = clicked_column.Rect.X + me.X - drag_x;
2739 drag_column.Rect = r;
2741 int x = me.X + owner.h_marker;
2742 ColumnHeader over = ColumnAtX (x);
2744 drag_to_index = owner.Columns.Count;
2745 else if (x < over.X + over.Width / 2)
2746 drag_to_index = GetReorderedIndex (over);
2748 drag_to_index = GetReorderedIndex (over) + 1;
2751 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
2752 bool pressed = clicked_column.Pressed;
2753 clicked_column.Pressed = over == clicked_column;
2754 if (clicked_column.Pressed ^ pressed) {
2755 Rectangle bounds = clicked_column.Rect;
2756 bounds.X -= owner.h_marker;
2757 Invalidate (bounds);
2763 for (int i = 0; i < owner.Columns.Count; i++) {
2764 Rectangle zone = owner.Columns [i].Rect;
2765 zone.X = zone.Right - 5;
2767 if (zone.Contains (pt)) {
2768 if (i < owner.Columns.Count - 1 && owner.Columns [i + 1].Width == 0)
2770 resize_column = owner.Columns [i];
2775 if (resize_column == null)
2776 Cursor = Cursors.Default;
2778 Cursor = Cursors.VSplit;
2781 void HeaderMouseUp (object sender, MouseEventArgs me)
2785 if (column_resize_active) {
2786 int column_idx = resize_column.Index;
2788 owner.RaiseColumnWidthChanged (column_idx);
2792 if (clicked_column != null && clicked_column.Pressed) {
2793 clicked_column.Pressed = false;
2794 Rectangle bounds = clicked_column.Rect;
2795 bounds.X -= owner.h_marker;
2796 Invalidate (bounds);
2797 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
2800 if (drag_column != null && owner.AllowColumnReorder) {
2802 if (drag_to_index > GetReorderedIndex (clicked_column))
2804 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
2805 owner.ReorderColumn (clicked_column, drag_to_index);
2810 clicked_column = null;
2813 internal override void OnPaintInternal (PaintEventArgs pe)
2818 Theme theme = ThemeEngine.Current;
2819 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
2821 if (drag_column == null)
2825 if (drag_to_index == owner.Columns.Count)
2826 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
2828 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
2829 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
2832 protected override void WndProc (ref Message m)
2834 switch ((Msg)m.Msg) {
2835 case Msg.WM_SETFOCUS:
2839 base.WndProc (ref m);
2845 private class ItemComparer : IComparer {
2846 readonly SortOrder sort_order;
2848 public ItemComparer (SortOrder sortOrder)
2850 sort_order = sortOrder;
2853 public int Compare (object x, object y)
2855 ListViewItem item_x = x as ListViewItem;
2856 ListViewItem item_y = y as ListViewItem;
2857 if (sort_order == SortOrder.Ascending)
2858 return String.Compare (item_x.Text, item_y.Text);
2860 return String.Compare (item_y.Text, item_x.Text);
2864 public class CheckedIndexCollection : IList, ICollection, IEnumerable
2866 private readonly ListView owner;
2868 #region Public Constructor
2869 public CheckedIndexCollection (ListView owner)
2873 #endregion // Public Constructor
2875 #region Public Properties
2878 get { return owner.CheckedItems.Count; }
2881 public bool IsReadOnly {
2882 get { return true; }
2885 public int this [int index] {
2887 int [] indices = GetIndices ();
2888 if (index < 0 || index >= indices.Length)
2889 throw new ArgumentOutOfRangeException ("index");
2890 return indices [index];
2894 bool ICollection.IsSynchronized {
2895 get { return false; }
2898 object ICollection.SyncRoot {
2899 get { return this; }
2902 bool IList.IsFixedSize {
2903 get { return true; }
2906 object IList.this [int index] {
2907 get { return this [index]; }
2908 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2910 #endregion // Public Properties
2912 #region Public Methods
2913 public bool Contains (int checkedIndex)
2915 int [] indices = GetIndices ();
2916 for (int i = 0; i < indices.Length; i++) {
2917 if (indices [i] == checkedIndex)
2923 public IEnumerator GetEnumerator ()
2925 int [] indices = GetIndices ();
2926 return indices.GetEnumerator ();
2929 void ICollection.CopyTo (Array dest, int index)
2931 int [] indices = GetIndices ();
2932 Array.Copy (indices, 0, dest, index, indices.Length);
2935 int IList.Add (object value)
2937 throw new NotSupportedException ("Add operation is not supported.");
2942 throw new NotSupportedException ("Clear operation is not supported.");
2945 bool IList.Contains (object checkedIndex)
2947 if (!(checkedIndex is int))
2949 return Contains ((int) checkedIndex);
2952 int IList.IndexOf (object checkedIndex)
2954 if (!(checkedIndex is int))
2956 return IndexOf ((int) checkedIndex);
2959 void IList.Insert (int index, object value)
2961 throw new NotSupportedException ("Insert operation is not supported.");
2964 void IList.Remove (object value)
2966 throw new NotSupportedException ("Remove operation is not supported.");
2969 void IList.RemoveAt (int index)
2971 throw new NotSupportedException ("RemoveAt operation is not supported.");
2974 public int IndexOf (int checkedIndex)
2976 int [] indices = GetIndices ();
2977 for (int i = 0; i < indices.Length; i++) {
2978 if (indices [i] == checkedIndex)
2983 #endregion // Public Methods
2985 private int [] GetIndices ()
2987 ArrayList checked_items = owner.CheckedItems.List;
2988 int [] indices = new int [checked_items.Count];
2989 for (int i = 0; i < checked_items.Count; i++) {
2990 ListViewItem item = (ListViewItem) checked_items [i];
2991 indices [i] = item.Index;
2995 } // CheckedIndexCollection
2997 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
2999 private readonly ListView owner;
3000 private ArrayList list;
3002 #region Public Constructor
3003 public CheckedListViewItemCollection (ListView owner)
3006 this.owner.Items.Changed += new CollectionChangedHandler (
3007 ItemsCollection_Changed);
3009 #endregion // Public Constructor
3011 #region Public Properties
3015 if (!owner.CheckBoxes)
3021 public bool IsReadOnly {
3022 get { return true; }
3025 public ListViewItem this [int index] {
3027 ArrayList checked_items = List;
3028 if (index < 0 || index >= checked_items.Count)
3029 throw new ArgumentOutOfRangeException ("index");
3030 return (ListViewItem) checked_items [index];
3035 public virtual ListViewItem this [string key] {
3037 int idx = IndexOfKey (key);
3038 return idx == -1 ? null : (ListViewItem) List [idx];
3043 bool ICollection.IsSynchronized {
3044 get { return false; }
3047 object ICollection.SyncRoot {
3048 get { return this; }
3051 bool IList.IsFixedSize {
3052 get { return true; }
3055 object IList.this [int index] {
3056 get { return this [index]; }
3057 set { throw new NotSupportedException ("SetItem operation is not supported."); }
3059 #endregion // Public Properties
3061 #region Public Methods
3062 public bool Contains (ListViewItem item)
3064 if (!owner.CheckBoxes)
3066 return List.Contains (item);
3070 public virtual bool ContainsKey (string key)
3072 return IndexOfKey (key) != -1;
3076 public void CopyTo (Array dest, int index)
3078 if (!owner.CheckBoxes)
3080 List.CopyTo (dest, index);
3083 public IEnumerator GetEnumerator ()
3085 if (!owner.CheckBoxes)
3086 return (new ListViewItem [0]).GetEnumerator ();
3087 return List.GetEnumerator ();
3090 int IList.Add (object value)
3092 throw new NotSupportedException ("Add operation is not supported.");
3097 throw new NotSupportedException ("Clear operation is not supported.");
3100 bool IList.Contains (object item)
3102 if (!(item is ListViewItem))
3104 return Contains ((ListViewItem) item);
3107 int IList.IndexOf (object item)
3109 if (!(item is ListViewItem))
3111 return IndexOf ((ListViewItem) item);
3114 void IList.Insert (int index, object value)
3116 throw new NotSupportedException ("Insert operation is not supported.");
3119 void IList.Remove (object value)
3121 throw new NotSupportedException ("Remove operation is not supported.");
3124 void IList.RemoveAt (int index)
3126 throw new NotSupportedException ("RemoveAt operation is not supported.");
3129 public int IndexOf (ListViewItem item)
3131 if (!owner.CheckBoxes)
3133 return List.IndexOf (item);
3137 public virtual int IndexOfKey (string key)
3139 if (key == null || key.Length == 0)
3142 ArrayList checked_items = List;
3143 for (int i = 0; i < checked_items.Count; i++) {
3144 ListViewItem item = (ListViewItem) checked_items [i];
3145 if (String.Compare (key, item.Name, true) == 0)
3152 #endregion // Public Methods
3154 internal ArrayList List {
3157 list = new ArrayList ();
3158 foreach (ListViewItem item in owner.Items) {
3167 internal void Reset ()
3169 // force re-population of list
3173 private void ItemsCollection_Changed ()
3177 } // CheckedListViewItemCollection
3179 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
3181 internal ArrayList list;
3182 private ListView owner;
3184 #region Public Constructor
3185 public ColumnHeaderCollection (ListView owner)
3187 list = new ArrayList ();
3190 #endregion // Public Constructor
3192 #region Public Properties
3195 get { return list.Count; }
3198 public bool IsReadOnly {
3199 get { return false; }
3202 public virtual ColumnHeader this [int index] {
3204 if (index < 0 || index >= list.Count)
3205 throw new ArgumentOutOfRangeException ("index");
3206 return (ColumnHeader) list [index];
3211 public virtual ColumnHeader this [string key] {
3213 int idx = IndexOfKey (key);
3217 return (ColumnHeader) list [idx];
3222 bool ICollection.IsSynchronized {
3223 get { return true; }
3226 object ICollection.SyncRoot {
3227 get { return this; }
3230 bool IList.IsFixedSize {
3231 get { return list.IsFixedSize; }
3234 object IList.this [int index] {
3235 get { return this [index]; }
3236 set { throw new NotSupportedException ("SetItem operation is not supported."); }
3238 #endregion // Public Properties
3240 #region Public Methods
3241 public virtual int Add (ColumnHeader value)
3244 value.SetListView (this.owner);
3245 idx = list.Add (value);
3246 if (owner.IsHandleCreated) {
3247 owner.Redraw (true);
3252 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
3254 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
3255 this.Add (colHeader);
3260 public virtual ColumnHeader Add (string text)
3262 return Add (String.Empty, text);
3265 public virtual ColumnHeader Add (string text, int iwidth)
3267 return Add (String.Empty, text, iwidth);
3270 public virtual ColumnHeader Add (string key, string text)
3272 ColumnHeader colHeader = new ColumnHeader ();
3273 colHeader.Name = key;
3274 colHeader.Text = text;
3279 public virtual ColumnHeader Add (string key, string text, int iwidth)
3281 return Add (key, text, iwidth, HorizontalAlignment.Left, -1);
3284 public virtual ColumnHeader Add (string key, string text, int iwidth, HorizontalAlignment textAlign, int imageIndex)
3286 ColumnHeader colHeader = new ColumnHeader (key, text, iwidth, textAlign);
3287 colHeader.ImageIndex = imageIndex;
3292 public virtual ColumnHeader Add (string key, string text, int iwidth, HorizontalAlignment textAlign, string imageKey)
3294 ColumnHeader colHeader = new ColumnHeader (key, text, iwidth, textAlign);
3295 colHeader.ImageKey = imageKey;
3301 public virtual void AddRange (ColumnHeader [] values)
3303 foreach (ColumnHeader colHeader in values) {
3304 colHeader.SetListView (this.owner);
3308 owner.Redraw (true);
3311 public virtual void Clear ()
3313 foreach (ColumnHeader col in list)
3314 col.SetListView (null);
3316 owner.Redraw (true);
3319 public bool Contains (ColumnHeader value)
3321 return list.Contains (value);
3325 public virtual bool ContainsKey (string key)
3327 return IndexOfKey (key) != -1;
3331 public IEnumerator GetEnumerator ()
3333 return list.GetEnumerator ();
3336 void ICollection.CopyTo (Array dest, int index)
3338 list.CopyTo (dest, index);
3341 int IList.Add (object value)
3343 if (! (value is ColumnHeader)) {
3344 throw new ArgumentException ("Not of type ColumnHeader", "value");
3347 return this.Add ((ColumnHeader) value);
3350 bool IList.Contains (object value)
3352 if (! (value is ColumnHeader)) {
3353 throw new ArgumentException ("Not of type ColumnHeader", "value");
3356 return this.Contains ((ColumnHeader) value);
3359 int IList.IndexOf (object value)
3361 if (! (value is ColumnHeader)) {
3362 throw new ArgumentException ("Not of type ColumnHeader", "value");
3365 return this.IndexOf ((ColumnHeader) value);
3368 void IList.Insert (int index, object value)
3370 if (! (value is ColumnHeader)) {
3371 throw new ArgumentException ("Not of type ColumnHeader", "value");
3374 this.Insert (index, (ColumnHeader) value);
3377 void IList.Remove (object value)
3379 if (! (value is ColumnHeader)) {
3380 throw new ArgumentException ("Not of type ColumnHeader", "value");
3383 this.Remove ((ColumnHeader) value);
3386 public int IndexOf (ColumnHeader value)
3388 return list.IndexOf (value);
3392 public virtual int IndexOfKey (string key)
3394 if (key == null || key.Length == 0)
3397 for (int i = 0; i < list.Count; i++) {
3398 ColumnHeader col = (ColumnHeader) list [i];
3399 if (String.Compare (key, col.Name, true) == 0)
3407 public void Insert (int index, ColumnHeader value)
3409 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
3410 // but it's really only greater.
3411 if (index < 0 || index > list.Count)
3412 throw new ArgumentOutOfRangeException ("index");
3414 value.SetListView (owner);
3415 list.Insert (index, value);
3416 owner.Redraw (true);
3420 public void Insert (int index, string text)
3422 Insert (index, String.Empty, text);
3425 public void Insert (int index, string text, int width)
3427 Insert (index, String.Empty, text, width);
3430 public void Insert (int index, string key, string text)
3432 ColumnHeader colHeader = new ColumnHeader ();
3433 colHeader.Name = key;
3434 colHeader.Text = text;
3435 Insert (index, colHeader);
3438 public void Insert (int index, string key, string text, int width)
3440 ColumnHeader colHeader = new ColumnHeader (key, text, width, HorizontalAlignment.Left);
3441 Insert (index, colHeader);
3444 public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, int imageIndex)
3446 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
3447 colHeader.ImageIndex = imageIndex;
3448 Insert (index, colHeader);
3451 public void Insert (int index, string key, string text, int width, HorizontalAlignment textAlign, string imageKey)
3453 ColumnHeader colHeader = new ColumnHeader (key, text, width, textAlign);
3454 colHeader.ImageKey = imageKey;
3455 Insert (index, colHeader);
3459 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
3461 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
3462 this.Insert (index, colHeader);
3465 public virtual void Remove (ColumnHeader column)
3467 // TODO: Update Column internal index ?
3468 list.Remove (column);
3469 column.SetListView (null);
3470 owner.Redraw (true);
3474 public virtual void RemoveByKey (string key)
3476 int idx = IndexOfKey (key);
3482 public virtual void RemoveAt (int index)
3484 if (index < 0 || index >= list.Count)
3485 throw new ArgumentOutOfRangeException ("index");
3487 ColumnHeader col = (ColumnHeader) list [index];
3490 #endregion // Public Methods
3493 } // ColumnHeaderCollection
3495 public class ListViewItemCollection : IList, ICollection, IEnumerable
3497 private readonly ArrayList list;
3498 private readonly ListView owner;
3500 #region Public Constructor
3501 public ListViewItemCollection (ListView owner)
3503 list = new ArrayList ();
3506 #endregion // Public Constructor
3508 #region Public Properties
3511 get { return list.Count; }
3514 public bool IsReadOnly {
3515 get { return false; }
3518 public virtual ListViewItem this [int displayIndex] {
3520 if (displayIndex < 0 || displayIndex >= list.Count)
3521 throw new ArgumentOutOfRangeException ("displayIndex");
3522 return (ListViewItem) list [displayIndex];
3526 if (displayIndex < 0 || displayIndex >= list.Count)
3527 throw new ArgumentOutOfRangeException ("displayIndex");
3529 if (list.Contains (value))
3530 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
3532 if (value.ListView != null && value.ListView != owner)
3533 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");
3535 value.Owner = owner;
3536 list [displayIndex] = value;
3539 owner.Redraw (true);
3544 public virtual ListViewItem this [string key] {
3546 int idx = IndexOfKey (key);
3550 return (ListViewItem) list [idx];
3555 bool ICollection.IsSynchronized {
3556 get { return true; }
3559 object ICollection.SyncRoot {
3560 get { return this; }
3563 bool IList.IsFixedSize {
3564 get { return list.IsFixedSize; }
3567 object IList.this [int index] {
3568 get { return this [index]; }
3570 if (value is ListViewItem)
3571 this [index] = (ListViewItem) value;
3573 this [index] = new ListViewItem (value.ToString ());
3577 #endregion // Public Properties
3579 #region Public Methods
3580 public virtual ListViewItem Add (ListViewItem value)
3583 CollectionChanged (true);
3588 public virtual ListViewItem Add (string text)
3590 ListViewItem item = new ListViewItem (text);
3591 return this.Add (item);
3594 public virtual ListViewItem Add (string text, int imageIndex)
3596 ListViewItem item = new ListViewItem (text, imageIndex);
3597 return this.Add (item);
3601 public virtual ListViewItem Add (string text, string imageKey)
3603 ListViewItem item = new ListViewItem (text, imageKey);
3604 return this.Add (item);
3607 public virtual ListViewItem Add (string key, string text, int imageIndex)
3609 ListViewItem item = new ListViewItem (text, imageIndex);
3611 return this.Add (item);
3614 public virtual ListViewItem Add (string key, string text, string imageKey)
3616 ListViewItem item = new ListViewItem (text, imageKey);
3618 return this.Add (item);
3622 public void AddRange (ListViewItem [] values)
3625 throw new ArgumentNullException ("Argument cannot be null!", "values");
3627 foreach (ListViewItem item in values)
3630 CollectionChanged (true);
3634 public void AddRange (ListViewItemCollection items)
3637 throw new ArgumentNullException ("Argument cannot be null!", "items");
3639 ListViewItem[] itemArray = new ListViewItem[items.Count];
3640 items.CopyTo (itemArray,0);
3641 this.AddRange (itemArray);
3645 public virtual void Clear ()
3647 owner.SetFocusedItem (null);
3648 owner.h_scroll.Value = owner.v_scroll.Value = 0;
3649 foreach (ListViewItem item in list) {
3650 owner.item_control.CancelEdit (item);
3654 CollectionChanged (false);
3657 public bool Contains (ListViewItem item)
3659 return list.Contains (item);
3663 public virtual bool ContainsKey (string key)
3665 return IndexOfKey (key) != -1;
3669 public void CopyTo (Array dest, int index)
3671 list.CopyTo (dest, index);
3675 public ListViewItem [] Find (string key, bool searchAllSubitems)
3678 return new ListViewItem [0];
3680 List<ListViewItem> temp_list = new List<ListViewItem> ();
3682 for (int i = 0; i < list.Count; i++) {
3683 ListViewItem lvi = (ListViewItem) list [i];
3684 if (String.Compare (key, lvi.Name, true) == 0)
3685 temp_list.Add (lvi);
3688 ListViewItem [] retval = new ListViewItem [temp_list.Count];
3689 temp_list.CopyTo (retval);
3695 public IEnumerator GetEnumerator ()
3697 return list.GetEnumerator ();
3700 int IList.Add (object item)
3705 if (item is ListViewItem) {
3706 li = (ListViewItem) item;
3707 if (list.Contains (li))
3708 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
3710 if (li.ListView != null && li.ListView != owner)
3711 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");
3714 li = new ListViewItem (item.ToString ());
3717 result = list.Add (li);
3718 CollectionChanged (true);
3723 bool IList.Contains (object item)
3725 return list.Contains (item);
3728 int IList.IndexOf (object item)
3730 return list.IndexOf (item);
3733 void IList.Insert (int index, object item)
3735 if (item is ListViewItem)
3736 this.Insert (index, (ListViewItem) item);
3738 this.Insert (index, item.ToString ());
3741 void IList.Remove (object item)
3743 Remove ((ListViewItem) item);
3746 public int IndexOf (ListViewItem item)
3748 return list.IndexOf (item);
3752 public virtual int IndexOfKey (string key)
3754 if (key == null || key.Length == 0)
3757 for (int i = 0; i < list.Count; i++) {
3758 ListViewItem lvi = (ListViewItem) list [i];
3759 if (String.Compare (key, lvi.Name, true) == 0)
3767 public ListViewItem Insert (int index, ListViewItem item)
3769 if (index < 0 || index > list.Count)
3770 throw new ArgumentOutOfRangeException ("index");
3772 if (list.Contains (item))
3773 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
3775 if (item.ListView != null && item.ListView != owner)
3776 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");
3779 list.Insert (index, item);
3780 CollectionChanged (true);
3784 public ListViewItem Insert (int index, string text)
3786 return this.Insert (index, new ListViewItem (text));
3789 public ListViewItem Insert (int index, string text, int imageIndex)
3791 return this.Insert (index, new ListViewItem (text, imageIndex));
3795 public ListViewItem Insert (int index, string key, string text, int imageIndex)
3797 ListViewItem lvi = new ListViewItem (text, imageIndex);
3799 return Insert (index, lvi);
3803 public virtual void Remove (ListViewItem item)
3805 if (!list.Contains (item))
3808 bool selection_changed = owner.SelectedItems.Contains (item);
3809 owner.item_control.CancelEdit (item);
3812 CollectionChanged (false);
3813 if (selection_changed)
3814 owner.OnSelectedIndexChanged (EventArgs.Empty);
3817 public virtual void RemoveAt (int index)
3819 if (index < 0 || index >= Count)
3820 throw new ArgumentOutOfRangeException ("index");
3821 ListViewItem item = (ListViewItem) list [index];
3826 public virtual void RemoveByKey (string key)
3828 int idx = IndexOfKey (key);
3834 #endregion // Public Methods
3836 void AddItem (ListViewItem value)
3838 if (list.Contains (value))
3839 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
3841 if (value.ListView != null && value.ListView != owner)
3842 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");
3843 value.Owner = owner;
3847 void CollectionChanged (bool sort)
3849 if (owner != null) {
3854 owner.Redraw (true);
3858 internal event CollectionChangedHandler Changed;
3860 internal void Sort (IComparer comparer)
3862 list.Sort (comparer);
3866 internal void OnChange ()
3868 if (Changed != null)
3871 } // ListViewItemCollection
3873 public class SelectedIndexCollection : IList, ICollection, IEnumerable
3875 private readonly ListView owner;
3877 #region Public Constructor
3878 public SelectedIndexCollection (ListView owner)
3882 #endregion // Public Constructor
3884 #region Public Properties
3888 return owner.SelectedItems.Count;
3892 public bool IsReadOnly {
3902 public int this [int index] {
3904 int [] indices = GetIndices ();
3905 if (index < 0 || index >= indices.Length)
3906 throw new ArgumentOutOfRangeException ("index");
3907 return indices [index];
3911 bool ICollection.IsSynchronized {
3912 get { return false; }
3915 object ICollection.SyncRoot {
3916 get { return this; }
3919 bool IList.IsFixedSize {
3929 object IList.this [int index] {
3930 get { return this [index]; }
3931 set { throw new NotSupportedException ("SetItem operation is not supported."); }
3933 #endregion // Public Properties
3935 #region Public Methods
3937 public int Add (int itemIndex)
3939 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
3940 throw new ArgumentOutOfRangeException ("index");
3942 owner.Items [itemIndex].Selected = true;
3943 if (!owner.IsHandleCreated)
3946 return owner.SelectedItems.Count;
3949 public void Clear ()
3951 owner.SelectedItems.Clear ();
3954 public bool Contains (int selectedIndex)
3956 int [] indices = GetIndices ();
3957 for (int i = 0; i < indices.Length; i++) {
3958 if (indices [i] == selectedIndex)
3964 public void CopyTo (Array dest, int index)
3966 int [] indices = GetIndices ();
3967 Array.Copy (indices, 0, dest, index, indices.Length);
3970 public IEnumerator GetEnumerator ()
3972 int [] indices = GetIndices ();
3973 return indices.GetEnumerator ();
3976 int IList.Add (object value)
3978 throw new NotSupportedException ("Add operation is not supported.");
3983 throw new NotSupportedException ("Clear operation is not supported.");
3986 bool IList.Contains (object selectedIndex)
3988 if (!(selectedIndex is int))
3990 return Contains ((int) selectedIndex);
3993 int IList.IndexOf (object selectedIndex)
3995 if (!(selectedIndex is int))
3997 return IndexOf ((int) selectedIndex);
4000 void IList.Insert (int index, object value)
4002 throw new NotSupportedException ("Insert operation is not supported.");
4005 void IList.Remove (object value)
4007 throw new NotSupportedException ("Remove operation is not supported.");
4010 void IList.RemoveAt (int index)
4012 throw new NotSupportedException ("RemoveAt operation is not supported.");
4015 public int IndexOf (int selectedIndex)
4017 int [] indices = GetIndices ();
4018 for (int i = 0; i < indices.Length; i++) {
4019 if (indices [i] == selectedIndex)
4026 public void Remove (int itemIndex)
4028 if (itemIndex < 0 || itemIndex >= owner.Items.Count)
4029 throw new ArgumentOutOfRangeException ("itemIndex");
4031 owner.Items [itemIndex].Selected = false;
4034 #endregion // Public Methods
4036 private int [] GetIndices ()
4038 ArrayList selected_items = owner.SelectedItems.List;
4039 int [] indices = new int [selected_items.Count];
4040 for (int i = 0; i < selected_items.Count; i++) {
4041 ListViewItem item = (ListViewItem) selected_items [i];
4042 indices [i] = item.Index;
4046 } // SelectedIndexCollection
4048 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
4050 private readonly ListView owner;
4051 private ArrayList list;
4053 #region Public Constructor
4054 public SelectedListViewItemCollection (ListView owner)
4057 this.owner.Items.Changed += new CollectionChangedHandler (
4058 ItemsCollection_Changed);
4060 #endregion // Public Constructor
4062 #region Public Properties
4066 if (!owner.IsHandleCreated)
4072 public bool IsReadOnly {
4073 get { return true; }
4076 public ListViewItem this [int index] {
4078 ArrayList selected_items = List;
4079 if (!owner.IsHandleCreated || index < 0 || index >= selected_items.Count)
4080 throw new ArgumentOutOfRangeException ("index");
4081 return (ListViewItem) selected_items [index];
4086 public virtual ListViewItem this [string key] {
4088 int idx = IndexOfKey (key);
4092 return (ListViewItem) List [idx];
4097 bool ICollection.IsSynchronized {
4098 get { return false; }
4101 object ICollection.SyncRoot {
4102 get { return this; }
4105 bool IList.IsFixedSize {
4106 get { return true; }
4109 object IList.this [int index] {
4110 get { return this [index]; }
4111 set { throw new NotSupportedException ("SetItem operation is not supported."); }
4113 #endregion // Public Properties
4115 #region Public Methods
4116 public void Clear ()
4118 if (!owner.IsHandleCreated)
4121 foreach (ListViewItem item in List)
4122 item.Selected = false;
4125 public bool Contains (ListViewItem item)
4127 if (!owner.IsHandleCreated)
4129 return List.Contains (item);
4133 public virtual bool ContainsKey (string key)
4135 return IndexOfKey (key) != -1;
4139 public void CopyTo (Array dest, int index)
4141 if (!owner.IsHandleCreated)
4143 List.CopyTo (dest, index);
4146 public IEnumerator GetEnumerator ()
4148 if (!owner.IsHandleCreated)
4149 return (new ListViewItem [0]).GetEnumerator ();
4150 return List.GetEnumerator ();
4153 int IList.Add (object value)
4155 throw new NotSupportedException ("Add operation is not supported.");
4158 bool IList.Contains (object item)
4160 if (!(item is ListViewItem))
4162 return Contains ((ListViewItem) item);
4165 int IList.IndexOf (object item)
4167 if (!(item is ListViewItem))
4169 return IndexOf ((ListViewItem) item);
4172 void IList.Insert (int index, object value)
4174 throw new NotSupportedException ("Insert operation is not supported.");
4177 void IList.Remove (object value)
4179 throw new NotSupportedException ("Remove operation is not supported.");
4182 void IList.RemoveAt (int index)
4184 throw new NotSupportedException ("RemoveAt operation is not supported.");
4187 public int IndexOf (ListViewItem item)
4189 if (!owner.IsHandleCreated)
4191 return List.IndexOf (item);
4195 public virtual int IndexOfKey (string key)
4197 if (!owner.IsHandleCreated || key == null || key.Length == 0)
4200 ArrayList selected_items = List;
4201 for (int i = 0; i < selected_items.Count; i++) {
4202 ListViewItem item = (ListViewItem) selected_items [i];
4203 if (String.Compare (item.Name, key, true) == 0)
4210 #endregion // Public Methods
4212 internal ArrayList List {
4215 list = new ArrayList ();
4216 foreach (ListViewItem item in owner.Items) {
4225 internal void Reset ()
4227 // force re-population of list
4231 private void ItemsCollection_Changed ()
4235 } // SelectedListViewItemCollection
4237 internal delegate void CollectionChangedHandler ();
4239 struct ItemMatrixLocation
4244 public ItemMatrixLocation (int row, int col)
4271 #endregion // Subclasses
4273 protected override void OnResize (EventArgs e)
4278 protected override void OnMouseLeave (EventArgs e)
4280 base.OnMouseLeave (e);
4284 // ColumnReorder event
4286 static object ColumnReorderedEvent = new object ();
4287 public event ColumnReorderedEventHandler ColumnReordered {
4288 add { Events.AddHandler (ColumnReorderedEvent, value); }
4289 remove { Events.RemoveHandler (ColumnReorderedEvent, value); }
4292 protected virtual void OnColumnReordered (ColumnReorderedEventArgs e)
4294 ColumnReorderedEventHandler creh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
4301 // ColumnWidthChanged
4303 static object ColumnWidthChangedEvent = new object ();
4304 public event ColumnWidthChangedEventHandler ColumnWidthChanged {
4305 add { Events.AddHandler (ColumnWidthChangedEvent, value); }
4306 remove { Events.RemoveHandler (ColumnWidthChangedEvent, value); }
4309 protected virtual void OnColumnWidthChanged (ColumnWidthChangedEventArgs e)
4311 ColumnWidthChangedEventHandler eh = (ColumnWidthChangedEventHandler) (Events[ColumnWidthChangedEvent]);
4316 void RaiseColumnWidthChanged (int resize_column)
4318 ColumnWidthChangedEventArgs n = new ColumnWidthChangedEventArgs (resize_column);
4320 OnColumnWidthChanged (n);
4324 // ColumnWidthChanging
4326 static object ColumnWidthChangingEvent = new object ();
4327 public event ColumnWidthChangingEventHandler ColumnWidthChanging {
4328 add { Events.AddHandler (ColumnWidthChangingEvent, value); }
4329 remove { Events.RemoveHandler (ColumnWidthChangingEvent, value); }
4332 protected virtual void OnColumnWidthChanging (ColumnWidthChangingEventArgs e)
4334 ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
4340 // 2.0 profile based implementation
4342 bool CanProceedWithResize (ColumnHeader col, int width)
4344 ColumnWidthChangingEventHandler cwceh = (ColumnWidthChangingEventHandler) (Events[ColumnWidthChangingEvent]);
4348 ColumnWidthChangingEventArgs changing = new ColumnWidthChangingEventArgs (col.Index, width);
4349 cwceh (this, changing);
4350 return !changing.Cancel;
4354 // 1.0 profile based implementation
4356 bool CanProceedWithResize (ColumnHeader col, int width)
4361 void RaiseColumnWidthChanged (int resize_column)