1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc. (http://www.novell.com)
23 // Ravindra Kumar (rkumar@novell.com)
24 // Jordi Mas i Hernandez, jordi@ximian.com
25 // Mike Kestner (mkestner@novell.com)
28 // - Feedback for item activation, change in cursor types as mouse moves.
37 using System.Collections;
38 using System.ComponentModel;
39 using System.ComponentModel.Design;
41 using System.Runtime.InteropServices;
42 using System.Globalization;
44 namespace System.Windows.Forms
46 [DefaultEvent ("SelectedIndexChanged")]
47 [DefaultProperty ("Items")]
48 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
49 public class ListView : Control
51 private ItemActivation activation = ItemActivation.Standard;
52 private ListViewAlignment alignment = ListViewAlignment.Top;
53 private bool allow_column_reorder = false;
54 private bool auto_arrange = true;
55 private bool check_boxes = false;
56 private CheckedIndexCollection checked_indices;
57 private CheckedListViewItemCollection checked_items;
58 private ColumnHeaderCollection columns;
59 internal ListViewItem focused_item;
60 private bool full_row_select = false;
61 private bool grid_lines = false;
62 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
63 private bool hide_selection = true;
64 private bool hover_selection = false;
65 private IComparer item_sorter;
66 private ListViewItemCollection items;
67 private bool label_edit = false;
68 private bool label_wrap = true;
69 private bool multiselect = true;
70 private bool scrollable = true;
71 private SelectedIndexCollection selected_indices;
72 private SelectedListViewItemCollection selected_items;
73 private SortOrder sort_order = SortOrder.None;
74 private ImageList state_image_list;
75 private bool updating = false;
76 private View view = View.LargeIcon;
77 private int layout_wd; // We might draw more than our client area
78 private int layout_ht; // therefore we need to have these two.
79 //private TextBox editor; // Used for editing an item text
80 HeaderControl header_control;
81 internal ItemControl item_control;
82 internal ScrollBar h_scroll; // used for scrolling horizontally
83 internal ScrollBar v_scroll; // used for scrolling vertically
84 internal int h_marker; // Position markers for scrolling
85 internal int v_marker;
86 private int keysearch_tickcnt;
87 private string keysearch_text;
88 static private readonly int keysearch_keydelay = 1000;
89 private int[] reordered_column_indices;
92 internal ImageList large_image_list;
93 internal ImageList small_image_list;
94 internal Size text_size = Size.Empty;
97 public event LabelEditEventHandler AfterLabelEdit;
100 [EditorBrowsable (EditorBrowsableState.Never)]
101 public new event EventHandler BackgroundImageChanged {
102 add { base.BackgroundImageChanged += value; }
103 remove { base.BackgroundImageChanged -= value; }
106 public event LabelEditEventHandler BeforeLabelEdit;
107 public event ColumnClickEventHandler ColumnClick;
108 public event EventHandler ItemActivate;
109 public event ItemCheckEventHandler ItemCheck;
110 public event ItemDragEventHandler ItemDrag;
113 [EditorBrowsable (EditorBrowsableState.Never)]
114 public new event PaintEventHandler Paint {
115 add { base.Paint += value; }
116 remove { base.Paint -= value; }
119 public event EventHandler SelectedIndexChanged;
122 [EditorBrowsable (EditorBrowsableState.Never)]
123 public new event EventHandler TextChanged {
124 add { base.TextChanged += value; }
125 remove { base.TextChanged -= value; }
130 #region Public Constructors
133 background_color = ThemeEngine.Current.ColorWindow;
134 checked_indices = new CheckedIndexCollection (this);
135 checked_items = new CheckedListViewItemCollection (this);
136 columns = new ColumnHeaderCollection (this);
137 foreground_color = SystemColors.WindowText;
138 items = new ListViewItemCollection (this);
139 selected_indices = new SelectedIndexCollection (this);
140 selected_items = new SelectedListViewItemCollection (this);
142 border_style = BorderStyle.Fixed3D;
144 header_control = new HeaderControl (this);
145 header_control.Visible = false;
146 item_control = new ItemControl (this);
147 item_control.Visible = true;
149 h_scroll = new HScrollBar ();
150 v_scroll = new VScrollBar ();
151 h_marker = v_marker = 0;
152 keysearch_tickcnt = 0;
154 // scroll bars are disabled initially
155 h_scroll.Visible = false;
156 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
157 v_scroll.Visible = false;
158 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
161 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
162 SizeChanged += new EventHandler (ListView_SizeChanged);
164 this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
166 #endregion // Public Constructors
168 #region Private Internal Properties
169 internal Size CheckBoxSize {
171 if (this.check_boxes) {
172 if (this.state_image_list != null)
173 return this.state_image_list.ImageSize;
175 return ThemeEngine.Current.ListViewCheckBoxSize;
183 bool CanMultiselect {
187 else if (multiselect && (XplatUI.State.ModifierKeys & (Keys.Control | Keys.Shift)) != 0)
194 #endregion // Private Internal Properties
196 #region Protected Properties
197 protected override CreateParams CreateParams {
198 get { return base.CreateParams; }
201 protected override Size DefaultSize {
202 get { return ThemeEngine.Current.ListViewDefaultSize; }
204 #endregion // Protected Properties
206 #region Public Instance Properties
207 [DefaultValue (ItemActivation.Standard)]
208 public ItemActivation Activation {
209 get { return activation; }
211 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
212 value != ItemActivation.TwoClick) {
213 throw new InvalidEnumArgumentException (string.Format
214 ("Enum argument value '{0}' is not valid for Activation", value));
221 [DefaultValue (ListViewAlignment.Top)]
223 public ListViewAlignment Alignment {
224 get { return alignment; }
226 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
227 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
228 throw new InvalidEnumArgumentException (string.Format
229 ("Enum argument value '{0}' is not valid for Alignment", value));
232 if (this.alignment != value) {
234 // alignment does not matter in Details/List views
235 if (this.view == View.LargeIcon ||
236 this.View == View.SmallIcon)
242 [DefaultValue (false)]
243 public bool AllowColumnReorder {
244 get { return allow_column_reorder; }
245 set { allow_column_reorder = value; }
248 [DefaultValue (true)]
249 public bool AutoArrange {
250 get { return auto_arrange; }
252 if (auto_arrange != value) {
253 auto_arrange = value;
254 // autoarrange does not matter in Details/List views
255 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
261 public override Color BackColor {
263 if (background_color.IsEmpty)
264 return ThemeEngine.Current.ColorWindow;
266 return background_color;
268 set { background_color = value; }
272 [EditorBrowsable (EditorBrowsableState.Never)]
273 public override Image BackgroundImage {
274 get { return background_image; }
276 if (value == background_image)
279 background_image = value;
280 OnBackgroundImageChanged (EventArgs.Empty);
284 [DefaultValue (BorderStyle.Fixed3D)]
286 public BorderStyle BorderStyle {
287 get { return InternalBorderStyle; }
288 set { InternalBorderStyle = value; }
291 [DefaultValue (false)]
292 public bool CheckBoxes {
293 get { return check_boxes; }
295 if (check_boxes != value) {
303 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
304 public CheckedIndexCollection CheckedIndices {
305 get { return checked_indices; }
309 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
310 public CheckedListViewItemCollection CheckedItems {
311 get { return checked_items; }
314 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
316 [MergableProperty (false)]
317 public ColumnHeaderCollection Columns {
318 get { return columns; }
322 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
323 public ListViewItem FocusedItem {
325 if (focused_item == null && Focused && items.Count > 0)
326 focused_item = items [0];
331 public override Color ForeColor {
333 if (foreground_color.IsEmpty)
334 return ThemeEngine.Current.ColorWindowText;
336 return foreground_color;
338 set { foreground_color = value; }
341 [DefaultValue (false)]
342 public bool FullRowSelect {
343 get { return full_row_select; }
344 set { full_row_select = value; }
347 [DefaultValue (false)]
348 public bool GridLines {
349 get { return grid_lines; }
351 if (grid_lines != value) {
358 [DefaultValue (ColumnHeaderStyle.Clickable)]
359 public ColumnHeaderStyle HeaderStyle {
360 get { return header_style; }
362 if (header_style == value)
366 case ColumnHeaderStyle.Clickable:
367 case ColumnHeaderStyle.Nonclickable:
368 case ColumnHeaderStyle.None:
371 throw new InvalidEnumArgumentException (string.Format
372 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
375 header_style = value;
376 if (view == View.Details)
381 [DefaultValue (true)]
382 public bool HideSelection {
383 get { return hide_selection; }
385 if (hide_selection != value) {
386 hide_selection = value;
392 [DefaultValue (false)]
393 public bool HoverSelection {
394 get { return hover_selection; }
395 set { hover_selection = value; }
398 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
400 [MergableProperty (false)]
401 public ListViewItemCollection Items {
402 get { return items; }
405 [DefaultValue (false)]
406 public bool LabelEdit {
407 get { return label_edit; }
408 set { label_edit = value; }
411 [DefaultValue (true)]
413 public bool LabelWrap {
414 get { return label_wrap; }
416 if (label_wrap != value) {
423 [DefaultValue (null)]
424 public ImageList LargeImageList {
425 get { return large_image_list; }
427 large_image_list = value;
433 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
434 public IComparer ListViewItemSorter {
435 get { return item_sorter; }
436 set { item_sorter = value; }
439 [DefaultValue (true)]
440 public bool MultiSelect {
441 get { return multiselect; }
442 set { multiselect = value; }
445 [DefaultValue (true)]
446 public bool Scrollable {
447 get { return scrollable; }
449 if (scrollable != value) {
457 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
458 public SelectedIndexCollection SelectedIndices {
459 get { return selected_indices; }
463 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
464 public SelectedListViewItemCollection SelectedItems {
465 get { return selected_items; }
468 [DefaultValue (null)]
469 public ImageList SmallImageList {
470 get { return small_image_list; }
472 small_image_list = value;
477 [DefaultValue (SortOrder.None)]
478 public SortOrder Sorting {
479 get { return sort_order; }
481 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
482 value != SortOrder.None) {
483 throw new InvalidEnumArgumentException (string.Format
484 ("Enum argument value '{0}' is not valid for Sorting", value));
487 if (sort_order != value) {
494 [DefaultValue (null)]
495 public ImageList StateImageList {
496 get { return state_image_list; }
498 state_image_list = value;
505 [EditorBrowsable (EditorBrowsableState.Never)]
506 public override string Text {
515 OnTextChanged (EventArgs.Empty);
520 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
521 public ListViewItem TopItem {
524 if (this.items.Count == 0)
526 // if contents are not scrolled
527 // it is the first item
528 else if (h_marker == 0 && v_marker == 0)
529 return this.items [0];
530 // do a hit test for the scrolled position
532 foreach (ListViewItem item in this.items) {
533 if (item.Bounds.X >= 0 && item.Bounds.Y >= 0)
541 [DefaultValue (View.LargeIcon)]
545 if (value != View.Details && value != View.LargeIcon &&
546 value != View.List && value != View.SmallIcon ) {
547 throw new InvalidEnumArgumentException (string.Format
548 ("Enum argument value '{0}' is not valid for View", value));
552 h_scroll.Value = v_scroll.Value = 0;
558 #endregion // Public Instance Properties
560 #region Internal Methods Properties
562 internal int FirstVisibleIndex {
565 if (this.items.Count == 0)
568 if (h_marker == 0 && v_marker == 0)
571 foreach (ListViewItem item in this.items) {
572 if (item.Bounds.Right >= 0 && item.Bounds.Bottom >= 0)
581 internal int LastVisibleIndex {
583 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
584 if (Items[i].Bounds.Y > ClientRectangle.Bottom)
588 return Items.Count - 1;
592 internal int TotalWidth {
593 get { return Math.Max (this.Width, this.layout_wd); }
596 internal int TotalHeight {
597 get { return Math.Max (this.Height, this.layout_ht); }
600 internal void Redraw (bool recalculate)
602 // Avoid calculations when control is being updated
607 CalculateListView (this.alignment);
612 internal Size GetChildColumnSize (int index)
614 Size ret_size = Size.Empty;
615 ColumnHeader col = this.columns [index];
617 if (col.Width == -2) { // autosize = max(items, columnheader)
618 Size size = Size.Ceiling (this.DeviceContext.MeasureString
619 (col.Text, this.Font));
620 ret_size = BiggestItem (index);
621 if (size.Width > ret_size.Width)
624 else { // -1 and all the values < -2 are put under one category
625 ret_size = BiggestItem (index);
626 // fall back to empty columns' width if no subitem is available for a column
627 if (ret_size.IsEmpty) {
628 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
629 if (col.Text.Length > 0)
630 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
631 (col.Text, this.Font)).Height;
633 ret_size.Height = this.Font.Height;
637 // adjust the size for icon and checkbox for 0th column
639 ret_size.Width += (this.CheckBoxSize.Width + 4);
640 if (this.small_image_list != null)
641 ret_size.Width += this.small_image_list.ImageSize.Width;
646 // Returns the size of biggest item text in a column.
647 private Size BiggestItem (int col)
649 Size temp = Size.Empty;
650 Size ret_size = Size.Empty;
652 // 0th column holds the item text, we check the size of
653 // the various subitems falling in that column and get
654 // the biggest one's size.
655 foreach (ListViewItem item in items) {
656 if (col >= item.SubItems.Count)
659 temp = Size.Ceiling (this.DeviceContext.MeasureString
660 (item.SubItems [col].Text, this.Font));
661 if (temp.Width > ret_size.Width)
665 // adjustment for space
666 if (!ret_size.IsEmpty)
672 // Sets the size of the biggest item text as per the view
673 private void CalcTextSize ()
675 // clear the old value
676 text_size = Size.Empty;
678 if (items.Count == 0)
681 text_size = BiggestItem (0);
683 if (view == View.LargeIcon && this.label_wrap) {
684 Size temp = Size.Empty;
685 if (this.check_boxes)
686 temp.Width += 2 * this.CheckBoxSize.Width;
687 if (large_image_list != null)
688 temp.Width += large_image_list.ImageSize.Width;
691 // wrapping is done for two lines only
692 if (text_size.Width > temp.Width) {
693 text_size.Width = temp.Width;
694 text_size.Height *= 2;
697 else if (view == View.List) {
698 // in list view max text shown in determined by the
699 // control width, even if scolling is enabled.
700 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
701 if (this.small_image_list != null)
702 max_wd -= this.small_image_list.ImageSize.Width;
704 if (text_size.Width > max_wd)
705 text_size.Width = max_wd;
708 // we do the default settings, if we have got 0's
709 if (text_size.Height <= 0)
710 text_size.Height = this.Font.Height;
711 if (text_size.Width <= 0)
712 text_size.Width = this.Width;
715 text_size.Width += 4;
716 text_size.Height += 2;
719 private void Scroll (ScrollBar scrollbar, int delta)
721 if (delta == 0 || !scrollbar.Visible)
725 if (scrollbar == h_scroll)
726 max = h_scroll.Maximum - item_control.Width;
728 max = v_scroll.Maximum - item_control.Height;
730 int val = scrollbar.Value + delta;
733 else if (val < scrollbar.Minimum)
734 val = scrollbar.Minimum;
735 scrollbar.Value = val;
738 private void CalculateScrollBars ()
740 Rectangle client_area = ClientRectangle;
742 if (!this.scrollable || this.items.Count <= 0) {
743 h_scroll.Visible = false;
744 v_scroll.Visible = false;
748 // making a scroll bar visible might make
749 // other scroll bar visible
750 if (layout_wd > client_area.Right) {
751 h_scroll.Visible = true;
752 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
753 v_scroll.Visible = true;
755 v_scroll.Visible = false;
756 } else if (layout_ht > client_area.Bottom) {
757 v_scroll.Visible = true;
758 if ((layout_wd + v_scroll.Width) > client_area.Right)
759 h_scroll.Visible = true;
761 h_scroll.Visible = false;
763 h_scroll.Visible = false;
764 v_scroll.Visible = false;
767 item_control.Height = ClientRectangle.Height - header_control.Height;
769 if (h_scroll.Visible) {
770 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
771 h_scroll.Minimum = 0;
773 // if v_scroll is visible, adjust the maximum of the
774 // h_scroll to account for the width of v_scroll
775 if (v_scroll.Visible) {
776 h_scroll.Maximum = layout_wd + v_scroll.Width;
777 h_scroll.Width = client_area.Width - v_scroll.Width;
780 h_scroll.Maximum = layout_wd;
781 h_scroll.Width = client_area.Width;
784 h_scroll.LargeChange = client_area.Width;
785 h_scroll.SmallChange = Font.Height;
786 item_control.Height -= h_scroll.Height;
789 if (header_control.Visible)
790 header_control.Width = ClientRectangle.Width;
791 item_control.Width = ClientRectangle.Width;
793 if (v_scroll.Visible) {
794 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
795 v_scroll.Minimum = 0;
797 // if h_scroll is visible, adjust the maximum of the
798 // v_scroll to account for the height of h_scroll
799 if (h_scroll.Visible) {
800 v_scroll.Maximum = layout_ht + h_scroll.Height;
801 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
803 v_scroll.Maximum = layout_ht;
804 v_scroll.Height = client_area.Height;
807 v_scroll.LargeChange = client_area.Height;
808 v_scroll.SmallChange = Font.Height;
809 if (header_control.Visible)
810 header_control.Width -= v_scroll.Width;
811 item_control.Width -= v_scroll.Width;
815 ColumnHeader GetReorderedColumn (int index)
817 if (reordered_column_indices == null)
818 return Columns [index];
820 return Columns [reordered_column_indices [index]];
823 void ReorderColumn (ColumnHeader col, int index)
825 if (reordered_column_indices == null) {
826 reordered_column_indices = new int [Columns.Count];
827 for (int i = 0; i < Columns.Count; i++)
828 reordered_column_indices [i] = i;
831 if (reordered_column_indices [index] == col.Index)
834 int[] curr = reordered_column_indices;
835 int[] result = new int [Columns.Count];
837 for (int i = 0; i < Columns.Count; i++) {
838 if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
842 result [i] = col.Index;
844 result [i] = curr [curr_idx++];
847 reordered_column_indices = result;
849 header_control.Invalidate ();
850 item_control.Invalidate ();
853 Size LargeIconItemSize {
855 int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
856 int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
857 int w = CheckBoxSize.Width + 2 + Math.Max (text_size.Width, image_w);
858 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
859 return new Size (w, h);
863 Size SmallIconItemSize {
865 int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
866 int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
867 int w = text_size.Width + 2 + CheckBoxSize.Width + image_w;
868 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
869 return new Size (w, h);
875 ListViewItem[,] item_matrix;
877 void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
879 header_control.Visible = false;
880 header_control.Size = Size.Empty;
881 item_control.Location = Point.Empty;
883 if (items.Count == 0)
886 Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
888 Rectangle area = ClientRectangle;
891 rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(sz.Height + y_spacing));
894 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
896 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(sz.Width + x_spacing));
899 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
902 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
903 layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
904 item_matrix = new ListViewItem [rows, cols];
907 foreach (ListViewItem item in items) {
908 int x = col * (sz.Width + x_spacing);
909 int y = row * (sz.Height + y_spacing);
910 item.Location = new Point (x, y);
914 item_matrix [row, col] = item;
928 item_control.Size = new Size (layout_wd, layout_ht);
933 if (columns.Count == 0 || header_style == ColumnHeaderStyle.None) {
934 header_control.Visible = false;
935 header_control.Size = Size.Empty;
940 for (int i = 0; i < Columns.Count; i++) {
941 ColumnHeader col = GetReorderedColumn (i);
944 col.CalcColumnHeader ();
948 header_control.Width = x;
949 header_control.Height = columns [0].Ht;
950 header_control.Visible = true;
953 void LayoutDetails ()
957 item_control.Location = new Point (0, header_control.Height);
960 if (items.Count > 0) {
961 foreach (ListViewItem item in items) {
963 item.Location = new Point (0, y);
964 y += item.Bounds.Height + 2;
967 // some space for bottom gridline
972 layout_wd = Math.Max (header_control.Width, item_control.Width);
973 layout_ht = y + header_control.Height;
976 private void CalculateListView (ListViewAlignment align)
986 LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
990 LayoutIcons (true, alignment == ListViewAlignment.Left,
991 ThemeEngine.Current.ListViewHorizontalSpacing,
992 ThemeEngine.Current.ListViewVerticalSpacing);
996 LayoutIcons (false, true, 4, 2);
1000 CalculateScrollBars ();
1003 internal void UpdateSelection (ListViewItem item)
1005 if (item.Selected) {
1007 if (!CanMultiselect && SelectedItems.Count > 0) {
1008 SelectedItems.Clear ();
1009 SelectedIndices.list.Clear ();
1012 if (!SelectedItems.Contains (item)) {
1013 SelectedItems.list.Add (item);
1014 SelectedIndices.list.Add (item.Index);
1017 SelectedItems.list.Remove (item);
1018 SelectedIndices.list.Remove (item.Index);
1022 private bool KeySearchString (KeyEventArgs ke)
1024 int current_tickcnt = Environment.TickCount;
1025 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
1026 keysearch_text = string.Empty;
1029 keysearch_text += (char) ke.KeyData;
1030 keysearch_tickcnt = current_tickcnt;
1032 int start = FocusedItem == null ? 0 : FocusedItem.Index;
1035 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1036 CompareOptions.IgnoreCase)) {
1037 SetFocusedItem (Items [i]);
1038 items [i].Selected = true;
1042 i = (i + 1 < Items.Count) ? i+1 : 0;
1050 int GetAdjustedIndex (Keys key)
1054 if (View == View.Details) {
1056 result = FocusedItem.Index - 1;
1057 else if (key == Keys.Down) {
1058 result = FocusedItem.Index + 1;
1059 if (result == items.Count)
1065 int row = FocusedItem.row;
1066 int col = FocusedItem.col;
1072 return item_matrix [row, col - 1].Index;
1075 if (col == (cols - 1))
1077 while (item_matrix [row, col + 1] == null)
1079 return item_matrix [row, col + 1].Index;
1084 return item_matrix [row - 1, col].Index;
1087 if (row == (rows - 1))
1089 while (item_matrix [row + 1, col] == null)
1091 return item_matrix [row + 1, col].Index;
1098 ListViewItem selection_start;
1100 private void SelectItems (ArrayList sel_items)
1102 multiselecting = true;
1103 ArrayList curr_items = (ArrayList) SelectedItems.list.Clone ();
1104 foreach (ListViewItem item in curr_items)
1105 if (!sel_items.Contains (item))
1106 item.Selected = false;
1107 foreach (ListViewItem item in sel_items)
1108 item.Selected = true;
1109 multiselecting = false;
1112 private void UpdateMultiSelection (int index)
1114 bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
1115 bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
1116 ListViewItem item = items [index];
1118 if (shift_pressed && selection_start != null) {
1119 ArrayList list = new ArrayList ();
1120 int start = Math.Min (selection_start.Index, index);
1121 int end = Math.Max (selection_start.Index, index);
1122 if (View == View.Details) {
1123 for (int i = start; i <= end; i++)
1124 list.Add (items [i]);
1126 int left = Math.Min (items [start].col, items [end].col);
1127 int right = Math.Max (items [start].col, items [end].col);
1128 int top = Math.Min (items [start].row, items [end].row);
1129 int bottom = Math.Max (items [start].row, items [end].row);
1130 foreach (ListViewItem curr in items)
1131 if (curr.row >= top && curr.row <= bottom &&
1132 curr.col >= left && curr.col <= right)
1136 } else if (!ctrl_pressed) {
1137 SelectedItems.Clear ();
1138 SelectedIndices.list.Clear ();
1139 item.Selected = true;
1140 selection_start = item;
1144 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1146 if (ke.Handled || Items.Count == 0)
1152 switch (ke.KeyCode) {
1155 index = Items.Count - 1;
1166 index = GetAdjustedIndex (ke.KeyCode);
1170 ke.Handled = KeySearchString (ke);
1178 UpdateMultiSelection (index);
1180 items [index].Selected = true;
1182 SetFocusedItem (items [index]);
1183 EnsureVisible (index);
1187 internal class ItemControl : Control {
1190 ListViewItem clicked_item;
1191 ListViewItem last_clicked_item;
1192 bool hover_processed = false;
1194 public ItemControl (ListView owner)
1197 DoubleClick += new EventHandler(ItemsDoubleClick);
1198 KeyDown += new KeyEventHandler (ItemsKeyDown);
1199 KeyUp += new KeyEventHandler (ItemsKeyUp);
1200 MouseDown += new MouseEventHandler(ItemsMouseDown);
1201 MouseMove += new MouseEventHandler(ItemsMouseMove);
1202 MouseHover += new EventHandler(ItemsMouseHover);
1203 MouseUp += new MouseEventHandler(ItemsMouseUp);
1204 MouseWheel += new MouseEventHandler(ItemsMouseWheel);
1207 void ItemsDoubleClick (object sender, EventArgs e)
1209 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1210 owner.ItemActivate (this, e);
1213 void ItemsKeyDown (object sender, KeyEventArgs args)
1215 owner.OnKeyDown (args);
1218 void ItemsKeyUp (object sender, KeyEventArgs args)
1220 owner.OnKeyUp (args);
1230 BoxSelect box_select_mode = BoxSelect.None;
1231 ArrayList prev_selection;
1232 Point box_select_start;
1234 Rectangle box_select_rect;
1235 internal Rectangle BoxSelectRectangle {
1236 get { return box_select_rect; }
1238 if (box_select_rect == value)
1241 InvalidateBoxSelectRect ();
1242 box_select_rect = value;
1243 InvalidateBoxSelectRect ();
1247 void InvalidateBoxSelectRect ()
1249 if (BoxSelectRectangle.Size.IsEmpty)
1252 Rectangle edge = BoxSelectRectangle;
1258 edge.Y = BoxSelectRectangle.Bottom - 1;
1260 edge.Y = BoxSelectRectangle.Y - 1;
1262 edge.Height = BoxSelectRectangle.Height + 2;
1264 edge.X = BoxSelectRectangle.Right - 1;
1268 private Rectangle CalculateBoxSelectRectangle (Point pt)
1270 int left = Math.Min (box_select_start.X, pt.X);
1271 int right = Math.Max (box_select_start.X, pt.X);
1272 int top = Math.Min (box_select_start.Y, pt.Y);
1273 int bottom = Math.Max (box_select_start.Y, pt.Y);
1274 return Rectangle.FromLTRB (left, top, right, bottom);
1277 ArrayList BoxSelectedItems {
1279 ArrayList result = new ArrayList ();
1280 foreach (ListViewItem item in owner.Items) {
1281 Rectangle r = item.Bounds;
1283 r.Y += r.Height / 4;
1286 if (BoxSelectRectangle.IntersectsWith (r))
1293 private bool PerformBoxSelection (Point pt)
1295 if (box_select_mode == BoxSelect.None)
1298 BoxSelectRectangle = CalculateBoxSelectRectangle (pt);
1300 ArrayList box_items = BoxSelectedItems;
1304 switch (box_select_mode) {
1306 case BoxSelect.Normal:
1310 case BoxSelect.Control:
1311 items = new ArrayList ();
1312 foreach (ListViewItem item in prev_selection)
1313 if (!box_items.Contains (item))
1315 foreach (ListViewItem item in box_items)
1316 if (!prev_selection.Contains (item))
1320 case BoxSelect.Shift:
1322 foreach (ListViewItem item in box_items)
1323 prev_selection.Remove (item);
1324 foreach (ListViewItem item in prev_selection)
1329 throw new Exception ("Unexpected Selection mode: " + box_select_mode);
1333 owner.SelectItems (items);
1339 private void ItemsMouseDown (object sender, MouseEventArgs me)
1341 if (owner.items.Count == 0)
1344 Point pt = new Point (me.X, me.Y);
1345 foreach (ListViewItem item in owner.items) {
1346 if (item.CheckRectReal.Contains (pt)) {
1347 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1348 item.Checked = !item.Checked;
1350 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1352 // Raise the ItemCheck event
1353 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1354 owner.OnItemCheck (ice);
1358 if (owner.View == View.Details && !owner.FullRowSelect) {
1359 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1360 clicked_item = item;
1364 if (item.Bounds.Contains (pt)) {
1365 clicked_item = item;
1371 owner.SetFocusedItem (clicked_item);
1373 if (clicked_item != null) {
1374 bool changed = !clicked_item.Selected;
1375 if (owner.MultiSelect && (XplatUI.State.ModifierKeys & Keys.Control) == 0)
1376 owner.UpdateMultiSelection (clicked_item.Index);
1378 clicked_item.Selected = true;
1381 owner.OnSelectedIndexChanged (EventArgs.Empty);
1383 // Raise double click if the item was clicked. On MS the
1384 // double click is only raised if you double click an item
1385 if (me.Clicks > 1 && clicked_item != null)
1386 owner.OnDoubleClick (EventArgs.Empty);
1387 else if (me.Clicks == 1 && clicked_item != null)
1388 owner.OnClick (EventArgs.Empty);
1390 if (owner.MultiSelect) {
1391 Keys mods = XplatUI.State.ModifierKeys;
1392 if ((mods & Keys.Shift) != 0)
1393 box_select_mode = BoxSelect.Shift;
1394 else if ((mods & Keys.Control) != 0)
1395 box_select_mode = BoxSelect.Control;
1397 box_select_mode = BoxSelect.Normal;
1398 box_select_start = pt;
1399 prev_selection = (ArrayList) owner.SelectedItems.list.Clone ();
1400 } else if (owner.selected_indices.Count > 0) {
1401 owner.SelectedItems.Clear ();
1402 owner.SelectedIndices.list.Clear ();
1403 owner.OnSelectedIndexChanged (EventArgs.Empty);
1408 private void ItemsMouseMove (object sender, MouseEventArgs me)
1410 if (PerformBoxSelection (new Point (me.X, me.Y)))
1413 if (owner.HoverSelection && hover_processed) {
1415 Point pt = PointToClient (Control.MousePosition);
1416 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1417 if (item == null || item.Selected)
1420 hover_processed = false;
1421 XplatUI.ResetMouseHover (Handle);
1426 private void ItemsMouseHover (object sender, EventArgs e)
1428 if (Capture || !owner.HoverSelection)
1431 hover_processed = true;
1432 Point pt = PointToClient (Control.MousePosition);
1433 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1438 item.Selected = true;
1439 owner.OnSelectedIndexChanged (new EventArgs ());
1442 private void ItemsMouseUp (object sender, MouseEventArgs me)
1445 if (owner.Items.Count == 0)
1448 Point pt = new Point (me.X, me.Y);
1450 Rectangle rect = Rectangle.Empty;
1451 if (clicked_item != null) {
1452 if (owner.view == View.Details && !owner.full_row_select)
1453 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1455 rect = clicked_item.Bounds;
1457 if (rect.Contains (pt)) {
1458 switch (owner.activation) {
1459 case ItemActivation.OneClick:
1460 owner.OnItemActivate (EventArgs.Empty);
1463 case ItemActivation.TwoClick:
1464 if (last_clicked_item == clicked_item) {
1465 owner.OnItemActivate (EventArgs.Empty);
1466 last_clicked_item = null;
1468 last_clicked_item = clicked_item;
1471 // DoubleClick activation is handled in another handler
1475 } else if (owner.SelectedItems.Count > 0 && BoxSelectRectangle.Size.IsEmpty) {
1476 // Need this to clean up background clicks
1477 owner.SelectedItems.Clear ();
1478 owner.SelectedIndices.list.Clear ();
1479 owner.OnSelectedIndexChanged (EventArgs.Empty);
1482 clicked_item = null;
1483 box_select_start = Point.Empty;
1484 BoxSelectRectangle = Rectangle.Empty;
1485 prev_selection = null;
1486 box_select_mode = BoxSelect.None;
1489 private void ItemsMouseWheel (object sender, MouseEventArgs me)
1491 if (owner.Items.Count == 0)
1494 int lines = me.Delta / 120;
1499 switch (owner.View) {
1501 case View.SmallIcon:
1502 owner.Scroll (owner.v_scroll, -owner.Items [0].Bounds.Height * SystemInformation.MouseWheelScrollLines * lines);
1504 case View.LargeIcon:
1505 owner.Scroll (owner.v_scroll, -(owner.Items [0].Bounds.Height + ThemeEngine.Current.ListViewVerticalSpacing) * lines);
1508 owner.Scroll (owner.h_scroll, -owner.Items [0].Bounds.Width * lines);
1513 internal override void OnPaintInternal (PaintEventArgs pe)
1515 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1519 internal override void OnPaintInternal (PaintEventArgs pe)
1524 CalculateScrollBars ();
1527 private void ListView_SizeChanged (object sender, EventArgs e)
1529 CalculateListView (alignment);
1532 private void SetFocusedItem (ListViewItem item)
1534 if (focused_item != null)
1535 focused_item.Focused = false;
1538 item.Focused = true;
1540 focused_item = item;
1543 private void HorizontalScroller (object sender, EventArgs e)
1545 // Avoid unnecessary flickering, when button is
1546 // kept pressed at the end
1547 if (h_marker != h_scroll.Value) {
1549 int pixels = h_marker - h_scroll.Value;
1551 h_marker = h_scroll.Value;
1552 if (header_control.Visible)
1553 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1555 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1559 private void VerticalScroller (object sender, EventArgs e)
1561 // Avoid unnecessary flickering, when button is
1562 // kept pressed at the end
1563 if (v_marker != v_scroll.Value) {
1564 int pixels = v_marker - v_scroll.Value;
1565 Rectangle area = item_control.ClientRectangle;
1566 v_marker = v_scroll.Value;
1567 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1570 #endregion // Internal Methods Properties
1572 #region Protected Methods
1573 protected override void CreateHandle ()
1575 base.CreateHandle ();
1578 protected override void Dispose (bool disposing)
1581 h_scroll.Dispose ();
1582 v_scroll.Dispose ();
1584 large_image_list = null;
1585 small_image_list = null;
1586 state_image_list = null;
1589 base.Dispose (disposing);
1592 protected override bool IsInputKey (Keys keyData)
1609 return base.IsInputKey (keyData);
1612 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1614 if (AfterLabelEdit != null)
1615 AfterLabelEdit (this, e);
1618 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1620 if (BeforeLabelEdit != null)
1621 BeforeLabelEdit (this, e);
1624 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1626 if (ColumnClick != null)
1627 ColumnClick (this, e);
1630 protected override void OnEnabledChanged (EventArgs e)
1632 base.OnEnabledChanged (e);
1635 protected override void OnFontChanged (EventArgs e)
1637 base.OnFontChanged (e);
1641 protected override void OnHandleCreated (EventArgs e)
1643 base.OnHandleCreated (e);
1645 Controls.AddImplicit (header_control);
1646 Controls.AddImplicit (item_control);
1647 Controls.AddImplicit (this.v_scroll);
1648 Controls.AddImplicit (this.h_scroll);
1652 protected override void OnHandleDestroyed (EventArgs e)
1654 base.OnHandleDestroyed (e);
1657 protected virtual void OnItemActivate (EventArgs e)
1659 if (ItemActivate != null)
1660 ItemActivate (this, e);
1663 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1665 if (ItemCheck != null)
1666 ItemCheck (this, ice);
1669 protected virtual void OnItemDrag (ItemDragEventArgs e)
1671 if (ItemDrag != null)
1675 protected virtual void OnSelectedIndexChanged (EventArgs e)
1677 if (SelectedIndexChanged != null)
1678 SelectedIndexChanged (this, e);
1681 protected override void OnSystemColorsChanged (EventArgs e)
1683 base.OnSystemColorsChanged (e);
1686 protected void RealizeProperties ()
1691 protected void UpdateExtendedStyles ()
1696 protected override void WndProc (ref Message m)
1698 base.WndProc (ref m);
1700 #endregion // Protected Methods
1702 #region Public Instance Methods
1703 public void ArrangeIcons ()
1705 ArrangeIcons (this.alignment);
1708 public void ArrangeIcons (ListViewAlignment alignment)
1710 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1711 if (view == View.LargeIcon || view == View.SmallIcon) {
1712 this.CalculateListView (alignment);
1713 // we have done the calculations already
1714 this.Redraw (false);
1718 public void BeginUpdate ()
1720 // flag to avoid painting
1724 public void Clear ()
1727 items.Clear (); // Redraw (true) called here
1730 public void EndUpdate ()
1732 // flag to avoid painting
1735 // probably, now we need a redraw with recalculations
1739 public void EnsureVisible (int index)
1741 if (index < 0 || index >= items.Count || scrollable == false)
1744 Rectangle view_rect = item_control.ClientRectangle;
1745 Rectangle bounds = items [index].Bounds;
1747 if (view_rect.Contains (bounds))
1750 if (bounds.Left < 0)
1751 h_scroll.Value += bounds.Left;
1752 else if (bounds.Right > view_rect.Right)
1753 h_scroll.Value += (bounds.Right - view_rect.Right);
1756 v_scroll.Value += bounds.Top;
1757 else if (bounds.Bottom > view_rect.Bottom)
1758 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1761 public ListViewItem GetItemAt (int x, int y)
1763 foreach (ListViewItem item in items) {
1764 if (item.Bounds.Contains (x, y))
1770 public Rectangle GetItemRect (int index)
1772 return GetItemRect (index, ItemBoundsPortion.Entire);
1775 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1777 if (index < 0 || index >= items.Count)
1778 throw new IndexOutOfRangeException ("Invalid Index");
1780 return items [index].GetBounds (portion);
1785 if (sort_order != SortOrder.None)
1786 items.list.Sort (item_sorter);
1788 if (sort_order == SortOrder.Descending)
1789 items.list.Reverse ();
1794 public override string ToString ()
1796 int count = this.Items.Count;
1799 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1801 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1803 #endregion // Public Instance Methods
1808 class HeaderControl : Control {
1811 bool column_resize_active = false;
1812 ColumnHeader resize_column;
1813 ColumnHeader clicked_column;
1814 ColumnHeader drag_column;
1816 int drag_to_index = -1;
1818 public HeaderControl (ListView owner)
1821 MouseDown += new MouseEventHandler (HeaderMouseDown);
1822 MouseMove += new MouseEventHandler (HeaderMouseMove);
1823 MouseUp += new MouseEventHandler (HeaderMouseUp);
1826 private ColumnHeader ColumnAtX (int x)
1828 Point pt = new Point (x, 0);
1829 ColumnHeader result = null;
1830 foreach (ColumnHeader col in owner.Columns) {
1831 if (col.Rect.Contains (pt)) {
1839 private int GetReorderedIndex (ColumnHeader col)
1841 if (owner.reordered_column_indices == null)
1844 for (int i = 0; i < owner.Columns.Count; i++)
1845 if (owner.reordered_column_indices [i] == col.Index)
1847 throw new Exception ("Column index missing from reordered array");
1850 private void HeaderMouseDown (object sender, MouseEventArgs me)
1852 if (resize_column != null) {
1853 column_resize_active = true;
1858 clicked_column = ColumnAtX (me.X + owner.h_marker);
1860 if (clicked_column != null) {
1862 if (owner.AllowColumnReorder) {
1864 drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
1865 drag_column.column_rect = clicked_column.Rect;
1866 drag_to_index = GetReorderedIndex (clicked_column);
1868 clicked_column.pressed = true;
1869 Rectangle bounds = clicked_column.Rect;
1870 bounds.X -= owner.h_marker;
1871 Invalidate (bounds);
1876 private void HeaderMouseMove (object sender, MouseEventArgs me)
1878 Point pt = new Point (me.X + owner.h_marker, me.Y);
1880 if (column_resize_active) {
1881 resize_column.Width = pt.X - resize_column.X;
1882 if (resize_column.Width < 0)
1883 resize_column.Width = 0;
1887 resize_column = null;
1889 if (clicked_column != null) {
1890 if (owner.AllowColumnReorder) {
1893 r = drag_column.column_rect;
1894 r.X = clicked_column.Rect.X + me.X - drag_x;
1895 drag_column.column_rect = r;
1897 int x = me.X + owner.h_marker;
1898 ColumnHeader over = ColumnAtX (x);
1900 drag_to_index = owner.Columns.Count;
1901 else if (x < over.X + over.Width / 2)
1902 drag_to_index = GetReorderedIndex (over);
1904 drag_to_index = GetReorderedIndex (over) + 1;
1907 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1908 bool pressed = clicked_column.pressed;
1909 clicked_column.pressed = over == clicked_column;
1910 if (clicked_column.pressed ^ pressed) {
1911 Rectangle bounds = clicked_column.Rect;
1912 bounds.X -= owner.h_marker;
1913 Invalidate (bounds);
1919 for (int i = 0; i < owner.Columns.Count; i++) {
1920 Rectangle zone = owner.Columns [i].Rect;
1921 zone.X = zone.Right - 5;
1923 if (zone.Contains (pt)) {
1924 resize_column = owner.Columns [i];
1929 if (resize_column == null)
1930 Cursor = Cursors.Default;
1932 Cursor = Cursors.VSplit;
1935 void HeaderMouseUp (object sender, MouseEventArgs me)
1939 if (column_resize_active) {
1940 column_resize_active = false;
1941 resize_column = null;
1942 Cursor = Cursors.Default;
1946 if (clicked_column != null && clicked_column.pressed) {
1947 clicked_column.pressed = false;
1948 Rectangle bounds = clicked_column.Rect;
1949 bounds.X -= owner.h_marker;
1950 Invalidate (bounds);
1951 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1954 if (drag_column != null && owner.AllowColumnReorder) {
1956 if (drag_to_index > GetReorderedIndex (clicked_column))
1958 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1959 owner.ReorderColumn (clicked_column, drag_to_index);
1964 clicked_column = null;
1967 internal override void OnPaintInternal (PaintEventArgs pe)
1972 Theme theme = ThemeEngine.Current;
1973 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1975 if (drag_column == null)
1979 if (drag_to_index == owner.Columns.Count)
1980 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1982 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1983 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1988 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1990 internal ArrayList list;
1991 private ListView owner;
1993 #region Public Constructor
1994 public CheckedIndexCollection (ListView owner)
1996 list = new ArrayList ();
1999 #endregion // Public Constructor
2001 #region Public Properties
2004 get { return list.Count; }
2007 public bool IsReadOnly {
2008 get { return true; }
2011 public int this [int index] {
2013 if (index < 0 || index >= list.Count)
2014 throw new ArgumentOutOfRangeException ("Index out of range.");
2015 return (int) list [index];
2019 bool ICollection.IsSynchronized {
2020 get { return false; }
2023 object ICollection.SyncRoot {
2024 get { return this; }
2027 bool IList.IsFixedSize {
2028 get { return true; }
2031 object IList.this [int index] {
2032 get { return this [index]; }
2033 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2035 #endregion // Public Properties
2037 #region Public Methods
2038 public bool Contains (int checkedIndex)
2040 return list.Contains (checkedIndex);
2043 public IEnumerator GetEnumerator ()
2045 return list.GetEnumerator ();
2048 void ICollection.CopyTo (Array dest, int index)
2050 list.CopyTo (dest, index);
2053 int IList.Add (object value)
2055 throw new NotSupportedException ("Add operation is not supported.");
2060 throw new NotSupportedException ("Clear operation is not supported.");
2063 bool IList.Contains (object checkedIndex)
2065 return list.Contains (checkedIndex);
2068 int IList.IndexOf (object checkedIndex)
2070 return list.IndexOf (checkedIndex);
2073 void IList.Insert (int index, object value)
2075 throw new NotSupportedException ("Insert operation is not supported.");
2078 void IList.Remove (object value)
2080 throw new NotSupportedException ("Remove operation is not supported.");
2083 void IList.RemoveAt (int index)
2085 throw new NotSupportedException ("RemoveAt operation is not supported.");
2088 public int IndexOf (int checkedIndex)
2090 return list.IndexOf (checkedIndex);
2092 #endregion // Public Methods
2094 } // CheckedIndexCollection
2096 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
2098 internal ArrayList list;
2099 private ListView owner;
2101 #region Public Constructor
2102 public CheckedListViewItemCollection (ListView owner)
2104 list = new ArrayList ();
2107 #endregion // Public Constructor
2109 #region Public Properties
2112 get { return list.Count; }
2115 public bool IsReadOnly {
2116 get { return true; }
2119 public ListViewItem this [int index] {
2121 if (index < 0 || index >= list.Count)
2122 throw new ArgumentOutOfRangeException ("Index out of range.");
2123 return (ListViewItem) list [index];
2127 bool ICollection.IsSynchronized {
2128 get { return list.IsSynchronized; }
2131 object ICollection.SyncRoot {
2132 get { return this; }
2135 bool IList.IsFixedSize {
2136 get { return true; }
2139 object IList.this [int index] {
2140 get { return this [index]; }
2141 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2143 #endregion // Public Properties
2145 #region Public Methods
2146 public bool Contains (ListViewItem item)
2148 return list.Contains (item);
2151 public void CopyTo (Array dest, int index)
2153 list.CopyTo (dest, index);
2156 public IEnumerator GetEnumerator ()
2158 return list.GetEnumerator ();
2161 int IList.Add (object value)
2163 throw new NotSupportedException ("Add operation is not supported.");
2168 throw new NotSupportedException ("Clear operation is not supported.");
2171 bool IList.Contains (object item)
2173 return list.Contains (item);
2176 int IList.IndexOf (object item)
2178 return list.IndexOf (item);
2181 void IList.Insert (int index, object value)
2183 throw new NotSupportedException ("Insert operation is not supported.");
2186 void IList.Remove (object value)
2188 throw new NotSupportedException ("Remove operation is not supported.");
2191 void IList.RemoveAt (int index)
2193 throw new NotSupportedException ("RemoveAt operation is not supported.");
2196 public int IndexOf (ListViewItem item)
2198 return list.IndexOf (item);
2200 #endregion // Public Methods
2202 } // CheckedListViewItemCollection
2204 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
2206 internal ArrayList list;
2207 private ListView owner;
2209 #region Public Constructor
2210 public ColumnHeaderCollection (ListView owner)
2212 list = new ArrayList ();
2215 #endregion // Public Constructor
2217 #region Public Properties
2220 get { return list.Count; }
2223 public bool IsReadOnly {
2224 get { return false; }
2227 public virtual ColumnHeader this [int index] {
2229 if (index < 0 || index >= list.Count)
2230 throw new ArgumentOutOfRangeException ("Index out of range.");
2231 return (ColumnHeader) list [index];
2235 bool ICollection.IsSynchronized {
2236 get { return true; }
2239 object ICollection.SyncRoot {
2240 get { return this; }
2243 bool IList.IsFixedSize {
2244 get { return list.IsFixedSize; }
2247 object IList.this [int index] {
2248 get { return this [index]; }
2249 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2251 #endregion // Public Properties
2253 #region Public Methods
2254 public virtual int Add (ColumnHeader value)
2257 value.owner = this.owner;
2258 idx = list.Add (value);
2259 owner.Redraw (true);
2263 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
2265 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2266 this.Add (colHeader);
2270 public virtual void AddRange (ColumnHeader [] values)
2272 foreach (ColumnHeader colHeader in values) {
2273 colHeader.owner = this.owner;
2277 owner.Redraw (true);
2280 public virtual void Clear ()
2283 owner.Redraw (true);
2286 public bool Contains (ColumnHeader value)
2288 return list.Contains (value);
2291 public IEnumerator GetEnumerator ()
2293 return list.GetEnumerator ();
2296 void ICollection.CopyTo (Array dest, int index)
2298 list.CopyTo (dest, index);
2301 int IList.Add (object value)
2303 if (! (value is ColumnHeader)) {
2304 throw new ArgumentException ("Not of type ColumnHeader", "value");
2307 return this.Add ((ColumnHeader) value);
2310 bool IList.Contains (object value)
2312 if (! (value is ColumnHeader)) {
2313 throw new ArgumentException ("Not of type ColumnHeader", "value");
2316 return this.Contains ((ColumnHeader) value);
2319 int IList.IndexOf (object value)
2321 if (! (value is ColumnHeader)) {
2322 throw new ArgumentException ("Not of type ColumnHeader", "value");
2325 return this.IndexOf ((ColumnHeader) value);
2328 void IList.Insert (int index, object value)
2330 if (! (value is ColumnHeader)) {
2331 throw new ArgumentException ("Not of type ColumnHeader", "value");
2334 this.Insert (index, (ColumnHeader) value);
2337 void IList.Remove (object value)
2339 if (! (value is ColumnHeader)) {
2340 throw new ArgumentException ("Not of type ColumnHeader", "value");
2343 this.Remove ((ColumnHeader) value);
2346 public int IndexOf (ColumnHeader value)
2348 return list.IndexOf (value);
2351 public void Insert (int index, ColumnHeader value)
2353 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2354 // but it's really only greater.
2355 if (index < 0 || index > list.Count)
2356 throw new ArgumentOutOfRangeException ("Index out of range.");
2358 value.owner = this.owner;
2359 list.Insert (index, value);
2360 owner.Redraw (true);
2363 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2365 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2366 this.Insert (index, colHeader);
2369 public virtual void Remove (ColumnHeader column)
2371 // TODO: Update Column internal index ?
2372 list.Remove (column);
2373 owner.Redraw (true);
2376 public virtual void RemoveAt (int index)
2378 if (index < 0 || index >= list.Count)
2379 throw new ArgumentOutOfRangeException ("Index out of range.");
2381 // TODO: Update Column internal index ?
2382 list.RemoveAt (index);
2383 owner.Redraw (true);
2385 #endregion // Public Methods
2388 } // ColumnHeaderCollection
2390 public class ListViewItemCollection : IList, ICollection, IEnumerable
2392 internal ArrayList list;
2393 private ListView owner;
2395 #region Public Constructor
2396 public ListViewItemCollection (ListView owner)
2398 list = new ArrayList ();
2401 #endregion // Public Constructor
2403 #region Public Properties
2406 get { return list.Count; }
2409 public bool IsReadOnly {
2410 get { return false; }
2413 public virtual ListViewItem this [int displayIndex] {
2415 if (displayIndex < 0 || displayIndex >= list.Count)
2416 throw new ArgumentOutOfRangeException ("Index out of range.");
2417 return (ListViewItem) list [displayIndex];
2421 if (displayIndex < 0 || displayIndex >= list.Count)
2422 throw new ArgumentOutOfRangeException ("Index out of range.");
2424 if (list.Contains (value))
2425 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2427 value.Owner = owner;
2428 list [displayIndex] = value;
2430 owner.Redraw (true);
2434 bool ICollection.IsSynchronized {
2435 get { return true; }
2438 object ICollection.SyncRoot {
2439 get { return this; }
2442 bool IList.IsFixedSize {
2443 get { return list.IsFixedSize; }
2446 object IList.this [int index] {
2447 get { return this [index]; }
2449 if (value is ListViewItem)
2450 this [index] = (ListViewItem) value;
2452 this [index] = new ListViewItem (value.ToString ());
2455 #endregion // Public Properties
2457 #region Public Methods
2458 public virtual ListViewItem Add (ListViewItem value)
2460 if (list.Contains (value))
2461 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2463 value.Owner = owner;
2466 if (owner.Sorting != SortOrder.None)
2469 owner.Redraw (true);
2474 public virtual ListViewItem Add (string text)
2476 ListViewItem item = new ListViewItem (text);
2477 return this.Add (item);
2480 public virtual ListViewItem Add (string text, int imageIndex)
2482 ListViewItem item = new ListViewItem (text, imageIndex);
2483 return this.Add (item);
2486 public void AddRange (ListViewItem [] values)
2489 owner.SelectedItems.list.Clear ();
2490 owner.SelectedIndices.list.Clear ();
2491 owner.CheckedItems.list.Clear ();
2492 owner.CheckedIndices.list.Clear ();
2494 foreach (ListViewItem item in values) {
2499 if (owner.Sorting != SortOrder.None)
2502 owner.Redraw (true);
2505 public virtual void Clear ()
2507 owner.SetFocusedItem (null);
2508 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2510 owner.SelectedItems.list.Clear ();
2511 owner.SelectedIndices.list.Clear ();
2512 owner.CheckedItems.list.Clear ();
2513 owner.CheckedIndices.list.Clear ();
2514 owner.Redraw (true);
2517 public bool Contains (ListViewItem item)
2519 return list.Contains (item);
2522 public void CopyTo (Array dest, int index)
2524 list.CopyTo (dest, index);
2527 public IEnumerator GetEnumerator ()
2529 return list.GetEnumerator ();
2532 int IList.Add (object item)
2537 if (item is ListViewItem) {
2538 li = (ListViewItem) item;
2539 if (list.Contains (li))
2540 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2543 li = new ListViewItem (item.ToString ());
2546 result = list.Add (li);
2547 owner.Redraw (true);
2552 bool IList.Contains (object item)
2554 return list.Contains (item);
2557 int IList.IndexOf (object item)
2559 return list.IndexOf (item);
2562 void IList.Insert (int index, object item)
2564 if (item is ListViewItem)
2565 this.Insert (index, (ListViewItem) item);
2567 this.Insert (index, item.ToString ());
2570 void IList.Remove (object item)
2572 Remove ((ListViewItem) item);
2575 public int IndexOf (ListViewItem item)
2577 return list.IndexOf (item);
2580 public ListViewItem Insert (int index, ListViewItem item)
2582 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2583 // but it's really only greater.
2584 if (index < 0 || index > list.Count)
2585 throw new ArgumentOutOfRangeException ("Index out of range.");
2587 if (list.Contains (item))
2588 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2591 list.Insert (index, item);
2592 owner.Redraw (true);
2596 public ListViewItem Insert (int index, string text)
2598 return this.Insert (index, new ListViewItem (text));
2601 public ListViewItem Insert (int index, string text, int imageIndex)
2603 return this.Insert (index, new ListViewItem (text, imageIndex));
2606 public virtual void Remove (ListViewItem item)
2608 if (!list.Contains (item))
2611 owner.SelectedItems.list.Remove (item);
2612 owner.SelectedIndices.list.Remove (item.Index);
2613 owner.CheckedItems.list.Remove (item);
2614 owner.CheckedIndices.list.Remove (item.Index);
2616 owner.Redraw (true);
2619 public virtual void RemoveAt (int index)
2621 if (index < 0 || index >= list.Count)
2622 throw new ArgumentOutOfRangeException ("Index out of range.");
2624 list.RemoveAt (index);
2625 owner.SelectedItems.list.RemoveAt (index);
2626 owner.SelectedIndices.list.RemoveAt (index);
2627 owner.CheckedItems.list.RemoveAt (index);
2628 owner.CheckedIndices.list.RemoveAt (index);
2629 owner.Redraw (false);
2631 #endregion // Public Methods
2633 } // ListViewItemCollection
2635 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2637 internal ArrayList list;
2638 private ListView owner;
2640 #region Public Constructor
2641 public SelectedIndexCollection (ListView owner)
2643 list = new ArrayList ();
2646 #endregion // Public Constructor
2648 #region Public Properties
2651 get { return list.Count; }
2654 public bool IsReadOnly {
2655 get { return true; }
2658 public int this [int index] {
2660 if (index < 0 || index >= list.Count)
2661 throw new ArgumentOutOfRangeException ("Index out of range.");
2662 return (int) list [index];
2666 bool ICollection.IsSynchronized {
2667 get { return list.IsSynchronized; }
2670 object ICollection.SyncRoot {
2671 get { return this; }
2674 bool IList.IsFixedSize {
2675 get { return true; }
2678 object IList.this [int index] {
2679 get { return this [index]; }
2680 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2682 #endregion // Public Properties
2684 #region Public Methods
2685 public bool Contains (int selectedIndex)
2687 return list.Contains (selectedIndex);
2690 public void CopyTo (Array dest, int index)
2692 list.CopyTo (dest, index);
2695 public IEnumerator GetEnumerator ()
2697 return list.GetEnumerator ();
2700 int IList.Add (object value)
2702 throw new NotSupportedException ("Add operation is not supported.");
2707 throw new NotSupportedException ("Clear operation is not supported.");
2710 bool IList.Contains (object selectedIndex)
2712 return list.Contains (selectedIndex);
2715 int IList.IndexOf (object selectedIndex)
2717 return list.IndexOf (selectedIndex);
2720 void IList.Insert (int index, object value)
2722 throw new NotSupportedException ("Insert operation is not supported.");
2725 void IList.Remove (object value)
2727 throw new NotSupportedException ("Remove operation is not supported.");
2730 void IList.RemoveAt (int index)
2732 throw new NotSupportedException ("RemoveAt operation is not supported.");
2735 public int IndexOf (int selectedIndex)
2737 return list.IndexOf (selectedIndex);
2739 #endregion // Public Methods
2741 } // SelectedIndexCollection
2743 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2745 internal ArrayList list;
2746 private ListView owner;
2748 #region Public Constructor
2749 public SelectedListViewItemCollection (ListView owner)
2751 list = new ArrayList ();
2754 #endregion // Public Constructor
2756 #region Public Properties
2759 get { return list.Count; }
2762 public bool IsReadOnly {
2763 get { return true; }
2766 public ListViewItem this [int index] {
2768 if (index < 0 || index >= list.Count)
2769 throw new ArgumentOutOfRangeException ("Index out of range.");
2770 return (ListViewItem) list [index];
2774 bool ICollection.IsSynchronized {
2775 get { return list.IsSynchronized; }
2778 object ICollection.SyncRoot {
2779 get { return this; }
2782 bool IList.IsFixedSize {
2783 get { return true; }
2786 object IList.this [int index] {
2787 get { return this [index]; }
2788 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2790 #endregion // Public Properties
2792 #region Public Methods
2793 public void Clear ()
2795 ArrayList copy = (ArrayList) list.Clone ();
2796 for (int i = 0; i < copy.Count; i++)
2797 ((ListViewItem) copy [i]).Selected = false;
2802 public bool Contains (ListViewItem item)
2804 return list.Contains (item);
2807 public void CopyTo (Array dest, int index)
2809 list.CopyTo (dest, index);
2812 public IEnumerator GetEnumerator ()
2814 return list.GetEnumerator ();
2817 int IList.Add (object value)
2819 throw new NotSupportedException ("Add operation is not supported.");
2822 bool IList.Contains (object item)
2824 return list.Contains (item);
2827 int IList.IndexOf (object item)
2829 return list.IndexOf (item);
2832 void IList.Insert (int index, object value)
2834 throw new NotSupportedException ("Insert operation is not supported.");
2837 void IList.Remove (object value)
2839 throw new NotSupportedException ("Remove operation is not supported.");
2842 void IList.RemoveAt (int index)
2844 throw new NotSupportedException ("RemoveAt operation is not supported.");
2847 public int IndexOf (ListViewItem item)
2849 return list.IndexOf (item);
2851 #endregion // Public Methods
2853 } // SelectedListViewItemCollection
2855 #endregion // Subclasses