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 Scroll (ScrollBar scrollbar, int delta)
718 if (delta == 0 || !scrollbar.Visible)
722 if (scrollbar == h_scroll)
723 max = h_scroll.Maximum - item_control.Width;
725 max = v_scroll.Maximum - item_control.Height;
727 int val = scrollbar.Value + delta;
730 else if (val < scrollbar.Minimum)
731 val = scrollbar.Minimum;
732 scrollbar.Value = val;
735 private void CalculateScrollBars ()
737 Rectangle client_area = ClientRectangle;
739 if (!this.scrollable || this.items.Count <= 0) {
740 h_scroll.Visible = false;
741 v_scroll.Visible = false;
745 // making a scroll bar visible might make
746 // other scroll bar visible
747 if (layout_wd > client_area.Right) {
748 h_scroll.Visible = true;
749 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
750 v_scroll.Visible = true;
752 v_scroll.Visible = false;
753 } else if (layout_ht > client_area.Bottom) {
754 v_scroll.Visible = true;
755 if ((layout_wd + v_scroll.Width) > client_area.Right)
756 h_scroll.Visible = true;
758 h_scroll.Visible = false;
760 h_scroll.Visible = false;
761 v_scroll.Visible = false;
764 item_control.Height = ClientRectangle.Height - header_control.Height;
766 if (h_scroll.Visible) {
767 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
768 h_scroll.Minimum = 0;
770 // if v_scroll is visible, adjust the maximum of the
771 // h_scroll to account for the width of v_scroll
772 if (v_scroll.Visible) {
773 h_scroll.Maximum = layout_wd + v_scroll.Width;
774 h_scroll.Width = client_area.Width - v_scroll.Width;
777 h_scroll.Maximum = layout_wd;
778 h_scroll.Width = client_area.Width;
781 h_scroll.LargeChange = client_area.Width;
782 h_scroll.SmallChange = Font.Height;
783 item_control.Height -= h_scroll.Height;
786 if (header_control.Visible)
787 header_control.Width = ClientRectangle.Width;
788 item_control.Width = ClientRectangle.Width;
790 if (v_scroll.Visible) {
791 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
792 v_scroll.Minimum = 0;
794 // if h_scroll is visible, adjust the maximum of the
795 // v_scroll to account for the height of h_scroll
796 if (h_scroll.Visible) {
797 v_scroll.Maximum = layout_ht + h_scroll.Height;
798 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
800 v_scroll.Maximum = layout_ht;
801 v_scroll.Height = client_area.Height;
804 v_scroll.LargeChange = client_area.Height;
805 v_scroll.SmallChange = Font.Height;
806 if (header_control.Visible)
807 header_control.Width -= v_scroll.Width;
808 item_control.Width -= v_scroll.Width;
812 ColumnHeader GetReorderedColumn (int index)
814 if (reordered_column_indices == null)
815 return Columns [index];
817 return Columns [reordered_column_indices [index]];
820 void ReorderColumn (ColumnHeader col, int index)
822 if (reordered_column_indices == null) {
823 reordered_column_indices = new int [Columns.Count];
824 for (int i = 0; i < Columns.Count; i++)
825 reordered_column_indices [i] = i;
828 if (reordered_column_indices [index] == col.Index)
831 int[] curr = reordered_column_indices;
832 int[] result = new int [Columns.Count];
834 for (int i = 0; i < Columns.Count; i++) {
835 if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
839 result [i] = col.Index;
841 result [i] = curr [curr_idx++];
844 reordered_column_indices = result;
846 header_control.Invalidate ();
847 item_control.Invalidate ();
850 Size LargeIconItemSize {
852 int w = Math.Max (text_size.Width, 2 + CheckBoxSize.Width + LargeImageList.ImageSize.Width);
853 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, LargeImageList.ImageSize.Height);
854 return new Size (w, h);
858 Size SmallIconItemSize {
860 int w = text_size.Width + 2 + CheckBoxSize.Width + SmallImageList.ImageSize.Width;
861 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, SmallImageList.ImageSize.Height));
862 return new Size (w, h);
868 ListViewItem[,] item_matrix;
870 void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
872 header_control.Visible = false;
873 header_control.Size = Size.Empty;
874 item_control.Location = Point.Empty;
876 if (items.Count == 0)
879 Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
881 Rectangle area = ClientRectangle;
884 rows = (int) Math.Floor ((double)area.Height / (double)(sz.Height + y_spacing));
887 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
889 cols = (int) Math.Floor ((double)area.Width / (double)(sz.Width + x_spacing));
892 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
895 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
896 layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
897 item_matrix = new ListViewItem [rows, cols];
900 foreach (ListViewItem item in items) {
901 int x = col * (sz.Width + x_spacing);
902 int y = row * (sz.Height + y_spacing);
903 item.Location = new Point (x, y);
907 item_matrix [row, col] = item;
921 item_control.Size = new Size (layout_wd, layout_ht);
926 if (columns.Count == 0 || header_style == ColumnHeaderStyle.None) {
927 header_control.Visible = false;
928 header_control.Size = Size.Empty;
933 for (int i = 0; i < Columns.Count; i++) {
934 ColumnHeader col = GetReorderedColumn (i);
937 col.CalcColumnHeader ();
941 header_control.Width = x;
942 header_control.Height = columns [0].Ht;
943 header_control.Visible = true;
946 void LayoutDetails ()
950 item_control.Location = new Point (0, header_control.Height);
953 if (items.Count > 0) {
954 foreach (ListViewItem item in items) {
956 item.Location = new Point (0, y);
957 y += item.Bounds.Height + 2;
960 // some space for bottom gridline
965 layout_wd = Math.Max (header_control.Width, item_control.Width);
966 layout_ht = y + header_control.Height;
969 private void CalculateListView (ListViewAlignment align)
979 LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
983 LayoutIcons (true, alignment == ListViewAlignment.Left,
984 ThemeEngine.Current.ListViewHorizontalSpacing,
985 ThemeEngine.Current.ListViewVerticalSpacing);
989 LayoutIcons (false, true, 4, 2);
993 CalculateScrollBars ();
996 internal void UpdateSelection (ListViewItem item)
1000 if (!CanMultiselect && SelectedItems.Count > 0) {
1001 SelectedItems.Clear ();
1002 SelectedIndices.list.Clear ();
1005 if (!SelectedItems.Contains (item)) {
1006 SelectedItems.list.Add (item);
1007 SelectedIndices.list.Add (item.Index);
1010 SelectedItems.list.Remove (item);
1011 SelectedIndices.list.Remove (item.Index);
1015 private bool KeySearchString (KeyEventArgs ke)
1017 int current_tickcnt = Environment.TickCount;
1018 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
1019 keysearch_text = string.Empty;
1022 keysearch_text += (char) ke.KeyData;
1023 keysearch_tickcnt = current_tickcnt;
1025 int start = FocusedItem == null ? 0 : FocusedItem.Index;
1028 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1029 CompareOptions.IgnoreCase)) {
1030 SetFocusedItem (Items [i]);
1031 items [i].Selected = true;
1035 i = (i + 1 < Items.Count) ? i+1 : 0;
1043 int GetAdjustedIndex (Keys key)
1047 if (View == View.Details) {
1049 result = FocusedItem.Index - 1;
1050 else if (key == Keys.Down) {
1051 result = FocusedItem.Index + 1;
1052 if (result == items.Count)
1058 int row = FocusedItem.row;
1059 int col = FocusedItem.col;
1065 return item_matrix [row, col - 1].Index;
1068 if (col == (cols - 1))
1070 while (item_matrix [row, col + 1] == null)
1072 return item_matrix [row, col + 1].Index;
1077 return item_matrix [row - 1, col].Index;
1080 if (row == (rows - 1))
1082 while (item_matrix [row + 1, col] == null)
1084 return item_matrix [row + 1, col].Index;
1091 ListViewItem selection_start;
1093 private void SelectItems (ArrayList sel_items)
1095 SelectedItems.Clear ();
1096 SelectedIndices.list.Clear ();
1097 foreach (ListViewItem item in sel_items)
1098 item.Selected = true;
1101 private void UpdateMultiSelection (int index)
1103 bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
1104 bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
1105 ListViewItem item = items [index];
1107 if (shift_pressed && selection_start != null) {
1108 ArrayList list = new ArrayList ();
1109 int start = Math.Min (selection_start.Index, index);
1110 int end = Math.Max (selection_start.Index, index);
1111 if (View == View.Details) {
1112 for (int i = start; i <= end; i++)
1113 list.Add (items [i]);
1115 int left = Math.Min (items [start].col, items [end].col);
1116 int right = Math.Max (items [start].col, items [end].col);
1117 int top = Math.Min (items [start].row, items [end].row);
1118 int bottom = Math.Max (items [start].row, items [end].row);
1119 foreach (ListViewItem curr in items)
1120 if (curr.row >= top && curr.row <= bottom &&
1121 curr.col >= left && curr.col <= right)
1125 } else if (!ctrl_pressed) {
1126 SelectedItems.Clear ();
1127 SelectedIndices.list.Clear ();
1128 item.Selected = true;
1129 selection_start = item;
1133 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1135 if (ke.Handled || Items.Count == 0)
1141 switch (ke.KeyCode) {
1144 index = Items.Count - 1;
1155 index = GetAdjustedIndex (ke.KeyCode);
1159 ke.Handled = KeySearchString (ke);
1167 UpdateMultiSelection (index);
1169 items [index].Selected = true;
1171 SetFocusedItem (items [index]);
1172 EnsureVisible (index);
1176 internal class ItemControl : Control {
1179 ListViewItem clicked_item;
1180 ListViewItem last_clicked_item;
1181 bool hover_processed = false;
1183 public ItemControl (ListView owner)
1186 DoubleClick += new EventHandler(ItemsDoubleClick);
1187 KeyDown += new KeyEventHandler (ItemsKeyDown);
1188 KeyUp += new KeyEventHandler (ItemsKeyUp);
1189 MouseDown += new MouseEventHandler(ItemsMouseDown);
1190 MouseMove += new MouseEventHandler(ItemsMouseMove);
1191 MouseHover += new EventHandler(ItemsMouseHover);
1192 MouseUp += new MouseEventHandler(ItemsMouseUp);
1193 MouseWheel += new MouseEventHandler(ItemsMouseWheel);
1194 Paint += new PaintEventHandler (ItemsPaint);
1197 void ItemsDoubleClick (object sender, EventArgs e)
1199 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1200 owner.ItemActivate (this, e);
1203 void ItemsKeyDown (object sender, KeyEventArgs args)
1205 owner.OnKeyDown (args);
1208 void ItemsKeyUp (object sender, KeyEventArgs args)
1210 owner.OnKeyUp (args);
1213 private void ItemsMouseDown (object sender, MouseEventArgs me)
1215 if (owner.items.Count == 0)
1218 Point pt = new Point (me.X, me.Y);
1219 foreach (ListViewItem item in owner.items) {
1220 if (item.CheckRectReal.Contains (pt)) {
1221 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1222 item.Checked = !item.Checked;
1224 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1226 // Raise the ItemCheck event
1227 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1228 owner.OnItemCheck (ice);
1232 if (owner.View == View.Details && !owner.FullRowSelect) {
1233 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1234 clicked_item = item;
1238 if (item.Bounds.Contains (pt)) {
1239 clicked_item = item;
1245 owner.SetFocusedItem (clicked_item);
1247 if (clicked_item != null) {
1248 bool changed = !clicked_item.Selected;
1249 if (owner.MultiSelect && (XplatUI.State.ModifierKeys & Keys.Control) == 0)
1250 owner.UpdateMultiSelection (clicked_item.Index);
1252 clicked_item.Selected = true;
1255 owner.OnSelectedIndexChanged (EventArgs.Empty);
1257 // Raise double click if the item was clicked. On MS the
1258 // double click is only raised if you double click an item
1259 if (me.Clicks > 1 && clicked_item != null)
1260 owner.OnDoubleClick (EventArgs.Empty);
1261 else if (me.Clicks == 1 && clicked_item != null)
1262 owner.OnClick (EventArgs.Empty);
1263 } else if (owner.selected_indices.Count > 0) {
1264 // Raise the event if there was at least one item
1265 // selected and the user click on a dead area (unselecting all)
1266 owner.SelectedItems.Clear ();
1267 owner.SelectedIndices.list.Clear ();
1268 owner.OnSelectedIndexChanged (EventArgs.Empty);
1272 private void ItemsMouseMove (object sender, MouseEventArgs me)
1274 if (owner.HoverSelection && hover_processed) {
1276 Point pt = PointToClient (Control.MousePosition);
1277 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1278 if (item == null || item.Selected)
1281 hover_processed = false;
1282 XplatUI.ResetMouseHover (Handle);
1287 private void ItemsMouseHover (object sender, EventArgs e)
1289 if (Capture || !owner.HoverSelection)
1292 hover_processed = true;
1293 Point pt = PointToClient (Control.MousePosition);
1294 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1299 item.Selected = true;
1300 owner.OnSelectedIndexChanged (new EventArgs ());
1303 private void ItemsMouseUp (object sender, MouseEventArgs me)
1306 if (owner.Items.Count == 0)
1309 Point pt = new Point (me.X, me.Y);
1311 Rectangle rect = Rectangle.Empty;
1312 if (clicked_item != null) {
1313 if (owner.view == View.Details && !owner.full_row_select)
1314 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1316 rect = clicked_item.Bounds;
1318 if (rect.Contains (pt)) {
1319 switch (owner.activation) {
1320 case ItemActivation.OneClick:
1321 owner.OnItemActivate (EventArgs.Empty);
1324 case ItemActivation.TwoClick:
1325 if (last_clicked_item == clicked_item) {
1326 owner.OnItemActivate (EventArgs.Empty);
1327 last_clicked_item = null;
1329 last_clicked_item = clicked_item;
1332 // DoubleClick activation is handled in another handler
1338 clicked_item = null;
1341 private void ItemsMouseWheel (object sender, MouseEventArgs me)
1343 if (owner.Items.Count == 0)
1346 int lines = me.Delta / 120;
1351 switch (owner.View) {
1353 case View.SmallIcon:
1354 owner.Scroll (owner.v_scroll, -owner.Items [0].Bounds.Height * SystemInformation.MouseWheelScrollLines * lines);
1356 case View.LargeIcon:
1357 owner.Scroll (owner.v_scroll, -(owner.Items [0].Bounds.Height + ThemeEngine.Current.ListViewVerticalSpacing) * lines);
1360 owner.Scroll (owner.h_scroll, -owner.Items [0].Bounds.Width * lines);
1365 private void ItemsPaint (object sender, PaintEventArgs pe)
1367 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1371 private void ListView_Paint (object sender, PaintEventArgs pe)
1373 if (Width <= 0 || Height <= 0 || !Visible || updating)
1376 CalculateScrollBars ();
1379 private void ListView_SizeChanged (object sender, EventArgs e)
1381 CalculateListView (alignment);
1384 private void SetFocusedItem (ListViewItem item)
1386 if (focused_item != null)
1387 focused_item.Focused = false;
1390 item.Focused = true;
1392 focused_item = item;
1395 private void HorizontalScroller (object sender, EventArgs e)
1397 // Avoid unnecessary flickering, when button is
1398 // kept pressed at the end
1399 if (h_marker != h_scroll.Value) {
1401 int pixels = h_marker - h_scroll.Value;
1403 h_marker = h_scroll.Value;
1404 if (header_control.Visible)
1405 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1407 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1411 private void VerticalScroller (object sender, EventArgs e)
1413 // Avoid unnecessary flickering, when button is
1414 // kept pressed at the end
1415 if (v_marker != v_scroll.Value) {
1416 int pixels = v_marker - v_scroll.Value;
1417 Rectangle area = item_control.ClientRectangle;
1418 v_marker = v_scroll.Value;
1419 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1422 #endregion // Internal Methods Properties
1424 #region Protected Methods
1425 protected override void CreateHandle ()
1427 base.CreateHandle ();
1430 protected override void Dispose (bool disposing)
1433 h_scroll.Dispose ();
1434 v_scroll.Dispose ();
1436 large_image_list = null;
1437 small_image_list = null;
1438 state_image_list = null;
1441 base.Dispose (disposing);
1444 protected override bool IsInputKey (Keys keyData)
1461 return base.IsInputKey (keyData);
1464 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1466 if (AfterLabelEdit != null)
1467 AfterLabelEdit (this, e);
1470 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1472 if (BeforeLabelEdit != null)
1473 BeforeLabelEdit (this, e);
1476 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1478 if (ColumnClick != null)
1479 ColumnClick (this, e);
1482 protected override void OnEnabledChanged (EventArgs e)
1484 base.OnEnabledChanged (e);
1487 protected override void OnFontChanged (EventArgs e)
1489 base.OnFontChanged (e);
1493 protected override void OnHandleCreated (EventArgs e)
1495 base.OnHandleCreated (e);
1497 Controls.AddImplicit (header_control);
1498 Controls.AddImplicit (item_control);
1499 Controls.AddImplicit (this.v_scroll);
1500 Controls.AddImplicit (this.h_scroll);
1504 protected override void OnHandleDestroyed (EventArgs e)
1506 base.OnHandleDestroyed (e);
1509 protected virtual void OnItemActivate (EventArgs e)
1511 if (ItemActivate != null)
1512 ItemActivate (this, e);
1515 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1517 if (ItemCheck != null)
1518 ItemCheck (this, ice);
1521 protected virtual void OnItemDrag (ItemDragEventArgs e)
1523 if (ItemDrag != null)
1527 protected virtual void OnSelectedIndexChanged (EventArgs e)
1529 if (SelectedIndexChanged != null)
1530 SelectedIndexChanged (this, e);
1533 protected override void OnSystemColorsChanged (EventArgs e)
1535 base.OnSystemColorsChanged (e);
1538 protected void RealizeProperties ()
1543 protected void UpdateExtendedStyles ()
1548 protected override void WndProc (ref Message m)
1550 base.WndProc (ref m);
1552 #endregion // Protected Methods
1554 #region Public Instance Methods
1555 public void ArrangeIcons ()
1557 ArrangeIcons (this.alignment);
1560 public void ArrangeIcons (ListViewAlignment alignment)
1562 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1563 if (view == View.LargeIcon || view == View.SmallIcon) {
1564 this.CalculateListView (alignment);
1565 // we have done the calculations already
1566 this.Redraw (false);
1570 public void BeginUpdate ()
1572 // flag to avoid painting
1576 public void Clear ()
1579 items.Clear (); // Redraw (true) called here
1582 public void EndUpdate ()
1584 // flag to avoid painting
1587 // probably, now we need a redraw with recalculations
1591 public void EnsureVisible (int index)
1593 if (index < 0 || index >= items.Count || scrollable == false)
1596 Rectangle view_rect = item_control.ClientRectangle;
1597 Rectangle bounds = items [index].Bounds;
1599 if (view_rect.Contains (bounds))
1602 if (bounds.Left < 0)
1603 h_scroll.Value += bounds.Left;
1604 else if (bounds.Right > view_rect.Right)
1605 h_scroll.Value += (bounds.Right - view_rect.Right);
1608 v_scroll.Value += bounds.Top;
1609 else if (bounds.Bottom > view_rect.Bottom)
1610 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1613 public ListViewItem GetItemAt (int x, int y)
1615 foreach (ListViewItem item in items) {
1616 if (item.Bounds.Contains (x, y))
1622 public Rectangle GetItemRect (int index)
1624 return GetItemRect (index, ItemBoundsPortion.Entire);
1627 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1629 if (index < 0 || index >= items.Count)
1630 throw new IndexOutOfRangeException ("Invalid Index");
1632 return items [index].GetBounds (portion);
1637 if (sort_order != SortOrder.None)
1638 items.list.Sort (item_sorter);
1640 if (sort_order == SortOrder.Descending)
1641 items.list.Reverse ();
1646 public override string ToString ()
1648 int count = this.Items.Count;
1651 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1653 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1655 #endregion // Public Instance Methods
1660 class HeaderControl : Control {
1663 bool column_resize_active = false;
1664 ColumnHeader resize_column;
1665 ColumnHeader clicked_column;
1666 ColumnHeader drag_column;
1668 int drag_to_index = -1;
1670 public HeaderControl (ListView owner)
1673 MouseDown += new MouseEventHandler (HeaderMouseDown);
1674 MouseMove += new MouseEventHandler (HeaderMouseMove);
1675 MouseUp += new MouseEventHandler (HeaderMouseUp);
1676 Paint += new PaintEventHandler (HeaderPaint);
1679 private ColumnHeader ColumnAtX (int x)
1681 Point pt = new Point (x, 0);
1682 ColumnHeader result = null;
1683 foreach (ColumnHeader col in owner.Columns) {
1684 if (col.Rect.Contains (pt)) {
1692 private int GetReorderedIndex (ColumnHeader col)
1694 if (owner.reordered_column_indices == null)
1697 for (int i = 0; i < owner.Columns.Count; i++)
1698 if (owner.reordered_column_indices [i] == col.Index)
1700 throw new Exception ("Column index missing from reordered array");
1703 private void HeaderMouseDown (object sender, MouseEventArgs me)
1705 if (resize_column != null) {
1706 column_resize_active = true;
1711 clicked_column = ColumnAtX (me.X + owner.h_marker);
1713 if (clicked_column != null) {
1715 if (owner.AllowColumnReorder) {
1717 drag_column = (ColumnHeader) clicked_column.Clone ();
1718 drag_column.column_rect = clicked_column.Rect;
1719 drag_to_index = GetReorderedIndex (clicked_column);
1721 clicked_column.pressed = true;
1722 Rectangle bounds = clicked_column.Rect;
1723 bounds.X -= owner.h_marker;
1724 Invalidate (bounds);
1729 private void HeaderMouseMove (object sender, MouseEventArgs me)
1731 Point pt = new Point (me.X + owner.h_marker, me.Y);
1733 if (column_resize_active) {
1734 resize_column.Width = pt.X - resize_column.X;
1735 if (resize_column.Width < 0)
1736 resize_column.Width = 0;
1740 resize_column = null;
1742 if (clicked_column != null) {
1743 if (owner.AllowColumnReorder) {
1746 r = drag_column.column_rect;
1747 r.X = clicked_column.Rect.X + me.X - drag_x;
1748 drag_column.column_rect = r;
1750 int x = me.X + owner.h_marker;
1751 ColumnHeader over = ColumnAtX (x);
1752 if (x < over.X + over.Width / 2)
1753 drag_to_index = GetReorderedIndex (over);
1755 drag_to_index = GetReorderedIndex (over) + 1;
1758 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1759 bool pressed = clicked_column.pressed;
1760 clicked_column.pressed = over == clicked_column;
1761 if (clicked_column.pressed ^ pressed) {
1762 Rectangle bounds = clicked_column.Rect;
1763 bounds.X -= owner.h_marker;
1764 Invalidate (bounds);
1770 for (int i = 0; i < owner.Columns.Count; i++) {
1771 Rectangle zone = owner.Columns [i].Rect;
1772 zone.X = zone.Right - 5;
1774 if (zone.Contains (pt)) {
1775 resize_column = owner.Columns [i];
1780 if (resize_column == null)
1781 Cursor = Cursors.Default;
1783 Cursor = Cursors.VSplit;
1786 void HeaderMouseUp (object sender, MouseEventArgs me)
1790 if (column_resize_active) {
1791 column_resize_active = false;
1792 resize_column = null;
1793 Cursor = Cursors.Default;
1797 if (clicked_column != null && clicked_column.pressed) {
1798 clicked_column.pressed = false;
1799 Rectangle bounds = clicked_column.Rect;
1800 bounds.X -= owner.h_marker;
1801 Invalidate (bounds);
1802 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1805 if (drag_column != null && owner.AllowColumnReorder) {
1807 if (drag_to_index > GetReorderedIndex (clicked_column))
1809 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1810 owner.ReorderColumn (clicked_column, drag_to_index);
1815 clicked_column = null;
1818 void HeaderPaint (object sender, PaintEventArgs pe)
1820 if (Width <= 0 || Height <= 0 || !Visible || owner.updating)
1823 Theme theme = ThemeEngine.Current;
1824 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1826 if (drag_column == null)
1830 if (drag_to_index == owner.Columns.Count)
1831 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1833 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1834 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1839 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1841 internal ArrayList list;
1842 private ListView owner;
1844 #region Public Constructor
1845 public CheckedIndexCollection (ListView owner)
1847 list = new ArrayList ();
1850 #endregion // Public Constructor
1852 #region Public Properties
1854 public virtual int Count {
1855 get { return list.Count; }
1858 public virtual bool IsReadOnly {
1859 get { return true; }
1862 public int this [int index] {
1864 if (index < 0 || index >= list.Count)
1865 throw new ArgumentOutOfRangeException ("Index out of range.");
1866 return (int) list [index];
1870 bool ICollection.IsSynchronized {
1871 get { return false; }
1874 object ICollection.SyncRoot {
1875 get { return this; }
1878 bool IList.IsFixedSize {
1879 get { return true; }
1882 object IList.this [int index] {
1883 get { return this [index]; }
1884 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1886 #endregion // Public Properties
1888 #region Public Methods
1889 public bool Contains (int checkedIndex)
1891 return list.Contains (checkedIndex);
1894 public virtual IEnumerator GetEnumerator ()
1896 return list.GetEnumerator ();
1899 void ICollection.CopyTo (Array dest, int index)
1901 list.CopyTo (dest, index);
1904 int IList.Add (object value)
1906 throw new NotSupportedException ("Add operation is not supported.");
1911 throw new NotSupportedException ("Clear operation is not supported.");
1914 bool IList.Contains (object checkedIndex)
1916 return list.Contains (checkedIndex);
1919 int IList.IndexOf (object checkedIndex)
1921 return list.IndexOf (checkedIndex);
1924 void IList.Insert (int index, object value)
1926 throw new NotSupportedException ("Insert operation is not supported.");
1929 void IList.Remove (object value)
1931 throw new NotSupportedException ("Remove operation is not supported.");
1934 void IList.RemoveAt (int index)
1936 throw new NotSupportedException ("RemoveAt operation is not supported.");
1939 public int IndexOf (int checkedIndex)
1941 return list.IndexOf (checkedIndex);
1943 #endregion // Public Methods
1945 } // CheckedIndexCollection
1947 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1949 internal ArrayList list;
1950 private ListView owner;
1952 #region Public Constructor
1953 public CheckedListViewItemCollection (ListView owner)
1955 list = new ArrayList ();
1958 #endregion // Public Constructor
1960 #region Public Properties
1962 public virtual int Count {
1963 get { return list.Count; }
1966 public virtual bool IsReadOnly {
1967 get { return true; }
1970 public ListViewItem this [int index] {
1972 if (index < 0 || index >= list.Count)
1973 throw new ArgumentOutOfRangeException ("Index out of range.");
1974 return (ListViewItem) list [index];
1978 bool ICollection.IsSynchronized {
1979 get { return list.IsSynchronized; }
1982 object ICollection.SyncRoot {
1983 get { return this; }
1986 bool IList.IsFixedSize {
1987 get { return true; }
1990 object IList.this [int index] {
1991 get { return this [index]; }
1992 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1994 #endregion // Public Properties
1996 #region Public Methods
1997 public bool Contains (ListViewItem item)
1999 return list.Contains (item);
2002 public virtual void CopyTo (Array dest, int index)
2004 list.CopyTo (dest, index);
2007 public virtual IEnumerator GetEnumerator ()
2009 return list.GetEnumerator ();
2012 int IList.Add (object value)
2014 throw new NotSupportedException ("Add operation is not supported.");
2019 throw new NotSupportedException ("Clear operation is not supported.");
2022 bool IList.Contains (object item)
2024 return list.Contains (item);
2027 int IList.IndexOf (object item)
2029 return list.IndexOf (item);
2032 void IList.Insert (int index, object value)
2034 throw new NotSupportedException ("Insert operation is not supported.");
2037 void IList.Remove (object value)
2039 throw new NotSupportedException ("Remove operation is not supported.");
2042 void IList.RemoveAt (int index)
2044 throw new NotSupportedException ("RemoveAt operation is not supported.");
2047 public int IndexOf (ListViewItem item)
2049 return list.IndexOf (item);
2051 #endregion // Public Methods
2053 } // CheckedListViewItemCollection
2055 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
2057 internal ArrayList list;
2058 private ListView owner;
2060 #region Public Constructor
2061 public ColumnHeaderCollection (ListView owner)
2063 list = new ArrayList ();
2066 #endregion // Public Constructor
2068 #region Public Properties
2070 public virtual int Count {
2071 get { return list.Count; }
2074 public virtual bool IsReadOnly {
2075 get { return false; }
2078 public virtual ColumnHeader this [int index] {
2080 if (index < 0 || index >= list.Count)
2081 throw new ArgumentOutOfRangeException ("Index out of range.");
2082 return (ColumnHeader) list [index];
2086 bool ICollection.IsSynchronized {
2087 get { return true; }
2090 object ICollection.SyncRoot {
2091 get { return this; }
2094 bool IList.IsFixedSize {
2095 get { return list.IsFixedSize; }
2098 object IList.this [int index] {
2099 get { return this [index]; }
2100 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2102 #endregion // Public Properties
2104 #region Public Methods
2105 public virtual int Add (ColumnHeader value)
2108 value.owner = this.owner;
2109 idx = list.Add (value);
2110 owner.Redraw (true);
2114 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
2116 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2117 this.Add (colHeader);
2121 public virtual void AddRange (ColumnHeader [] values)
2123 foreach (ColumnHeader colHeader in values) {
2124 colHeader.owner = this.owner;
2128 owner.Redraw (true);
2131 public virtual void Clear ()
2134 owner.Redraw (true);
2137 public bool Contains (ColumnHeader value)
2139 return list.Contains (value);
2142 public virtual IEnumerator GetEnumerator ()
2144 return list.GetEnumerator ();
2147 void ICollection.CopyTo (Array dest, int index)
2149 list.CopyTo (dest, index);
2152 int IList.Add (object value)
2154 if (! (value is ColumnHeader)) {
2155 throw new ArgumentException ("Not of type ColumnHeader", "value");
2158 return this.Add ((ColumnHeader) value);
2161 bool IList.Contains (object value)
2163 if (! (value is ColumnHeader)) {
2164 throw new ArgumentException ("Not of type ColumnHeader", "value");
2167 return this.Contains ((ColumnHeader) value);
2170 int IList.IndexOf (object value)
2172 if (! (value is ColumnHeader)) {
2173 throw new ArgumentException ("Not of type ColumnHeader", "value");
2176 return this.IndexOf ((ColumnHeader) value);
2179 void IList.Insert (int index, object value)
2181 if (! (value is ColumnHeader)) {
2182 throw new ArgumentException ("Not of type ColumnHeader", "value");
2185 this.Insert (index, (ColumnHeader) value);
2188 void IList.Remove (object value)
2190 if (! (value is ColumnHeader)) {
2191 throw new ArgumentException ("Not of type ColumnHeader", "value");
2194 this.Remove ((ColumnHeader) value);
2197 public int IndexOf (ColumnHeader value)
2199 return list.IndexOf (value);
2202 public void Insert (int index, ColumnHeader value)
2204 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2205 // but it's really only greater.
2206 if (index < 0 || index > list.Count)
2207 throw new ArgumentOutOfRangeException ("Index out of range.");
2209 value.owner = this.owner;
2210 list.Insert (index, value);
2211 owner.Redraw (true);
2214 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2216 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2217 this.Insert (index, colHeader);
2220 public virtual void Remove (ColumnHeader column)
2222 // TODO: Update Column internal index ?
2223 list.Remove (column);
2224 owner.Redraw (true);
2227 public virtual void RemoveAt (int index)
2229 if (index < 0 || index >= list.Count)
2230 throw new ArgumentOutOfRangeException ("Index out of range.");
2232 // TODO: Update Column internal index ?
2233 list.RemoveAt (index);
2234 owner.Redraw (true);
2236 #endregion // Public Methods
2239 } // ColumnHeaderCollection
2241 public class ListViewItemCollection : IList, ICollection, IEnumerable
2243 internal ArrayList list;
2244 private ListView owner;
2246 #region Public Constructor
2247 public ListViewItemCollection (ListView owner)
2249 list = new ArrayList ();
2252 #endregion // Public Constructor
2254 #region Public Properties
2256 public virtual int Count {
2257 get { return list.Count; }
2260 public virtual bool IsReadOnly {
2261 get { return false; }
2264 public virtual ListViewItem this [int displayIndex] {
2266 if (displayIndex < 0 || displayIndex >= list.Count)
2267 throw new ArgumentOutOfRangeException ("Index out of range.");
2268 return (ListViewItem) list [displayIndex];
2272 if (displayIndex < 0 || displayIndex >= list.Count)
2273 throw new ArgumentOutOfRangeException ("Index out of range.");
2275 if (list.Contains (value))
2276 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2278 value.Owner = owner;
2279 list [displayIndex] = value;
2281 owner.Redraw (true);
2285 bool ICollection.IsSynchronized {
2286 get { return true; }
2289 object ICollection.SyncRoot {
2290 get { return this; }
2293 bool IList.IsFixedSize {
2294 get { return list.IsFixedSize; }
2297 object IList.this [int index] {
2298 get { return this [index]; }
2300 if (value is ListViewItem)
2301 this [index] = (ListViewItem) value;
2303 this [index] = new ListViewItem (value.ToString ());
2306 #endregion // Public Properties
2308 #region Public Methods
2309 public virtual ListViewItem Add (ListViewItem value)
2311 if (list.Contains (value))
2312 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2314 value.Owner = owner;
2317 if (owner.Sorting != SortOrder.None)
2320 owner.Redraw (true);
2325 public virtual ListViewItem Add (string text)
2327 ListViewItem item = new ListViewItem (text);
2328 return this.Add (item);
2331 public virtual ListViewItem Add (string text, int imageIndex)
2333 ListViewItem item = new ListViewItem (text, imageIndex);
2334 return this.Add (item);
2337 public void AddRange (ListViewItem [] values)
2340 owner.SelectedItems.list.Clear ();
2341 owner.SelectedIndices.list.Clear ();
2342 owner.CheckedItems.list.Clear ();
2343 owner.CheckedIndices.list.Clear ();
2345 foreach (ListViewItem item in values) {
2350 if (owner.Sorting != SortOrder.None)
2353 owner.Redraw (true);
2356 public virtual void Clear ()
2358 owner.SetFocusedItem (null);
2359 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2361 owner.SelectedItems.list.Clear ();
2362 owner.SelectedIndices.list.Clear ();
2363 owner.CheckedItems.list.Clear ();
2364 owner.CheckedIndices.list.Clear ();
2365 owner.Redraw (true);
2368 public bool Contains (ListViewItem item)
2370 return list.Contains (item);
2373 public virtual void CopyTo (Array dest, int index)
2375 list.CopyTo (dest, index);
2378 public virtual IEnumerator GetEnumerator ()
2380 return list.GetEnumerator ();
2383 int IList.Add (object item)
2388 if (item is ListViewItem) {
2389 li = (ListViewItem) item;
2390 if (list.Contains (li))
2391 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2394 li = new ListViewItem (item.ToString ());
2397 result = list.Add (li);
2398 owner.Redraw (true);
2403 bool IList.Contains (object item)
2405 return list.Contains (item);
2408 int IList.IndexOf (object item)
2410 return list.IndexOf (item);
2413 void IList.Insert (int index, object item)
2415 if (item is ListViewItem)
2416 this.Insert (index, (ListViewItem) item);
2418 this.Insert (index, item.ToString ());
2421 void IList.Remove (object item)
2423 Remove ((ListViewItem) item);
2426 public int IndexOf (ListViewItem item)
2428 return list.IndexOf (item);
2431 public ListViewItem Insert (int index, ListViewItem item)
2433 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2434 // but it's really only greater.
2435 if (index < 0 || index > list.Count)
2436 throw new ArgumentOutOfRangeException ("Index out of range.");
2438 if (list.Contains (item))
2439 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2442 list.Insert (index, item);
2443 owner.Redraw (true);
2447 public ListViewItem Insert (int index, string text)
2449 return this.Insert (index, new ListViewItem (text));
2452 public ListViewItem Insert (int index, string text, int imageIndex)
2454 return this.Insert (index, new ListViewItem (text, imageIndex));
2457 public virtual void Remove (ListViewItem item)
2459 if (!list.Contains (item))
2462 owner.SelectedItems.list.Remove (item);
2463 owner.SelectedIndices.list.Remove (item.Index);
2464 owner.CheckedItems.list.Remove (item);
2465 owner.CheckedIndices.list.Remove (item.Index);
2467 owner.Redraw (true);
2470 public virtual void RemoveAt (int index)
2472 if (index < 0 || index >= list.Count)
2473 throw new ArgumentOutOfRangeException ("Index out of range.");
2475 list.RemoveAt (index);
2476 owner.SelectedItems.list.RemoveAt (index);
2477 owner.SelectedIndices.list.RemoveAt (index);
2478 owner.CheckedItems.list.RemoveAt (index);
2479 owner.CheckedIndices.list.RemoveAt (index);
2480 owner.Redraw (false);
2482 #endregion // Public Methods
2484 } // ListViewItemCollection
2486 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2488 internal ArrayList list;
2489 private ListView owner;
2491 #region Public Constructor
2492 public SelectedIndexCollection (ListView owner)
2494 list = new ArrayList ();
2497 #endregion // Public Constructor
2499 #region Public Properties
2501 public virtual int Count {
2502 get { return list.Count; }
2505 public virtual bool IsReadOnly {
2506 get { return true; }
2509 public int this [int index] {
2511 if (index < 0 || index >= list.Count)
2512 throw new ArgumentOutOfRangeException ("Index out of range.");
2513 return (int) list [index];
2517 bool ICollection.IsSynchronized {
2518 get { return list.IsSynchronized; }
2521 object ICollection.SyncRoot {
2522 get { return this; }
2525 bool IList.IsFixedSize {
2526 get { return true; }
2529 object IList.this [int index] {
2530 get { return this [index]; }
2531 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2533 #endregion // Public Properties
2535 #region Public Methods
2536 public bool Contains (int selectedIndex)
2538 return list.Contains (selectedIndex);
2541 public virtual void CopyTo (Array dest, int index)
2543 list.CopyTo (dest, index);
2546 public virtual IEnumerator GetEnumerator ()
2548 return list.GetEnumerator ();
2551 int IList.Add (object value)
2553 throw new NotSupportedException ("Add operation is not supported.");
2558 throw new NotSupportedException ("Clear operation is not supported.");
2561 bool IList.Contains (object selectedIndex)
2563 return list.Contains (selectedIndex);
2566 int IList.IndexOf (object selectedIndex)
2568 return list.IndexOf (selectedIndex);
2571 void IList.Insert (int index, object value)
2573 throw new NotSupportedException ("Insert operation is not supported.");
2576 void IList.Remove (object value)
2578 throw new NotSupportedException ("Remove operation is not supported.");
2581 void IList.RemoveAt (int index)
2583 throw new NotSupportedException ("RemoveAt operation is not supported.");
2586 public int IndexOf (int selectedIndex)
2588 return list.IndexOf (selectedIndex);
2590 #endregion // Public Methods
2592 } // SelectedIndexCollection
2594 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2596 internal ArrayList list;
2597 private ListView owner;
2599 #region Public Constructor
2600 public SelectedListViewItemCollection (ListView owner)
2602 list = new ArrayList ();
2605 #endregion // Public Constructor
2607 #region Public Properties
2609 public virtual int Count {
2610 get { return list.Count; }
2613 public virtual bool IsReadOnly {
2614 get { return true; }
2617 public ListViewItem this [int index] {
2619 if (index < 0 || index >= list.Count)
2620 throw new ArgumentOutOfRangeException ("Index out of range.");
2621 return (ListViewItem) list [index];
2625 bool ICollection.IsSynchronized {
2626 get { return list.IsSynchronized; }
2629 object ICollection.SyncRoot {
2630 get { return this; }
2633 bool IList.IsFixedSize {
2634 get { return true; }
2637 object IList.this [int index] {
2638 get { return this [index]; }
2639 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2641 #endregion // Public Properties
2643 #region Public Methods
2644 public virtual void Clear ()
2646 ArrayList copy = (ArrayList) list.Clone ();
2647 for (int i = 0; i < copy.Count; i++)
2648 ((ListViewItem) copy [i]).Selected = false;
2653 public bool Contains (ListViewItem item)
2655 return list.Contains (item);
2658 public virtual void CopyTo (Array dest, int index)
2660 list.CopyTo (dest, index);
2663 public virtual IEnumerator GetEnumerator ()
2665 return list.GetEnumerator ();
2668 int IList.Add (object value)
2670 throw new NotSupportedException ("Add operation is not supported.");
2673 bool IList.Contains (object item)
2675 return list.Contains (item);
2678 int IList.IndexOf (object item)
2680 return list.IndexOf (item);
2683 void IList.Insert (int index, object value)
2685 throw new NotSupportedException ("Insert operation is not supported.");
2688 void IList.Remove (object value)
2690 throw new NotSupportedException ("Remove operation is not supported.");
2693 void IList.RemoveAt (int index)
2695 throw new NotSupportedException ("RemoveAt operation is not supported.");
2698 public int IndexOf (ListViewItem item)
2700 return list.IndexOf (item);
2702 #endregion // Public Methods
2704 } // SelectedListViewItemCollection
2706 #endregion // Subclasses