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;
1162 bool hover_processed = false;
1164 public ItemControl (ListView owner)
1167 DoubleClick += new EventHandler(ItemsDoubleClick);
1168 KeyDown += new KeyEventHandler (ItemsKeyDown);
1169 KeyUp += new KeyEventHandler (ItemsKeyUp);
1170 MouseDown += new MouseEventHandler(ItemsMouseDown);
1171 MouseMove += new MouseEventHandler(ItemsMouseMove);
1172 MouseHover += new EventHandler(ItemsMouseHover);
1173 MouseUp += new MouseEventHandler(ItemsMouseUp);
1174 Paint += new PaintEventHandler (ItemsPaint);
1177 void ItemsDoubleClick (object sender, EventArgs e)
1179 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1180 owner.ItemActivate (this, e);
1183 void ItemsKeyDown (object sender, KeyEventArgs args)
1185 owner.OnKeyDown (args);
1188 void ItemsKeyUp (object sender, KeyEventArgs args)
1190 owner.OnKeyUp (args);
1193 private void ItemsMouseDown (object sender, MouseEventArgs me)
1195 if (owner.items.Count == 0)
1198 Point pt = new Point (me.X, me.Y);
1199 foreach (ListViewItem item in owner.items) {
1200 if (item.CheckRectReal.Contains (pt)) {
1201 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1202 item.Checked = !item.Checked;
1204 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1206 // Raise the ItemCheck event
1207 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1208 owner.OnItemCheck (ice);
1212 if (owner.View == View.Details && !owner.FullRowSelect) {
1213 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1214 clicked_item = item;
1218 if (item.Bounds.Contains (pt)) {
1219 clicked_item = item;
1225 owner.SetFocusedItem (clicked_item);
1227 if (clicked_item != null) {
1228 bool changed = !clicked_item.Selected;
1229 if (owner.MultiSelect && (XplatUI.State.ModifierKeys & Keys.Control) == 0)
1230 owner.UpdateMultiSelection (clicked_item.Index);
1232 clicked_item.Selected = true;
1235 owner.OnSelectedIndexChanged (EventArgs.Empty);
1237 // Raise double click if the item was clicked. On MS the
1238 // double click is only raised if you double click an item
1239 if (me.Clicks > 1 && clicked_item != null)
1240 owner.OnDoubleClick (EventArgs.Empty);
1241 else if (me.Clicks == 1 && clicked_item != null)
1242 owner.OnClick (EventArgs.Empty);
1243 } else if (owner.selected_indices.Count > 0) {
1244 // Raise the event if there was at least one item
1245 // selected and the user click on a dead area (unselecting all)
1246 owner.SelectedItems.Clear ();
1247 owner.SelectedIndices.list.Clear ();
1248 owner.OnSelectedIndexChanged (EventArgs.Empty);
1252 private void ItemsMouseMove (object sender, MouseEventArgs me)
1254 if (owner.HoverSelection && hover_processed) {
1256 Point pt = PointToClient (Control.MousePosition);
1257 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1258 if (item == null || item.Selected)
1261 hover_processed = false;
1262 XplatUI.ResetMouseHover (Handle);
1267 private void ItemsMouseHover (object sender, EventArgs e)
1269 if (Capture || !owner.HoverSelection)
1272 hover_processed = true;
1273 Point pt = PointToClient (Control.MousePosition);
1274 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1279 item.Selected = true;
1280 owner.OnSelectedIndexChanged (new EventArgs ());
1283 private void ItemsMouseUp (object sender, MouseEventArgs me)
1286 if (owner.Items.Count == 0)
1289 Point pt = new Point (me.X, me.Y);
1291 Rectangle rect = Rectangle.Empty;
1292 if (clicked_item != null) {
1293 if (owner.view == View.Details && !owner.full_row_select)
1294 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1296 rect = clicked_item.Bounds;
1298 if (rect.Contains (pt)) {
1299 switch (owner.activation) {
1300 case ItemActivation.OneClick:
1301 owner.OnItemActivate (EventArgs.Empty);
1304 case ItemActivation.TwoClick:
1305 if (last_clicked_item == clicked_item) {
1306 owner.OnItemActivate (EventArgs.Empty);
1307 last_clicked_item = null;
1309 last_clicked_item = clicked_item;
1312 // DoubleClick activation is handled in another handler
1318 clicked_item = null;
1321 private void ItemsPaint (object sender, PaintEventArgs pe)
1323 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1327 private void ListView_Paint (object sender, PaintEventArgs pe)
1329 if (Width <= 0 || Height <= 0 || !Visible || updating)
1332 CalculateScrollBars ();
1335 private void ListView_SizeChanged (object sender, EventArgs e)
1337 CalculateListView (alignment);
1340 private void SetFocusedItem (ListViewItem item)
1342 if (focused_item != null)
1343 focused_item.Focused = false;
1346 item.Focused = true;
1348 focused_item = item;
1351 private void HorizontalScroller (object sender, EventArgs e)
1353 // Avoid unnecessary flickering, when button is
1354 // kept pressed at the end
1355 if (h_marker != h_scroll.Value) {
1357 int pixels = h_marker - h_scroll.Value;
1359 h_marker = h_scroll.Value;
1360 if (header_control.Visible)
1361 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1363 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1367 private void VerticalScroller (object sender, EventArgs e)
1369 // Avoid unnecessary flickering, when button is
1370 // kept pressed at the end
1371 if (v_marker != v_scroll.Value) {
1372 int pixels = v_marker - v_scroll.Value;
1373 Rectangle area = item_control.ClientRectangle;
1374 v_marker = v_scroll.Value;
1375 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1378 #endregion // Internal Methods Properties
1380 #region Protected Methods
1381 protected override void CreateHandle ()
1383 base.CreateHandle ();
1386 protected override void Dispose (bool disposing)
1389 h_scroll.Dispose ();
1390 v_scroll.Dispose ();
1392 large_image_list = null;
1393 small_image_list = null;
1394 state_image_list = null;
1397 base.Dispose (disposing);
1400 protected override bool IsInputKey (Keys keyData)
1417 return base.IsInputKey (keyData);
1420 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1422 if (AfterLabelEdit != null)
1423 AfterLabelEdit (this, e);
1426 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1428 if (BeforeLabelEdit != null)
1429 BeforeLabelEdit (this, e);
1432 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1434 if (ColumnClick != null)
1435 ColumnClick (this, e);
1438 protected override void OnEnabledChanged (EventArgs e)
1440 base.OnEnabledChanged (e);
1443 protected override void OnFontChanged (EventArgs e)
1445 base.OnFontChanged (e);
1449 protected override void OnHandleCreated (EventArgs e)
1451 base.OnHandleCreated (e);
1453 Controls.AddImplicit (header_control);
1454 Controls.AddImplicit (item_control);
1455 Controls.AddImplicit (this.v_scroll);
1456 Controls.AddImplicit (this.h_scroll);
1460 protected override void OnHandleDestroyed (EventArgs e)
1462 base.OnHandleDestroyed (e);
1465 protected virtual void OnItemActivate (EventArgs e)
1467 if (ItemActivate != null)
1468 ItemActivate (this, e);
1471 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1473 if (ItemCheck != null)
1474 ItemCheck (this, ice);
1477 protected virtual void OnItemDrag (ItemDragEventArgs e)
1479 if (ItemDrag != null)
1483 protected virtual void OnSelectedIndexChanged (EventArgs e)
1485 if (SelectedIndexChanged != null)
1486 SelectedIndexChanged (this, e);
1489 protected override void OnSystemColorsChanged (EventArgs e)
1491 base.OnSystemColorsChanged (e);
1494 protected void RealizeProperties ()
1499 protected void UpdateExtendedStyles ()
1504 protected override void WndProc (ref Message m)
1506 base.WndProc (ref m);
1508 #endregion // Protected Methods
1510 #region Public Instance Methods
1511 public void ArrangeIcons ()
1513 ArrangeIcons (this.alignment);
1516 public void ArrangeIcons (ListViewAlignment alignment)
1518 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1519 if (view == View.LargeIcon || view == View.SmallIcon) {
1520 this.CalculateListView (alignment);
1521 // we have done the calculations already
1522 this.Redraw (false);
1526 public void BeginUpdate ()
1528 // flag to avoid painting
1532 public void Clear ()
1535 items.Clear (); // Redraw (true) called here
1538 public void EndUpdate ()
1540 // flag to avoid painting
1543 // probably, now we need a redraw with recalculations
1547 public void EnsureVisible (int index)
1549 if (index < 0 || index >= items.Count || scrollable == false)
1552 Rectangle view_rect = item_control.ClientRectangle;
1553 Rectangle bounds = items [index].Bounds;
1555 if (view_rect.Contains (bounds))
1558 if (bounds.Left < 0)
1559 h_scroll.Value += bounds.Left;
1560 else if (bounds.Right > view_rect.Right)
1561 h_scroll.Value += (bounds.Right - view_rect.Right);
1564 v_scroll.Value += bounds.Top;
1565 else if (bounds.Bottom > view_rect.Bottom)
1566 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1569 public ListViewItem GetItemAt (int x, int y)
1571 foreach (ListViewItem item in items) {
1572 if (item.Bounds.Contains (x, y))
1578 public Rectangle GetItemRect (int index)
1580 return GetItemRect (index, ItemBoundsPortion.Entire);
1583 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1585 if (index < 0 || index >= items.Count)
1586 throw new IndexOutOfRangeException ("Invalid Index");
1588 return items [index].GetBounds (portion);
1593 if (sort_order != SortOrder.None)
1594 items.list.Sort (item_sorter);
1596 if (sort_order == SortOrder.Descending)
1597 items.list.Reverse ();
1602 public override string ToString ()
1604 int count = this.Items.Count;
1607 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1609 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1611 #endregion // Public Instance Methods
1616 class HeaderControl : Control {
1619 bool column_resize_active = false;
1620 ColumnHeader resize_column;
1621 ColumnHeader clicked_column;
1622 ColumnHeader drag_column;
1624 int drag_to_index = -1;
1626 public HeaderControl (ListView owner)
1629 MouseDown += new MouseEventHandler (HeaderMouseDown);
1630 MouseMove += new MouseEventHandler (HeaderMouseMove);
1631 MouseUp += new MouseEventHandler (HeaderMouseUp);
1632 Paint += new PaintEventHandler (HeaderPaint);
1635 private ColumnHeader ColumnAtX (int x)
1637 Point pt = new Point (x, 0);
1638 ColumnHeader result = null;
1639 foreach (ColumnHeader col in owner.Columns) {
1640 if (col.Rect.Contains (pt)) {
1648 private int GetReorderedIndex (ColumnHeader col)
1650 if (owner.reordered_column_indices == null)
1653 for (int i = 0; i < owner.Columns.Count; i++)
1654 if (owner.reordered_column_indices [i] == col.Index)
1656 throw new Exception ("Column index missing from reordered array");
1659 private void HeaderMouseDown (object sender, MouseEventArgs me)
1661 if (resize_column != null) {
1662 column_resize_active = true;
1667 clicked_column = ColumnAtX (me.X + owner.h_marker);
1669 if (clicked_column != null) {
1671 if (owner.AllowColumnReorder) {
1673 drag_column = (ColumnHeader) clicked_column.Clone ();
1674 drag_column.column_rect = clicked_column.Rect;
1675 drag_to_index = GetReorderedIndex (clicked_column);
1677 clicked_column.pressed = true;
1678 Rectangle bounds = clicked_column.Rect;
1679 bounds.X -= owner.h_marker;
1680 Invalidate (bounds);
1685 private void HeaderMouseMove (object sender, MouseEventArgs me)
1687 Point pt = new Point (me.X + owner.h_marker, me.Y);
1689 if (column_resize_active) {
1690 resize_column.Width = pt.X - resize_column.X;
1691 if (resize_column.Width < 0)
1692 resize_column.Width = 0;
1696 resize_column = null;
1698 if (clicked_column != null) {
1699 if (owner.AllowColumnReorder) {
1702 r = drag_column.column_rect;
1703 r.X = clicked_column.Rect.X + me.X - drag_x;
1704 drag_column.column_rect = r;
1706 int x = me.X + owner.h_marker;
1707 ColumnHeader over = ColumnAtX (x);
1708 if (x < over.X + over.Width / 2)
1709 drag_to_index = GetReorderedIndex (over);
1711 drag_to_index = GetReorderedIndex (over) + 1;
1714 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1715 bool pressed = clicked_column.pressed;
1716 clicked_column.pressed = over == clicked_column;
1717 if (clicked_column.pressed ^ pressed) {
1718 Rectangle bounds = clicked_column.Rect;
1719 bounds.X -= owner.h_marker;
1720 Invalidate (bounds);
1726 for (int i = 0; i < owner.Columns.Count; i++) {
1727 Rectangle zone = owner.Columns [i].Rect;
1728 zone.X = zone.Right - 5;
1730 if (zone.Contains (pt)) {
1731 resize_column = owner.Columns [i];
1736 if (resize_column == null)
1737 Cursor = Cursors.Default;
1739 Cursor = Cursors.VSplit;
1742 void HeaderMouseUp (object sender, MouseEventArgs me)
1746 if (column_resize_active) {
1747 column_resize_active = false;
1748 resize_column = null;
1749 Cursor = Cursors.Default;
1753 if (clicked_column != null && clicked_column.pressed) {
1754 clicked_column.pressed = false;
1755 Rectangle bounds = clicked_column.Rect;
1756 bounds.X -= owner.h_marker;
1757 Invalidate (bounds);
1758 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1761 if (drag_column != null && owner.AllowColumnReorder) {
1763 if (drag_to_index > GetReorderedIndex (clicked_column))
1765 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1766 owner.ReorderColumn (clicked_column, drag_to_index);
1771 clicked_column = null;
1774 void HeaderPaint (object sender, PaintEventArgs pe)
1776 if (Width <= 0 || Height <= 0 || !Visible || owner.updating)
1779 Theme theme = ThemeEngine.Current;
1780 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1782 if (drag_column == null)
1786 if (drag_to_index == owner.Columns.Count)
1787 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1789 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1790 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1795 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1797 internal ArrayList list;
1798 private ListView owner;
1800 #region Public Constructor
1801 public CheckedIndexCollection (ListView owner)
1803 list = new ArrayList ();
1806 #endregion // Public Constructor
1808 #region Public Properties
1810 public virtual int Count {
1811 get { return list.Count; }
1814 public virtual bool IsReadOnly {
1815 get { return true; }
1818 public int this [int index] {
1820 if (index < 0 || index >= list.Count)
1821 throw new ArgumentOutOfRangeException ("Index out of range.");
1822 return (int) list [index];
1826 bool ICollection.IsSynchronized {
1827 get { return false; }
1830 object ICollection.SyncRoot {
1831 get { return this; }
1834 bool IList.IsFixedSize {
1835 get { return true; }
1838 object IList.this [int index] {
1839 get { return this [index]; }
1840 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1842 #endregion // Public Properties
1844 #region Public Methods
1845 public bool Contains (int checkedIndex)
1847 return list.Contains (checkedIndex);
1850 public virtual IEnumerator GetEnumerator ()
1852 return list.GetEnumerator ();
1855 void ICollection.CopyTo (Array dest, int index)
1857 list.CopyTo (dest, index);
1860 int IList.Add (object value)
1862 throw new NotSupportedException ("Add operation is not supported.");
1867 throw new NotSupportedException ("Clear operation is not supported.");
1870 bool IList.Contains (object checkedIndex)
1872 return list.Contains (checkedIndex);
1875 int IList.IndexOf (object checkedIndex)
1877 return list.IndexOf (checkedIndex);
1880 void IList.Insert (int index, object value)
1882 throw new NotSupportedException ("Insert operation is not supported.");
1885 void IList.Remove (object value)
1887 throw new NotSupportedException ("Remove operation is not supported.");
1890 void IList.RemoveAt (int index)
1892 throw new NotSupportedException ("RemoveAt operation is not supported.");
1895 public int IndexOf (int checkedIndex)
1897 return list.IndexOf (checkedIndex);
1899 #endregion // Public Methods
1901 } // CheckedIndexCollection
1903 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1905 internal ArrayList list;
1906 private ListView owner;
1908 #region Public Constructor
1909 public CheckedListViewItemCollection (ListView owner)
1911 list = new ArrayList ();
1914 #endregion // Public Constructor
1916 #region Public Properties
1918 public virtual int Count {
1919 get { return list.Count; }
1922 public virtual bool IsReadOnly {
1923 get { return true; }
1926 public ListViewItem this [int index] {
1928 if (index < 0 || index >= list.Count)
1929 throw new ArgumentOutOfRangeException ("Index out of range.");
1930 return (ListViewItem) list [index];
1934 bool ICollection.IsSynchronized {
1935 get { return list.IsSynchronized; }
1938 object ICollection.SyncRoot {
1939 get { return this; }
1942 bool IList.IsFixedSize {
1943 get { return true; }
1946 object IList.this [int index] {
1947 get { return this [index]; }
1948 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1950 #endregion // Public Properties
1952 #region Public Methods
1953 public bool Contains (ListViewItem item)
1955 return list.Contains (item);
1958 public virtual void CopyTo (Array dest, int index)
1960 list.CopyTo (dest, index);
1963 public virtual IEnumerator GetEnumerator ()
1965 return list.GetEnumerator ();
1968 int IList.Add (object value)
1970 throw new NotSupportedException ("Add operation is not supported.");
1975 throw new NotSupportedException ("Clear operation is not supported.");
1978 bool IList.Contains (object item)
1980 return list.Contains (item);
1983 int IList.IndexOf (object item)
1985 return list.IndexOf (item);
1988 void IList.Insert (int index, object value)
1990 throw new NotSupportedException ("Insert operation is not supported.");
1993 void IList.Remove (object value)
1995 throw new NotSupportedException ("Remove operation is not supported.");
1998 void IList.RemoveAt (int index)
2000 throw new NotSupportedException ("RemoveAt operation is not supported.");
2003 public int IndexOf (ListViewItem item)
2005 return list.IndexOf (item);
2007 #endregion // Public Methods
2009 } // CheckedListViewItemCollection
2011 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
2013 internal ArrayList list;
2014 private ListView owner;
2016 #region Public Constructor
2017 public ColumnHeaderCollection (ListView owner)
2019 list = new ArrayList ();
2022 #endregion // Public Constructor
2024 #region Public Properties
2026 public virtual int Count {
2027 get { return list.Count; }
2030 public virtual bool IsReadOnly {
2031 get { return false; }
2034 public virtual ColumnHeader this [int index] {
2036 if (index < 0 || index >= list.Count)
2037 throw new ArgumentOutOfRangeException ("Index out of range.");
2038 return (ColumnHeader) list [index];
2042 bool ICollection.IsSynchronized {
2043 get { return true; }
2046 object ICollection.SyncRoot {
2047 get { return this; }
2050 bool IList.IsFixedSize {
2051 get { return list.IsFixedSize; }
2054 object IList.this [int index] {
2055 get { return this [index]; }
2056 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2058 #endregion // Public Properties
2060 #region Public Methods
2061 public virtual int Add (ColumnHeader value)
2064 value.owner = this.owner;
2065 idx = list.Add (value);
2066 owner.Redraw (true);
2070 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
2072 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2073 this.Add (colHeader);
2077 public virtual void AddRange (ColumnHeader [] values)
2079 foreach (ColumnHeader colHeader in values) {
2080 colHeader.owner = this.owner;
2084 owner.Redraw (true);
2087 public virtual void Clear ()
2090 owner.Redraw (true);
2093 public bool Contains (ColumnHeader value)
2095 return list.Contains (value);
2098 public virtual IEnumerator GetEnumerator ()
2100 return list.GetEnumerator ();
2103 void ICollection.CopyTo (Array dest, int index)
2105 list.CopyTo (dest, index);
2108 int IList.Add (object value)
2110 if (! (value is ColumnHeader)) {
2111 throw new ArgumentException ("Not of type ColumnHeader", "value");
2114 return this.Add ((ColumnHeader) value);
2117 bool IList.Contains (object value)
2119 if (! (value is ColumnHeader)) {
2120 throw new ArgumentException ("Not of type ColumnHeader", "value");
2123 return this.Contains ((ColumnHeader) value);
2126 int IList.IndexOf (object value)
2128 if (! (value is ColumnHeader)) {
2129 throw new ArgumentException ("Not of type ColumnHeader", "value");
2132 return this.IndexOf ((ColumnHeader) value);
2135 void IList.Insert (int index, object value)
2137 if (! (value is ColumnHeader)) {
2138 throw new ArgumentException ("Not of type ColumnHeader", "value");
2141 this.Insert (index, (ColumnHeader) value);
2144 void IList.Remove (object value)
2146 if (! (value is ColumnHeader)) {
2147 throw new ArgumentException ("Not of type ColumnHeader", "value");
2150 this.Remove ((ColumnHeader) value);
2153 public int IndexOf (ColumnHeader value)
2155 return list.IndexOf (value);
2158 public void Insert (int index, ColumnHeader value)
2160 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2161 // but it's really only greater.
2162 if (index < 0 || index > list.Count)
2163 throw new ArgumentOutOfRangeException ("Index out of range.");
2165 value.owner = this.owner;
2166 list.Insert (index, value);
2167 owner.Redraw (true);
2170 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2172 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2173 this.Insert (index, colHeader);
2176 public virtual void Remove (ColumnHeader column)
2178 // TODO: Update Column internal index ?
2179 list.Remove (column);
2180 owner.Redraw (true);
2183 public virtual void RemoveAt (int index)
2185 if (index < 0 || index >= list.Count)
2186 throw new ArgumentOutOfRangeException ("Index out of range.");
2188 // TODO: Update Column internal index ?
2189 list.RemoveAt (index);
2190 owner.Redraw (true);
2192 #endregion // Public Methods
2195 } // ColumnHeaderCollection
2197 public class ListViewItemCollection : IList, ICollection, IEnumerable
2199 internal ArrayList list;
2200 private ListView owner;
2202 #region Public Constructor
2203 public ListViewItemCollection (ListView owner)
2205 list = new ArrayList ();
2208 #endregion // Public Constructor
2210 #region Public Properties
2212 public virtual int Count {
2213 get { return list.Count; }
2216 public virtual bool IsReadOnly {
2217 get { return false; }
2220 public virtual ListViewItem this [int displayIndex] {
2222 if (displayIndex < 0 || displayIndex >= list.Count)
2223 throw new ArgumentOutOfRangeException ("Index out of range.");
2224 return (ListViewItem) list [displayIndex];
2228 if (displayIndex < 0 || displayIndex >= list.Count)
2229 throw new ArgumentOutOfRangeException ("Index out of range.");
2231 if (list.Contains (value))
2232 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2234 value.Owner = owner;
2235 list [displayIndex] = value;
2237 owner.Redraw (true);
2241 bool ICollection.IsSynchronized {
2242 get { return true; }
2245 object ICollection.SyncRoot {
2246 get { return this; }
2249 bool IList.IsFixedSize {
2250 get { return list.IsFixedSize; }
2253 object IList.this [int index] {
2254 get { return this [index]; }
2256 if (value is ListViewItem)
2257 this [index] = (ListViewItem) value;
2259 this [index] = new ListViewItem (value.ToString ());
2262 #endregion // Public Properties
2264 #region Public Methods
2265 public virtual ListViewItem Add (ListViewItem value)
2267 if (list.Contains (value))
2268 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2270 value.Owner = owner;
2273 if (owner.Sorting != SortOrder.None)
2276 owner.Redraw (true);
2281 public virtual ListViewItem Add (string text)
2283 ListViewItem item = new ListViewItem (text);
2284 return this.Add (item);
2287 public virtual ListViewItem Add (string text, int imageIndex)
2289 ListViewItem item = new ListViewItem (text, imageIndex);
2290 return this.Add (item);
2293 public void AddRange (ListViewItem [] values)
2296 owner.SelectedItems.list.Clear ();
2297 owner.SelectedIndices.list.Clear ();
2298 owner.CheckedItems.list.Clear ();
2299 owner.CheckedIndices.list.Clear ();
2301 foreach (ListViewItem item in values) {
2306 if (owner.Sorting != SortOrder.None)
2309 owner.Redraw (true);
2312 public virtual void Clear ()
2314 owner.SetFocusedItem (null);
2315 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2317 owner.SelectedItems.list.Clear ();
2318 owner.SelectedIndices.list.Clear ();
2319 owner.CheckedItems.list.Clear ();
2320 owner.CheckedIndices.list.Clear ();
2321 owner.Redraw (true);
2324 public bool Contains (ListViewItem item)
2326 return list.Contains (item);
2329 public virtual void CopyTo (Array dest, int index)
2331 list.CopyTo (dest, index);
2334 public virtual IEnumerator GetEnumerator ()
2336 return list.GetEnumerator ();
2339 int IList.Add (object item)
2344 if (item is ListViewItem) {
2345 li = (ListViewItem) item;
2346 if (list.Contains (li))
2347 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2350 li = new ListViewItem (item.ToString ());
2353 result = list.Add (li);
2354 owner.Redraw (true);
2359 bool IList.Contains (object item)
2361 return list.Contains (item);
2364 int IList.IndexOf (object item)
2366 return list.IndexOf (item);
2369 void IList.Insert (int index, object item)
2371 if (item is ListViewItem)
2372 this.Insert (index, (ListViewItem) item);
2374 this.Insert (index, item.ToString ());
2377 void IList.Remove (object item)
2379 Remove ((ListViewItem) item);
2382 public int IndexOf (ListViewItem item)
2384 return list.IndexOf (item);
2387 public ListViewItem Insert (int index, ListViewItem item)
2389 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2390 // but it's really only greater.
2391 if (index < 0 || index > list.Count)
2392 throw new ArgumentOutOfRangeException ("Index out of range.");
2394 if (list.Contains (item))
2395 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2398 list.Insert (index, item);
2399 owner.Redraw (true);
2403 public ListViewItem Insert (int index, string text)
2405 return this.Insert (index, new ListViewItem (text));
2408 public ListViewItem Insert (int index, string text, int imageIndex)
2410 return this.Insert (index, new ListViewItem (text, imageIndex));
2413 public virtual void Remove (ListViewItem item)
2415 if (!list.Contains (item))
2418 owner.SelectedItems.list.Remove (item);
2419 owner.SelectedIndices.list.Remove (item.Index);
2420 owner.CheckedItems.list.Remove (item);
2421 owner.CheckedIndices.list.Remove (item.Index);
2423 owner.Redraw (true);
2426 public virtual void RemoveAt (int index)
2428 if (index < 0 || index >= list.Count)
2429 throw new ArgumentOutOfRangeException ("Index out of range.");
2431 list.RemoveAt (index);
2432 owner.SelectedItems.list.RemoveAt (index);
2433 owner.SelectedIndices.list.RemoveAt (index);
2434 owner.CheckedItems.list.RemoveAt (index);
2435 owner.CheckedIndices.list.RemoveAt (index);
2436 owner.Redraw (false);
2438 #endregion // Public Methods
2440 } // ListViewItemCollection
2442 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2444 internal ArrayList list;
2445 private ListView owner;
2447 #region Public Constructor
2448 public SelectedIndexCollection (ListView owner)
2450 list = new ArrayList ();
2453 #endregion // Public Constructor
2455 #region Public Properties
2457 public virtual int Count {
2458 get { return list.Count; }
2461 public virtual bool IsReadOnly {
2462 get { return true; }
2465 public int this [int index] {
2467 if (index < 0 || index >= list.Count)
2468 throw new ArgumentOutOfRangeException ("Index out of range.");
2469 return (int) list [index];
2473 bool ICollection.IsSynchronized {
2474 get { return list.IsSynchronized; }
2477 object ICollection.SyncRoot {
2478 get { return this; }
2481 bool IList.IsFixedSize {
2482 get { return true; }
2485 object IList.this [int index] {
2486 get { return this [index]; }
2487 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2489 #endregion // Public Properties
2491 #region Public Methods
2492 public bool Contains (int selectedIndex)
2494 return list.Contains (selectedIndex);
2497 public virtual void CopyTo (Array dest, int index)
2499 list.CopyTo (dest, index);
2502 public virtual IEnumerator GetEnumerator ()
2504 return list.GetEnumerator ();
2507 int IList.Add (object value)
2509 throw new NotSupportedException ("Add operation is not supported.");
2514 throw new NotSupportedException ("Clear operation is not supported.");
2517 bool IList.Contains (object selectedIndex)
2519 return list.Contains (selectedIndex);
2522 int IList.IndexOf (object selectedIndex)
2524 return list.IndexOf (selectedIndex);
2527 void IList.Insert (int index, object value)
2529 throw new NotSupportedException ("Insert operation is not supported.");
2532 void IList.Remove (object value)
2534 throw new NotSupportedException ("Remove operation is not supported.");
2537 void IList.RemoveAt (int index)
2539 throw new NotSupportedException ("RemoveAt operation is not supported.");
2542 public int IndexOf (int selectedIndex)
2544 return list.IndexOf (selectedIndex);
2546 #endregion // Public Methods
2548 } // SelectedIndexCollection
2550 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2552 internal ArrayList list;
2553 private ListView owner;
2555 #region Public Constructor
2556 public SelectedListViewItemCollection (ListView owner)
2558 list = new ArrayList ();
2561 #endregion // Public Constructor
2563 #region Public Properties
2565 public virtual int Count {
2566 get { return list.Count; }
2569 public virtual bool IsReadOnly {
2570 get { return true; }
2573 public ListViewItem this [int index] {
2575 if (index < 0 || index >= list.Count)
2576 throw new ArgumentOutOfRangeException ("Index out of range.");
2577 return (ListViewItem) list [index];
2581 bool ICollection.IsSynchronized {
2582 get { return list.IsSynchronized; }
2585 object ICollection.SyncRoot {
2586 get { return this; }
2589 bool IList.IsFixedSize {
2590 get { return true; }
2593 object IList.this [int index] {
2594 get { return this [index]; }
2595 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2597 #endregion // Public Properties
2599 #region Public Methods
2600 public virtual void Clear ()
2602 ArrayList copy = (ArrayList) list.Clone ();
2603 for (int i = 0; i < copy.Count; i++)
2604 ((ListViewItem) copy [i]).Selected = false;
2609 public bool Contains (ListViewItem item)
2611 return list.Contains (item);
2614 public virtual void CopyTo (Array dest, int index)
2616 list.CopyTo (dest, index);
2619 public virtual IEnumerator GetEnumerator ()
2621 return list.GetEnumerator ();
2624 int IList.Add (object value)
2626 throw new NotSupportedException ("Add operation is not supported.");
2629 bool IList.Contains (object item)
2631 return list.Contains (item);
2634 int IList.IndexOf (object item)
2636 return list.IndexOf (item);
2639 void IList.Insert (int index, object value)
2641 throw new NotSupportedException ("Insert operation is not supported.");
2644 void IList.Remove (object value)
2646 throw new NotSupportedException ("Remove operation is not supported.");
2649 void IList.RemoveAt (int index)
2651 throw new NotSupportedException ("RemoveAt operation is not supported.");
2654 public int IndexOf (ListViewItem item)
2656 return list.IndexOf (item);
2658 #endregion // Public Methods
2660 } // SelectedListViewItemCollection
2662 #endregion // Subclasses