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 base.Paint += new PaintEventHandler (ListView_Paint);
163 SizeChanged += new EventHandler (ListView_SizeChanged);
165 this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
167 #endregion // Public Constructors
169 #region Private Internal Properties
170 internal Size CheckBoxSize {
172 if (this.check_boxes) {
173 if (this.state_image_list != null)
174 return this.state_image_list.ImageSize;
176 return ThemeEngine.Current.ListViewCheckBoxSize;
182 internal bool CanMultiselect {
184 if (multiselect && (XplatUI.State.ModifierKeys & (Keys.Control | Keys.Shift)) != 0)
191 #endregion // Private Internal Properties
193 #region Protected Properties
194 protected override CreateParams CreateParams {
195 get { return base.CreateParams; }
198 protected override Size DefaultSize {
199 get { return ThemeEngine.Current.ListViewDefaultSize; }
201 #endregion // Protected Properties
203 #region Public Instance Properties
204 [DefaultValue (ItemActivation.Standard)]
205 public ItemActivation Activation {
206 get { return activation; }
208 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
209 value != ItemActivation.TwoClick) {
210 throw new InvalidEnumArgumentException (string.Format
211 ("Enum argument value '{0}' is not valid for Activation", value));
218 [DefaultValue (ListViewAlignment.Top)]
220 public ListViewAlignment Alignment {
221 get { return alignment; }
223 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
224 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
225 throw new InvalidEnumArgumentException (string.Format
226 ("Enum argument value '{0}' is not valid for Alignment", value));
229 if (this.alignment != value) {
231 // alignment does not matter in Details/List views
232 if (this.view == View.LargeIcon ||
233 this.View == View.SmallIcon)
239 [DefaultValue (false)]
240 public bool AllowColumnReorder {
241 get { return allow_column_reorder; }
242 set { allow_column_reorder = value; }
245 [DefaultValue (true)]
246 public bool AutoArrange {
247 get { return auto_arrange; }
249 if (auto_arrange != value) {
250 auto_arrange = value;
251 // autoarrange does not matter in Details/List views
252 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
258 public override Color BackColor {
260 if (background_color.IsEmpty)
261 return ThemeEngine.Current.ColorWindow;
263 return background_color;
265 set { background_color = value; }
269 [EditorBrowsable (EditorBrowsableState.Never)]
270 public override Image BackgroundImage {
271 get { return background_image; }
273 if (value == background_image)
276 background_image = value;
277 OnBackgroundImageChanged (EventArgs.Empty);
281 [DefaultValue (BorderStyle.Fixed3D)]
283 public BorderStyle BorderStyle {
284 get { return InternalBorderStyle; }
285 set { InternalBorderStyle = value; }
288 [DefaultValue (false)]
289 public bool CheckBoxes {
290 get { return check_boxes; }
292 if (check_boxes != value) {
300 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
301 public CheckedIndexCollection CheckedIndices {
302 get { return checked_indices; }
306 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
307 public CheckedListViewItemCollection CheckedItems {
308 get { return checked_items; }
311 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
313 [MergableProperty (false)]
314 public ColumnHeaderCollection Columns {
315 get { return columns; }
319 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
320 public ListViewItem FocusedItem {
322 if (focused_item == null && Focused && items.Count > 0)
323 focused_item = items [0];
328 public override Color ForeColor {
330 if (foreground_color.IsEmpty)
331 return ThemeEngine.Current.ColorWindowText;
333 return foreground_color;
335 set { foreground_color = value; }
338 [DefaultValue (false)]
339 public bool FullRowSelect {
340 get { return full_row_select; }
341 set { full_row_select = value; }
344 [DefaultValue (false)]
345 public bool GridLines {
346 get { return grid_lines; }
348 if (grid_lines != value) {
355 [DefaultValue (ColumnHeaderStyle.Clickable)]
356 public ColumnHeaderStyle HeaderStyle {
357 get { return header_style; }
359 if (header_style == value)
363 case ColumnHeaderStyle.Clickable:
364 case ColumnHeaderStyle.Nonclickable:
365 case ColumnHeaderStyle.None:
368 throw new InvalidEnumArgumentException (string.Format
369 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
372 header_style = value;
373 if (view == View.Details)
378 [DefaultValue (true)]
379 public bool HideSelection {
380 get { return hide_selection; }
382 if (hide_selection != value) {
383 hide_selection = value;
389 [DefaultValue (false)]
390 public bool HoverSelection {
391 get { return hover_selection; }
392 set { hover_selection = value; }
395 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
397 [MergableProperty (false)]
398 public ListViewItemCollection Items {
399 get { return items; }
402 [DefaultValue (false)]
403 public bool LabelEdit {
404 get { return label_edit; }
405 set { label_edit = value; }
408 [DefaultValue (true)]
410 public bool LabelWrap {
411 get { return label_wrap; }
413 if (label_wrap != value) {
420 [DefaultValue (null)]
421 public ImageList LargeImageList {
422 get { return large_image_list; }
424 large_image_list = value;
430 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
431 public IComparer ListViewItemSorter {
432 get { return item_sorter; }
433 set { item_sorter = value; }
436 [DefaultValue (true)]
437 public bool MultiSelect {
438 get { return multiselect; }
439 set { multiselect = value; }
442 [DefaultValue (true)]
443 public bool Scrollable {
444 get { return scrollable; }
446 if (scrollable != value) {
454 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
455 public SelectedIndexCollection SelectedIndices {
456 get { return selected_indices; }
460 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
461 public SelectedListViewItemCollection SelectedItems {
462 get { return selected_items; }
465 [DefaultValue (null)]
466 public ImageList SmallImageList {
467 get { return small_image_list; }
469 small_image_list = value;
474 [DefaultValue (SortOrder.None)]
475 public SortOrder Sorting {
476 get { return sort_order; }
478 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
479 value != SortOrder.None) {
480 throw new InvalidEnumArgumentException (string.Format
481 ("Enum argument value '{0}' is not valid for Sorting", value));
484 if (sort_order != value) {
491 [DefaultValue (null)]
492 public ImageList StateImageList {
493 get { return state_image_list; }
495 state_image_list = value;
502 [EditorBrowsable (EditorBrowsableState.Never)]
503 public override string Text {
512 OnTextChanged (EventArgs.Empty);
517 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
518 public ListViewItem TopItem {
521 if (this.items.Count == 0)
523 // if contents are not scrolled
524 // it is the first item
525 else if (h_marker == 0 && v_marker == 0)
526 return this.items [0];
527 // do a hit test for the scrolled position
529 foreach (ListViewItem item in this.items) {
530 if (item.Bounds.X >= 0 && item.Bounds.Y >= 0)
538 [DefaultValue (View.LargeIcon)]
542 if (value != View.Details && value != View.LargeIcon &&
543 value != View.List && value != View.SmallIcon ) {
544 throw new InvalidEnumArgumentException (string.Format
545 ("Enum argument value '{0}' is not valid for View", value));
549 h_scroll.Value = v_scroll.Value = 0;
555 #endregion // Public Instance Properties
557 #region Internal Methods Properties
559 internal int FirstVisibleIndex {
562 if (this.items.Count == 0)
565 if (h_marker == 0 && v_marker == 0)
568 foreach (ListViewItem item in this.items) {
569 if (item.Bounds.Right >= 0 && item.Bounds.Bottom >= 0)
578 internal int LastVisibleIndex {
580 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
581 if (Items[i].Bounds.Y > ClientRectangle.Bottom)
585 return Items.Count - 1;
589 internal int TotalWidth {
590 get { return Math.Max (this.Width, this.layout_wd); }
593 internal int TotalHeight {
594 get { return Math.Max (this.Height, this.layout_ht); }
597 internal void Redraw (bool recalculate)
599 // Avoid calculations when control is being updated
604 CalculateListView (this.alignment);
609 internal Size GetChildColumnSize (int index)
611 Size ret_size = Size.Empty;
612 ColumnHeader col = this.columns [index];
614 if (col.Width == -2) { // autosize = max(items, columnheader)
615 Size size = Size.Ceiling (this.DeviceContext.MeasureString
616 (col.Text, this.Font));
617 ret_size = BiggestItem (index);
618 if (size.Width > ret_size.Width)
621 else { // -1 and all the values < -2 are put under one category
622 ret_size = BiggestItem (index);
623 // fall back to empty columns' width if no subitem is available for a column
624 if (ret_size.IsEmpty) {
625 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
626 if (col.Text.Length > 0)
627 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
628 (col.Text, this.Font)).Height;
630 ret_size.Height = this.Font.Height;
634 // adjust the size for icon and checkbox for 0th column
636 ret_size.Width += (this.CheckBoxSize.Width + 4);
637 if (this.small_image_list != null)
638 ret_size.Width += this.small_image_list.ImageSize.Width;
643 // Returns the size of biggest item text in a column.
644 private Size BiggestItem (int col)
646 Size temp = Size.Empty;
647 Size ret_size = Size.Empty;
649 // 0th column holds the item text, we check the size of
650 // the various subitems falling in that column and get
651 // the biggest one's size.
652 foreach (ListViewItem item in items) {
653 if (col >= item.SubItems.Count)
656 temp = Size.Ceiling (this.DeviceContext.MeasureString
657 (item.SubItems [col].Text, this.Font));
658 if (temp.Width > ret_size.Width)
662 // adjustment for space
663 if (!ret_size.IsEmpty)
669 // Sets the size of the biggest item text as per the view
670 private void CalcTextSize ()
672 // clear the old value
673 text_size = Size.Empty;
675 if (items.Count == 0)
678 text_size = BiggestItem (0);
680 if (view == View.LargeIcon && this.label_wrap) {
681 Size temp = Size.Empty;
682 if (this.check_boxes)
683 temp.Width += 2 * this.CheckBoxSize.Width;
684 if (large_image_list != null)
685 temp.Width += large_image_list.ImageSize.Width;
688 // wrapping is done for two lines only
689 if (text_size.Width > temp.Width) {
690 text_size.Width = temp.Width;
691 text_size.Height *= 2;
694 else if (view == View.List) {
695 // in list view max text shown in determined by the
696 // control width, even if scolling is enabled.
697 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
698 if (this.small_image_list != null)
699 max_wd -= this.small_image_list.ImageSize.Width;
701 if (text_size.Width > max_wd)
702 text_size.Width = max_wd;
705 // we do the default settings, if we have got 0's
706 if (text_size.Height <= 0)
707 text_size.Height = this.Font.Height;
708 if (text_size.Width <= 0)
709 text_size.Width = this.Width;
712 text_size.Width += 4;
713 text_size.Height += 2;
716 private void CalculateScrollBars ()
718 Rectangle client_area = ClientRectangle;
720 if (!this.scrollable || this.items.Count <= 0) {
721 h_scroll.Visible = false;
722 v_scroll.Visible = false;
726 // making a scroll bar visible might make
727 // other scroll bar visible
728 if (layout_wd > client_area.Right) {
729 h_scroll.Visible = true;
730 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
731 v_scroll.Visible = true;
733 v_scroll.Visible = false;
734 } else if (layout_ht > client_area.Bottom) {
735 v_scroll.Visible = true;
736 if ((layout_wd + v_scroll.Width) > client_area.Right)
737 h_scroll.Visible = true;
739 h_scroll.Visible = false;
741 h_scroll.Visible = false;
742 v_scroll.Visible = false;
745 item_control.Height = ClientRectangle.Height - header_control.Height;
747 if (h_scroll.Visible) {
748 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
749 h_scroll.Minimum = 0;
751 // if v_scroll is visible, adjust the maximum of the
752 // h_scroll to account for the width of v_scroll
753 if (v_scroll.Visible) {
754 h_scroll.Maximum = layout_wd + v_scroll.Width;
755 h_scroll.Width = client_area.Width - v_scroll.Width;
758 h_scroll.Maximum = layout_wd;
759 h_scroll.Width = client_area.Width;
762 h_scroll.LargeChange = client_area.Width;
763 h_scroll.SmallChange = Font.Height;
764 item_control.Height -= h_scroll.Height;
767 if (header_control.Visible)
768 header_control.Width = ClientRectangle.Width;
769 item_control.Width = ClientRectangle.Width;
771 if (v_scroll.Visible) {
772 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
773 v_scroll.Minimum = 0;
775 // if h_scroll is visible, adjust the maximum of the
776 // v_scroll to account for the height of h_scroll
777 if (h_scroll.Visible) {
778 v_scroll.Maximum = layout_ht + h_scroll.Height;
779 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
781 v_scroll.Maximum = layout_ht;
782 v_scroll.Height = client_area.Height;
785 v_scroll.LargeChange = client_area.Height;
786 v_scroll.SmallChange = Font.Height;
787 if (header_control.Visible)
788 header_control.Width -= v_scroll.Width;
789 item_control.Width -= v_scroll.Width;
793 ColumnHeader GetReorderedColumn (int index)
795 if (reordered_column_indices == null)
796 return Columns [index];
798 return Columns [reordered_column_indices [index]];
801 void ReorderColumn (ColumnHeader col, int index)
803 if (reordered_column_indices == null) {
804 reordered_column_indices = new int [Columns.Count];
805 for (int i = 0; i < Columns.Count; i++)
806 reordered_column_indices [i] = i;
809 if (reordered_column_indices [index] == col.Index)
812 int[] curr = reordered_column_indices;
813 int[] result = new int [Columns.Count];
815 for (int i = 0; i < Columns.Count; i++) {
816 if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
820 result [i] = col.Index;
822 result [i] = curr [curr_idx++];
825 reordered_column_indices = result;
827 header_control.Invalidate ();
828 item_control.Invalidate ();
831 Size LargeIconItemSize {
833 int w = Math.Max (text_size.Width, 2 + CheckBoxSize.Width + LargeImageList.ImageSize.Width);
834 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, LargeImageList.ImageSize.Height);
835 return new Size (w, h);
839 Size SmallIconItemSize {
841 int w = text_size.Width + 2 + CheckBoxSize.Width + SmallImageList.ImageSize.Width;
842 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, SmallImageList.ImageSize.Height));
843 return new Size (w, h);
849 ListViewItem[,] item_matrix;
851 void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
853 header_control.Visible = false;
854 header_control.Size = Size.Empty;
855 item_control.Location = Point.Empty;
857 if (items.Count == 0)
860 Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
862 Rectangle area = ClientRectangle;
865 rows = (int) Math.Floor ((double)area.Height / (double)(sz.Height + y_spacing));
868 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
870 cols = (int) Math.Floor ((double)area.Width / (double)(sz.Width + x_spacing));
873 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
876 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
877 layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
878 item_matrix = new ListViewItem [rows, cols];
881 foreach (ListViewItem item in items) {
882 int x = col * (sz.Width + x_spacing);
883 int y = row * (sz.Height + y_spacing);
884 item.Location = new Point (x, y);
888 item_matrix [row, col] = item;
902 item_control.Size = new Size (layout_wd, layout_ht);
907 if (columns.Count == 0 || header_style == ColumnHeaderStyle.None) {
908 header_control.Visible = false;
909 header_control.Size = Size.Empty;
914 for (int i = 0; i < Columns.Count; i++) {
915 ColumnHeader col = GetReorderedColumn (i);
918 col.CalcColumnHeader ();
922 header_control.Width = x;
923 header_control.Height = columns [0].Ht;
924 header_control.Visible = true;
927 void LayoutDetails ()
931 item_control.Location = new Point (0, header_control.Height);
934 if (items.Count > 0) {
935 foreach (ListViewItem item in items) {
937 item.Location = new Point (0, y);
938 y += item.Bounds.Height + 2;
941 // some space for bottom gridline
946 layout_wd = Math.Max (header_control.Width, item_control.Width);
947 layout_ht = y + header_control.Height;
950 private void CalculateListView (ListViewAlignment align)
960 LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
964 LayoutIcons (true, alignment == ListViewAlignment.Left,
965 ThemeEngine.Current.ListViewHorizontalSpacing,
966 ThemeEngine.Current.ListViewVerticalSpacing);
970 LayoutIcons (false, true, 4, 2);
974 CalculateScrollBars ();
977 internal void UpdateSelection (ListViewItem item)
981 if (!CanMultiselect && SelectedItems.Count > 0) {
982 SelectedItems.Clear ();
983 SelectedIndices.list.Clear ();
986 if (!SelectedItems.Contains (item)) {
987 SelectedItems.list.Add (item);
988 SelectedIndices.list.Add (item.Index);
991 SelectedItems.list.Remove (item);
992 SelectedIndices.list.Remove (item.Index);
996 private bool KeySearchString (KeyEventArgs ke)
998 int current_tickcnt = Environment.TickCount;
999 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
1000 keysearch_text = string.Empty;
1003 keysearch_text += (char) ke.KeyData;
1004 keysearch_tickcnt = current_tickcnt;
1006 int start = FocusedItem == null ? 0 : FocusedItem.Index;
1009 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1010 CompareOptions.IgnoreCase)) {
1011 SetFocusedItem (Items [i]);
1012 items [i].Selected = true;
1016 i = (i + 1 < Items.Count) ? i+1 : 0;
1024 int GetAdjustedIndex (Keys key)
1028 if (View == View.Details) {
1030 result = FocusedItem.Index - 1;
1031 else if (key == Keys.Down) {
1032 result = FocusedItem.Index + 1;
1033 if (result == items.Count)
1039 int row = FocusedItem.row;
1040 int col = FocusedItem.col;
1046 return item_matrix [row, col - 1].Index;
1049 if (col == (cols - 1))
1051 while (item_matrix [row, col + 1] == null)
1053 return item_matrix [row, col + 1].Index;
1058 return item_matrix [row - 1, col].Index;
1061 if (row == (rows - 1))
1063 while (item_matrix [row + 1, col] == null)
1065 return item_matrix [row + 1, col].Index;
1072 ListViewItem selection_start;
1074 private void SelectItems (ArrayList sel_items)
1076 SelectedItems.Clear ();
1077 SelectedIndices.list.Clear ();
1078 foreach (ListViewItem item in sel_items)
1079 item.Selected = true;
1082 private void UpdateMultiSelection (int index)
1084 bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
1085 bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
1086 ListViewItem item = items [index];
1088 if (shift_pressed && selection_start != null) {
1089 ArrayList list = new ArrayList ();
1090 int start = Math.Min (selection_start.Index, index);
1091 int end = Math.Max (selection_start.Index, index);
1092 if (View == View.Details) {
1093 for (int i = start; i <= end; i++)
1094 list.Add (items [i]);
1096 int left = Math.Min (items [start].col, items [end].col);
1097 int right = Math.Max (items [start].col, items [end].col);
1098 int top = Math.Min (items [start].row, items [end].row);
1099 int bottom = Math.Max (items [start].row, items [end].row);
1100 foreach (ListViewItem curr in items)
1101 if (curr.row >= top && curr.row <= bottom &&
1102 curr.col >= left && curr.col <= right)
1106 } else if (!ctrl_pressed) {
1107 SelectedItems.Clear ();
1108 SelectedIndices.list.Clear ();
1109 item.Selected = true;
1110 selection_start = item;
1114 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1116 if (ke.Handled || Items.Count == 0)
1122 switch (ke.KeyCode) {
1125 index = Items.Count - 1;
1136 index = GetAdjustedIndex (ke.KeyCode);
1140 ke.Handled = KeySearchString (ke);
1148 UpdateMultiSelection (index);
1150 items [index].Selected = true;
1152 SetFocusedItem (items [index]);
1153 EnsureVisible (index);
1157 internal class ItemControl : Control {
1160 ListViewItem clicked_item;
1161 ListViewItem last_clicked_item;
1163 public ItemControl (ListView owner)
1166 DoubleClick += new EventHandler(ItemsDoubleClick);
1167 KeyDown += new KeyEventHandler (ItemsKeyDown);
1168 KeyUp += new KeyEventHandler (ItemsKeyUp);
1169 MouseDown += new MouseEventHandler(ItemsMouseDown);
1170 MouseHover += new EventHandler(ItemsMouseHover);
1171 MouseUp += new MouseEventHandler(ItemsMouseUp);
1172 Paint += new PaintEventHandler (ItemsPaint);
1175 void ItemsDoubleClick (object sender, EventArgs e)
1177 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1178 owner.ItemActivate (this, e);
1181 void ItemsKeyDown (object sender, KeyEventArgs args)
1183 owner.OnKeyDown (args);
1186 void ItemsKeyUp (object sender, KeyEventArgs args)
1188 owner.OnKeyUp (args);
1191 private void ItemsMouseDown (object sender, MouseEventArgs me)
1193 if (owner.items.Count == 0)
1196 Point pt = new Point (me.X, me.Y);
1197 foreach (ListViewItem item in owner.items) {
1198 if (item.CheckRectReal.Contains (pt)) {
1199 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1200 item.Checked = !item.Checked;
1202 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1204 // Raise the ItemCheck event
1205 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1206 owner.OnItemCheck (ice);
1210 if (owner.View == View.Details && !owner.FullRowSelect) {
1211 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1212 clicked_item = item;
1216 if (item.Bounds.Contains (pt)) {
1217 clicked_item = item;
1223 owner.SetFocusedItem (clicked_item);
1225 if (clicked_item != null) {
1226 bool changed = !clicked_item.Selected;
1227 if (owner.MultiSelect && (XplatUI.State.ModifierKeys & Keys.Control) == 0)
1228 owner.UpdateMultiSelection (clicked_item.Index);
1230 clicked_item.Selected = true;
1233 owner.OnSelectedIndexChanged (EventArgs.Empty);
1235 // Raise double click if the item was clicked. On MS the
1236 // double click is only raised if you double click an item
1237 if (me.Clicks > 1 && clicked_item != null)
1238 owner.OnDoubleClick (EventArgs.Empty);
1239 else if (me.Clicks == 1 && clicked_item != null)
1240 owner.OnClick (EventArgs.Empty);
1241 } else if (owner.selected_indices.Count > 0) {
1242 // Raise the event if there was at least one item
1243 // selected and the user click on a dead area (unselecting all)
1244 owner.SelectedItems.Clear ();
1245 owner.SelectedIndices.list.Clear ();
1246 owner.OnSelectedIndexChanged (EventArgs.Empty);
1250 private void ItemsMouseHover (object sender, EventArgs e)
1252 if (Capture || !owner.hover_selection)
1255 Point pt = PointToClient (Control.MousePosition);
1256 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1261 item.Selected = true;
1262 owner.OnSelectedIndexChanged (new EventArgs ());
1265 private void ItemsMouseUp (object sender, MouseEventArgs me)
1268 if (owner.Items.Count == 0)
1271 Point pt = new Point (me.X, me.Y);
1273 Rectangle rect = Rectangle.Empty;
1274 if (clicked_item != null) {
1275 if (owner.view == View.Details && !owner.full_row_select)
1276 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1278 rect = clicked_item.Bounds;
1280 if (rect.Contains (pt)) {
1281 switch (owner.activation) {
1282 case ItemActivation.OneClick:
1283 owner.ItemActivate (this, EventArgs.Empty);
1286 case ItemActivation.TwoClick:
1287 if (last_clicked_item == clicked_item) {
1288 owner.ItemActivate (this, EventArgs.Empty);
1289 last_clicked_item = null;
1291 last_clicked_item = clicked_item;
1294 // DoubleClick activation is handled in another handler
1300 clicked_item = null;
1303 private void ItemsPaint (object sender, PaintEventArgs pe)
1305 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1309 private void ListView_Paint (object sender, PaintEventArgs pe)
1311 if (Width <= 0 || Height <= 0 || !Visible || updating)
1314 CalculateScrollBars ();
1317 private void ListView_SizeChanged (object sender, EventArgs e)
1319 CalculateListView (alignment);
1322 private void SetFocusedItem (ListViewItem item)
1324 if (focused_item != null)
1325 focused_item.Focused = false;
1328 item.Focused = true;
1330 focused_item = item;
1333 private void HorizontalScroller (object sender, EventArgs e)
1335 // Avoid unnecessary flickering, when button is
1336 // kept pressed at the end
1337 if (h_marker != h_scroll.Value) {
1339 int pixels = h_marker - h_scroll.Value;
1341 h_marker = h_scroll.Value;
1342 if (header_control.Visible)
1343 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1345 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1349 private void VerticalScroller (object sender, EventArgs e)
1351 // Avoid unnecessary flickering, when button is
1352 // kept pressed at the end
1353 if (v_marker != v_scroll.Value) {
1354 int pixels = v_marker - v_scroll.Value;
1355 Rectangle area = item_control.ClientRectangle;
1356 v_marker = v_scroll.Value;
1357 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1360 #endregion // Internal Methods Properties
1362 #region Protected Methods
1363 protected override void CreateHandle ()
1365 base.CreateHandle ();
1368 protected override void Dispose (bool disposing)
1371 h_scroll.Dispose ();
1372 v_scroll.Dispose ();
1374 large_image_list = null;
1375 small_image_list = null;
1376 state_image_list = null;
1379 base.Dispose (disposing);
1382 protected override bool IsInputKey (Keys keyData)
1399 return base.IsInputKey (keyData);
1402 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1404 if (AfterLabelEdit != null)
1405 AfterLabelEdit (this, e);
1408 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1410 if (BeforeLabelEdit != null)
1411 BeforeLabelEdit (this, e);
1414 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1416 if (ColumnClick != null)
1417 ColumnClick (this, e);
1420 protected override void OnEnabledChanged (EventArgs e)
1422 base.OnEnabledChanged (e);
1425 protected override void OnFontChanged (EventArgs e)
1427 base.OnFontChanged (e);
1431 protected override void OnHandleCreated (EventArgs e)
1433 base.OnHandleCreated (e);
1435 Controls.AddImplicit (header_control);
1436 Controls.AddImplicit (item_control);
1437 Controls.AddImplicit (this.v_scroll);
1438 Controls.AddImplicit (this.h_scroll);
1442 protected override void OnHandleDestroyed (EventArgs e)
1444 base.OnHandleDestroyed (e);
1447 protected virtual void OnItemActivate (EventArgs e)
1449 if (ItemActivate != null)
1450 ItemActivate (this, e);
1453 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1455 if (ItemCheck != null)
1456 ItemCheck (this, ice);
1459 protected virtual void OnItemDrag (ItemDragEventArgs e)
1461 if (ItemDrag != null)
1465 protected virtual void OnSelectedIndexChanged (EventArgs e)
1467 if (SelectedIndexChanged != null)
1468 SelectedIndexChanged (this, e);
1471 protected override void OnSystemColorsChanged (EventArgs e)
1473 base.OnSystemColorsChanged (e);
1476 protected void RealizeProperties ()
1481 protected void UpdateExtendedStyles ()
1486 protected override void WndProc (ref Message m)
1488 base.WndProc (ref m);
1490 #endregion // Protected Methods
1492 #region Public Instance Methods
1493 public void ArrangeIcons ()
1495 ArrangeIcons (this.alignment);
1498 public void ArrangeIcons (ListViewAlignment alignment)
1500 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1501 if (view == View.LargeIcon || view == View.SmallIcon) {
1502 this.CalculateListView (alignment);
1503 // we have done the calculations already
1504 this.Redraw (false);
1508 public void BeginUpdate ()
1510 // flag to avoid painting
1514 public void Clear ()
1517 items.Clear (); // Redraw (true) called here
1520 public void EndUpdate ()
1522 // flag to avoid painting
1525 // probably, now we need a redraw with recalculations
1529 public void EnsureVisible (int index)
1531 if (index < 0 || index >= items.Count || scrollable == false)
1534 Rectangle view_rect = item_control.ClientRectangle;
1535 Rectangle bounds = items [index].Bounds;
1537 if (view_rect.Contains (bounds))
1540 if (bounds.Left < 0)
1541 h_scroll.Value += bounds.Left;
1542 else if (bounds.Right > view_rect.Right)
1543 h_scroll.Value += (bounds.Right - view_rect.Right);
1546 v_scroll.Value += bounds.Top;
1547 else if (bounds.Bottom > view_rect.Bottom)
1548 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1551 public ListViewItem GetItemAt (int x, int y)
1553 foreach (ListViewItem item in items) {
1554 if (item.Bounds.Contains (x, y))
1560 public Rectangle GetItemRect (int index)
1562 return GetItemRect (index, ItemBoundsPortion.Entire);
1565 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1567 if (index < 0 || index >= items.Count)
1568 throw new IndexOutOfRangeException ("Invalid Index");
1570 return items [index].GetBounds (portion);
1575 if (sort_order != SortOrder.None)
1576 items.list.Sort (item_sorter);
1578 if (sort_order == SortOrder.Descending)
1579 items.list.Reverse ();
1584 public override string ToString ()
1586 int count = this.Items.Count;
1589 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1591 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1593 #endregion // Public Instance Methods
1598 class HeaderControl : Control {
1601 bool column_resize_active = false;
1602 ColumnHeader resize_column;
1603 ColumnHeader clicked_column;
1604 ColumnHeader drag_column;
1606 int drag_to_index = -1;
1608 public HeaderControl (ListView owner)
1611 MouseDown += new MouseEventHandler (HeaderMouseDown);
1612 MouseMove += new MouseEventHandler (HeaderMouseMove);
1613 MouseUp += new MouseEventHandler (HeaderMouseUp);
1614 Paint += new PaintEventHandler (HeaderPaint);
1617 private ColumnHeader ColumnAtX (int x)
1619 Point pt = new Point (x, 0);
1620 ColumnHeader result = null;
1621 foreach (ColumnHeader col in owner.Columns) {
1622 if (col.Rect.Contains (pt)) {
1630 private int GetReorderedIndex (ColumnHeader col)
1632 if (owner.reordered_column_indices == null)
1635 for (int i = 0; i < owner.Columns.Count; i++)
1636 if (owner.reordered_column_indices [i] == col.Index)
1638 throw new Exception ("Column index missing from reordered array");
1641 private void HeaderMouseDown (object sender, MouseEventArgs me)
1643 if (resize_column != null) {
1644 column_resize_active = true;
1649 clicked_column = ColumnAtX (me.X + owner.h_marker);
1651 if (clicked_column != null) {
1653 if (owner.AllowColumnReorder) {
1655 drag_column = (ColumnHeader) clicked_column.Clone ();
1656 drag_column.column_rect = clicked_column.Rect;
1657 drag_to_index = GetReorderedIndex (clicked_column);
1659 clicked_column.pressed = true;
1660 Rectangle bounds = clicked_column.Rect;
1661 bounds.X -= owner.h_marker;
1662 Invalidate (bounds);
1667 private void HeaderMouseMove (object sender, MouseEventArgs me)
1669 Point pt = new Point (me.X + owner.h_marker, me.Y);
1671 if (column_resize_active) {
1672 resize_column.Width = pt.X - resize_column.X;
1673 if (resize_column.Width < 0)
1674 resize_column.Width = 0;
1678 resize_column = null;
1680 if (clicked_column != null) {
1681 if (owner.AllowColumnReorder) {
1684 r = drag_column.column_rect;
1685 r.X = clicked_column.Rect.X + me.X - drag_x;
1686 drag_column.column_rect = r;
1688 int x = me.X + owner.h_marker;
1689 ColumnHeader over = ColumnAtX (x);
1690 if (x < over.X + over.Width / 2)
1691 drag_to_index = GetReorderedIndex (over);
1693 drag_to_index = GetReorderedIndex (over) + 1;
1696 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1697 bool pressed = clicked_column.pressed;
1698 clicked_column.pressed = over == clicked_column;
1699 if (clicked_column.pressed ^ pressed) {
1700 Rectangle bounds = clicked_column.Rect;
1701 bounds.X -= owner.h_marker;
1702 Invalidate (bounds);
1708 for (int i = 0; i < owner.Columns.Count; i++) {
1709 Rectangle zone = owner.Columns [i].Rect;
1710 zone.X = zone.Right - 5;
1712 if (zone.Contains (pt)) {
1713 resize_column = owner.Columns [i];
1718 if (resize_column == null)
1719 Cursor = Cursors.Default;
1721 Cursor = Cursors.VSplit;
1724 void HeaderMouseUp (object sender, MouseEventArgs me)
1728 if (column_resize_active) {
1729 column_resize_active = false;
1730 resize_column = null;
1731 Cursor = Cursors.Default;
1735 if (clicked_column != null && clicked_column.pressed) {
1736 clicked_column.pressed = false;
1737 Rectangle bounds = clicked_column.Rect;
1738 bounds.X -= owner.h_marker;
1739 Invalidate (bounds);
1740 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1743 if (drag_column != null && owner.AllowColumnReorder) {
1745 if (drag_to_index > GetReorderedIndex (clicked_column))
1747 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1748 owner.ReorderColumn (clicked_column, drag_to_index);
1753 clicked_column = null;
1756 void HeaderPaint (object sender, PaintEventArgs pe)
1758 if (Width <= 0 || Height <= 0 || !Visible || owner.updating)
1761 Theme theme = ThemeEngine.Current;
1762 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1764 if (drag_column == null)
1768 if (drag_to_index == owner.Columns.Count)
1769 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1771 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1772 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1777 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1779 internal ArrayList list;
1780 private ListView owner;
1782 #region Public Constructor
1783 public CheckedIndexCollection (ListView owner)
1785 list = new ArrayList ();
1788 #endregion // Public Constructor
1790 #region Public Properties
1792 public virtual int Count {
1793 get { return list.Count; }
1796 public virtual bool IsReadOnly {
1797 get { return true; }
1800 public int this [int index] {
1802 if (index < 0 || index >= list.Count)
1803 throw new ArgumentOutOfRangeException ("Index out of range.");
1804 return (int) list [index];
1808 bool ICollection.IsSynchronized {
1809 get { return false; }
1812 object ICollection.SyncRoot {
1813 get { return this; }
1816 bool IList.IsFixedSize {
1817 get { return true; }
1820 object IList.this [int index] {
1821 get { return this [index]; }
1822 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1824 #endregion // Public Properties
1826 #region Public Methods
1827 public bool Contains (int checkedIndex)
1829 return list.Contains (checkedIndex);
1832 public virtual IEnumerator GetEnumerator ()
1834 return list.GetEnumerator ();
1837 void ICollection.CopyTo (Array dest, int index)
1839 list.CopyTo (dest, index);
1842 int IList.Add (object value)
1844 throw new NotSupportedException ("Add operation is not supported.");
1849 throw new NotSupportedException ("Clear operation is not supported.");
1852 bool IList.Contains (object checkedIndex)
1854 return list.Contains (checkedIndex);
1857 int IList.IndexOf (object checkedIndex)
1859 return list.IndexOf (checkedIndex);
1862 void IList.Insert (int index, object value)
1864 throw new NotSupportedException ("Insert operation is not supported.");
1867 void IList.Remove (object value)
1869 throw new NotSupportedException ("Remove operation is not supported.");
1872 void IList.RemoveAt (int index)
1874 throw new NotSupportedException ("RemoveAt operation is not supported.");
1877 public int IndexOf (int checkedIndex)
1879 return list.IndexOf (checkedIndex);
1881 #endregion // Public Methods
1883 } // CheckedIndexCollection
1885 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1887 internal ArrayList list;
1888 private ListView owner;
1890 #region Public Constructor
1891 public CheckedListViewItemCollection (ListView owner)
1893 list = new ArrayList ();
1896 #endregion // Public Constructor
1898 #region Public Properties
1900 public virtual int Count {
1901 get { return list.Count; }
1904 public virtual bool IsReadOnly {
1905 get { return true; }
1908 public ListViewItem this [int index] {
1910 if (index < 0 || index >= list.Count)
1911 throw new ArgumentOutOfRangeException ("Index out of range.");
1912 return (ListViewItem) list [index];
1916 bool ICollection.IsSynchronized {
1917 get { return list.IsSynchronized; }
1920 object ICollection.SyncRoot {
1921 get { return this; }
1924 bool IList.IsFixedSize {
1925 get { return true; }
1928 object IList.this [int index] {
1929 get { return this [index]; }
1930 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1932 #endregion // Public Properties
1934 #region Public Methods
1935 public bool Contains (ListViewItem item)
1937 return list.Contains (item);
1940 public virtual void CopyTo (Array dest, int index)
1942 list.CopyTo (dest, index);
1945 public virtual IEnumerator GetEnumerator ()
1947 return list.GetEnumerator ();
1950 int IList.Add (object value)
1952 throw new NotSupportedException ("Add operation is not supported.");
1957 throw new NotSupportedException ("Clear operation is not supported.");
1960 bool IList.Contains (object item)
1962 return list.Contains (item);
1965 int IList.IndexOf (object item)
1967 return list.IndexOf (item);
1970 void IList.Insert (int index, object value)
1972 throw new NotSupportedException ("Insert operation is not supported.");
1975 void IList.Remove (object value)
1977 throw new NotSupportedException ("Remove operation is not supported.");
1980 void IList.RemoveAt (int index)
1982 throw new NotSupportedException ("RemoveAt operation is not supported.");
1985 public int IndexOf (ListViewItem item)
1987 return list.IndexOf (item);
1989 #endregion // Public Methods
1991 } // CheckedListViewItemCollection
1993 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1995 internal ArrayList list;
1996 private ListView owner;
1998 #region Public Constructor
1999 public ColumnHeaderCollection (ListView owner)
2001 list = new ArrayList ();
2004 #endregion // Public Constructor
2006 #region Public Properties
2008 public virtual int Count {
2009 get { return list.Count; }
2012 public virtual bool IsReadOnly {
2013 get { return false; }
2016 public virtual ColumnHeader this [int index] {
2018 if (index < 0 || index >= list.Count)
2019 throw new ArgumentOutOfRangeException ("Index out of range.");
2020 return (ColumnHeader) list [index];
2024 bool ICollection.IsSynchronized {
2025 get { return true; }
2028 object ICollection.SyncRoot {
2029 get { return this; }
2032 bool IList.IsFixedSize {
2033 get { return list.IsFixedSize; }
2036 object IList.this [int index] {
2037 get { return this [index]; }
2038 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2040 #endregion // Public Properties
2042 #region Public Methods
2043 public virtual int Add (ColumnHeader value)
2046 value.owner = this.owner;
2047 idx = list.Add (value);
2048 owner.Redraw (true);
2052 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
2054 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2055 this.Add (colHeader);
2059 public virtual void AddRange (ColumnHeader [] values)
2061 foreach (ColumnHeader colHeader in values) {
2062 colHeader.owner = this.owner;
2066 owner.Redraw (true);
2069 public virtual void Clear ()
2072 owner.Redraw (true);
2075 public bool Contains (ColumnHeader value)
2077 return list.Contains (value);
2080 public virtual IEnumerator GetEnumerator ()
2082 return list.GetEnumerator ();
2085 void ICollection.CopyTo (Array dest, int index)
2087 list.CopyTo (dest, index);
2090 int IList.Add (object value)
2092 if (! (value is ColumnHeader)) {
2093 throw new ArgumentException ("Not of type ColumnHeader", "value");
2096 return this.Add ((ColumnHeader) value);
2099 bool IList.Contains (object value)
2101 if (! (value is ColumnHeader)) {
2102 throw new ArgumentException ("Not of type ColumnHeader", "value");
2105 return this.Contains ((ColumnHeader) value);
2108 int IList.IndexOf (object value)
2110 if (! (value is ColumnHeader)) {
2111 throw new ArgumentException ("Not of type ColumnHeader", "value");
2114 return this.IndexOf ((ColumnHeader) value);
2117 void IList.Insert (int index, object value)
2119 if (! (value is ColumnHeader)) {
2120 throw new ArgumentException ("Not of type ColumnHeader", "value");
2123 this.Insert (index, (ColumnHeader) value);
2126 void IList.Remove (object value)
2128 if (! (value is ColumnHeader)) {
2129 throw new ArgumentException ("Not of type ColumnHeader", "value");
2132 this.Remove ((ColumnHeader) value);
2135 public int IndexOf (ColumnHeader value)
2137 return list.IndexOf (value);
2140 public void Insert (int index, ColumnHeader value)
2142 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2143 // but it's really only greater.
2144 if (index < 0 || index > list.Count)
2145 throw new ArgumentOutOfRangeException ("Index out of range.");
2147 value.owner = this.owner;
2148 list.Insert (index, value);
2149 owner.Redraw (true);
2152 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2154 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2155 this.Insert (index, colHeader);
2158 public virtual void Remove (ColumnHeader column)
2160 // TODO: Update Column internal index ?
2161 list.Remove (column);
2162 owner.Redraw (true);
2165 public virtual void RemoveAt (int index)
2167 if (index < 0 || index >= list.Count)
2168 throw new ArgumentOutOfRangeException ("Index out of range.");
2170 // TODO: Update Column internal index ?
2171 list.RemoveAt (index);
2172 owner.Redraw (true);
2174 #endregion // Public Methods
2177 } // ColumnHeaderCollection
2179 public class ListViewItemCollection : IList, ICollection, IEnumerable
2181 internal ArrayList list;
2182 private ListView owner;
2184 #region Public Constructor
2185 public ListViewItemCollection (ListView owner)
2187 list = new ArrayList ();
2190 #endregion // Public Constructor
2192 #region Public Properties
2194 public virtual int Count {
2195 get { return list.Count; }
2198 public virtual bool IsReadOnly {
2199 get { return false; }
2202 public virtual ListViewItem this [int displayIndex] {
2204 if (displayIndex < 0 || displayIndex >= list.Count)
2205 throw new ArgumentOutOfRangeException ("Index out of range.");
2206 return (ListViewItem) list [displayIndex];
2210 if (displayIndex < 0 || displayIndex >= list.Count)
2211 throw new ArgumentOutOfRangeException ("Index out of range.");
2213 if (list.Contains (value))
2214 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2216 value.Owner = owner;
2217 list [displayIndex] = value;
2219 owner.Redraw (true);
2223 bool ICollection.IsSynchronized {
2224 get { return true; }
2227 object ICollection.SyncRoot {
2228 get { return this; }
2231 bool IList.IsFixedSize {
2232 get { return list.IsFixedSize; }
2235 object IList.this [int index] {
2236 get { return this [index]; }
2238 if (value is ListViewItem)
2239 this [index] = (ListViewItem) value;
2241 this [index] = new ListViewItem (value.ToString ());
2244 #endregion // Public Properties
2246 #region Public Methods
2247 public virtual ListViewItem Add (ListViewItem value)
2249 if (list.Contains (value))
2250 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2252 value.Owner = owner;
2255 if (owner.Sorting != SortOrder.None)
2258 owner.Redraw (true);
2263 public virtual ListViewItem Add (string text)
2265 ListViewItem item = new ListViewItem (text);
2266 return this.Add (item);
2269 public virtual ListViewItem Add (string text, int imageIndex)
2271 ListViewItem item = new ListViewItem (text, imageIndex);
2272 return this.Add (item);
2275 public void AddRange (ListViewItem [] values)
2278 owner.SelectedItems.list.Clear ();
2279 owner.SelectedIndices.list.Clear ();
2280 owner.CheckedItems.list.Clear ();
2281 owner.CheckedIndices.list.Clear ();
2283 foreach (ListViewItem item in values) {
2288 if (owner.Sorting != SortOrder.None)
2291 owner.Redraw (true);
2294 public virtual void Clear ()
2296 owner.SetFocusedItem (null);
2297 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2299 owner.SelectedItems.list.Clear ();
2300 owner.SelectedIndices.list.Clear ();
2301 owner.CheckedItems.list.Clear ();
2302 owner.CheckedIndices.list.Clear ();
2303 owner.Redraw (true);
2306 public bool Contains (ListViewItem item)
2308 return list.Contains (item);
2311 public virtual void CopyTo (Array dest, int index)
2313 list.CopyTo (dest, index);
2316 public virtual IEnumerator GetEnumerator ()
2318 return list.GetEnumerator ();
2321 int IList.Add (object item)
2326 if (item is ListViewItem) {
2327 li = (ListViewItem) item;
2328 if (list.Contains (li))
2329 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2332 li = new ListViewItem (item.ToString ());
2335 result = list.Add (li);
2336 owner.Redraw (true);
2341 bool IList.Contains (object item)
2343 return list.Contains (item);
2346 int IList.IndexOf (object item)
2348 return list.IndexOf (item);
2351 void IList.Insert (int index, object item)
2353 if (item is ListViewItem)
2354 this.Insert (index, (ListViewItem) item);
2356 this.Insert (index, item.ToString ());
2359 void IList.Remove (object item)
2361 Remove ((ListViewItem) item);
2364 public int IndexOf (ListViewItem item)
2366 return list.IndexOf (item);
2369 public ListViewItem Insert (int index, ListViewItem item)
2371 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2372 // but it's really only greater.
2373 if (index < 0 || index > list.Count)
2374 throw new ArgumentOutOfRangeException ("Index out of range.");
2376 if (list.Contains (item))
2377 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2380 list.Insert (index, item);
2381 owner.Redraw (true);
2385 public ListViewItem Insert (int index, string text)
2387 return this.Insert (index, new ListViewItem (text));
2390 public ListViewItem Insert (int index, string text, int imageIndex)
2392 return this.Insert (index, new ListViewItem (text, imageIndex));
2395 public virtual void Remove (ListViewItem item)
2397 if (!list.Contains (item))
2400 owner.SelectedItems.list.Remove (item);
2401 owner.SelectedIndices.list.Remove (item.Index);
2402 owner.CheckedItems.list.Remove (item);
2403 owner.CheckedIndices.list.Remove (item.Index);
2405 owner.Redraw (true);
2408 public virtual void RemoveAt (int index)
2410 if (index < 0 || index >= list.Count)
2411 throw new ArgumentOutOfRangeException ("Index out of range.");
2413 list.RemoveAt (index);
2414 owner.SelectedItems.list.RemoveAt (index);
2415 owner.SelectedIndices.list.RemoveAt (index);
2416 owner.CheckedItems.list.RemoveAt (index);
2417 owner.CheckedIndices.list.RemoveAt (index);
2418 owner.Redraw (false);
2420 #endregion // Public Methods
2422 } // ListViewItemCollection
2424 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2426 internal ArrayList list;
2427 private ListView owner;
2429 #region Public Constructor
2430 public SelectedIndexCollection (ListView owner)
2432 list = new ArrayList ();
2435 #endregion // Public Constructor
2437 #region Public Properties
2439 public virtual int Count {
2440 get { return list.Count; }
2443 public virtual bool IsReadOnly {
2444 get { return true; }
2447 public int this [int index] {
2449 if (index < 0 || index >= list.Count)
2450 throw new ArgumentOutOfRangeException ("Index out of range.");
2451 return (int) list [index];
2455 bool ICollection.IsSynchronized {
2456 get { return list.IsSynchronized; }
2459 object ICollection.SyncRoot {
2460 get { return this; }
2463 bool IList.IsFixedSize {
2464 get { return true; }
2467 object IList.this [int index] {
2468 get { return this [index]; }
2469 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2471 #endregion // Public Properties
2473 #region Public Methods
2474 public bool Contains (int selectedIndex)
2476 return list.Contains (selectedIndex);
2479 public virtual void CopyTo (Array dest, int index)
2481 list.CopyTo (dest, index);
2484 public virtual IEnumerator GetEnumerator ()
2486 return list.GetEnumerator ();
2489 int IList.Add (object value)
2491 throw new NotSupportedException ("Add operation is not supported.");
2496 throw new NotSupportedException ("Clear operation is not supported.");
2499 bool IList.Contains (object selectedIndex)
2501 return list.Contains (selectedIndex);
2504 int IList.IndexOf (object selectedIndex)
2506 return list.IndexOf (selectedIndex);
2509 void IList.Insert (int index, object value)
2511 throw new NotSupportedException ("Insert operation is not supported.");
2514 void IList.Remove (object value)
2516 throw new NotSupportedException ("Remove operation is not supported.");
2519 void IList.RemoveAt (int index)
2521 throw new NotSupportedException ("RemoveAt operation is not supported.");
2524 public int IndexOf (int selectedIndex)
2526 return list.IndexOf (selectedIndex);
2528 #endregion // Public Methods
2530 } // SelectedIndexCollection
2532 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2534 internal ArrayList list;
2535 private ListView owner;
2537 #region Public Constructor
2538 public SelectedListViewItemCollection (ListView owner)
2540 list = new ArrayList ();
2543 #endregion // Public Constructor
2545 #region Public Properties
2547 public virtual int Count {
2548 get { return list.Count; }
2551 public virtual bool IsReadOnly {
2552 get { return true; }
2555 public ListViewItem this [int index] {
2557 if (index < 0 || index >= list.Count)
2558 throw new ArgumentOutOfRangeException ("Index out of range.");
2559 return (ListViewItem) list [index];
2563 bool ICollection.IsSynchronized {
2564 get { return list.IsSynchronized; }
2567 object ICollection.SyncRoot {
2568 get { return this; }
2571 bool IList.IsFixedSize {
2572 get { return true; }
2575 object IList.this [int index] {
2576 get { return this [index]; }
2577 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2579 #endregion // Public Properties
2581 #region Public Methods
2582 public virtual void Clear ()
2584 ArrayList copy = (ArrayList) list.Clone ();
2585 for (int i = 0; i < copy.Count; i++)
2586 ((ListViewItem) copy [i]).Selected = false;
2591 public bool Contains (ListViewItem item)
2593 return list.Contains (item);
2596 public virtual void CopyTo (Array dest, int index)
2598 list.CopyTo (dest, index);
2601 public virtual IEnumerator GetEnumerator ()
2603 return list.GetEnumerator ();
2606 int IList.Add (object value)
2608 throw new NotSupportedException ("Add operation is not supported.");
2611 bool IList.Contains (object item)
2613 return list.Contains (item);
2616 int IList.IndexOf (object item)
2618 return list.IndexOf (item);
2621 void IList.Insert (int index, object value)
2623 throw new NotSupportedException ("Insert operation is not supported.");
2626 void IList.Remove (object value)
2628 throw new NotSupportedException ("Remove operation is not supported.");
2631 void IList.RemoveAt (int index)
2633 throw new NotSupportedException ("RemoveAt operation is not supported.");
2636 public int IndexOf (ListViewItem item)
2638 return list.IndexOf (item);
2640 #endregion // Public Methods
2642 } // SelectedListViewItemCollection
2644 #endregion // Subclasses