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 {
321 get { return focused_item; }
324 public override Color ForeColor {
326 if (foreground_color.IsEmpty)
327 return ThemeEngine.Current.ColorWindowText;
329 return foreground_color;
331 set { foreground_color = value; }
334 [DefaultValue (false)]
335 public bool FullRowSelect {
336 get { return full_row_select; }
337 set { full_row_select = value; }
340 [DefaultValue (false)]
341 public bool GridLines {
342 get { return grid_lines; }
344 if (grid_lines != value) {
351 [DefaultValue (ColumnHeaderStyle.Clickable)]
352 public ColumnHeaderStyle HeaderStyle {
353 get { return header_style; }
355 if (header_style == value)
359 case ColumnHeaderStyle.Clickable:
360 case ColumnHeaderStyle.Nonclickable:
361 case ColumnHeaderStyle.None:
364 throw new InvalidEnumArgumentException (string.Format
365 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
368 header_style = value;
369 if (view == View.Details)
374 [DefaultValue (true)]
375 public bool HideSelection {
376 get { return hide_selection; }
378 if (hide_selection != value) {
379 hide_selection = value;
385 [DefaultValue (false)]
386 public bool HoverSelection {
387 get { return hover_selection; }
388 set { hover_selection = value; }
391 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
393 [MergableProperty (false)]
394 public ListViewItemCollection Items {
395 get { return items; }
398 [DefaultValue (false)]
399 public bool LabelEdit {
400 get { return label_edit; }
401 set { label_edit = value; }
404 [DefaultValue (true)]
406 public bool LabelWrap {
407 get { return label_wrap; }
409 if (label_wrap != value) {
416 [DefaultValue (null)]
417 public ImageList LargeImageList {
418 get { return large_image_list; }
420 large_image_list = value;
426 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
427 public IComparer ListViewItemSorter {
428 get { return item_sorter; }
429 set { item_sorter = value; }
432 [DefaultValue (true)]
433 public bool MultiSelect {
434 get { return multiselect; }
435 set { multiselect = value; }
438 [DefaultValue (true)]
439 public bool Scrollable {
440 get { return scrollable; }
442 if (scrollable != value) {
450 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
451 public SelectedIndexCollection SelectedIndices {
452 get { return selected_indices; }
456 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
457 public SelectedListViewItemCollection SelectedItems {
458 get { return selected_items; }
461 [DefaultValue (null)]
462 public ImageList SmallImageList {
463 get { return small_image_list; }
465 small_image_list = value;
470 [DefaultValue (SortOrder.None)]
471 public SortOrder Sorting {
472 get { return sort_order; }
474 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
475 value != SortOrder.None) {
476 throw new InvalidEnumArgumentException (string.Format
477 ("Enum argument value '{0}' is not valid for Sorting", value));
480 if (sort_order != value) {
487 [DefaultValue (null)]
488 public ImageList StateImageList {
489 get { return state_image_list; }
491 state_image_list = value;
498 [EditorBrowsable (EditorBrowsableState.Never)]
499 public override string Text {
508 OnTextChanged (EventArgs.Empty);
513 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
514 public ListViewItem TopItem {
517 if (this.items.Count == 0)
519 // if contents are not scrolled
520 // it is the first item
521 else if (h_marker == 0 && v_marker == 0)
522 return this.items [0];
523 // do a hit test for the scrolled position
525 foreach (ListViewItem item in this.items) {
526 if (item.Bounds.X >= 0 && item.Bounds.Y >= 0)
534 [DefaultValue (View.LargeIcon)]
538 if (value != View.Details && value != View.LargeIcon &&
539 value != View.List && value != View.SmallIcon ) {
540 throw new InvalidEnumArgumentException (string.Format
541 ("Enum argument value '{0}' is not valid for View", value));
545 h_scroll.Value = v_scroll.Value = 0;
551 #endregion // Public Instance Properties
553 #region Internal Methods Properties
555 internal int FirstVisibleIndex {
558 if (this.items.Count == 0)
561 if (h_marker == 0 && v_marker == 0)
564 foreach (ListViewItem item in this.items) {
565 if (item.Bounds.Right >= 0 && item.Bounds.Bottom >= 0)
574 internal int LastVisibleIndex {
576 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
577 if (Items[i].Bounds.Y > ClientRectangle.Bottom)
581 return Items.Count - 1;
585 internal int TotalWidth {
586 get { return Math.Max (this.Width, this.layout_wd); }
589 internal int TotalHeight {
590 get { return Math.Max (this.Height, this.layout_ht); }
593 internal void Redraw (bool recalculate)
595 // Avoid calculations when control is being updated
600 CalculateListView (this.alignment);
605 internal Size GetChildColumnSize (int index)
607 Size ret_size = Size.Empty;
608 ColumnHeader col = this.columns [index];
610 if (col.Width == -2) { // autosize = max(items, columnheader)
611 Size size = Size.Ceiling (this.DeviceContext.MeasureString
612 (col.Text, this.Font));
613 ret_size = BiggestItem (index);
614 if (size.Width > ret_size.Width)
617 else { // -1 and all the values < -2 are put under one category
618 ret_size = BiggestItem (index);
619 // fall back to empty columns' width if no subitem is available for a column
620 if (ret_size.IsEmpty) {
621 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
622 if (col.Text.Length > 0)
623 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
624 (col.Text, this.Font)).Height;
626 ret_size.Height = this.Font.Height;
630 // adjust the size for icon and checkbox for 0th column
632 ret_size.Width += (this.CheckBoxSize.Width + 4);
633 if (this.small_image_list != null)
634 ret_size.Width += this.small_image_list.ImageSize.Width;
639 // Returns the size of biggest item text in a column.
640 private Size BiggestItem (int col)
642 Size temp = Size.Empty;
643 Size ret_size = Size.Empty;
645 // 0th column holds the item text, we check the size of
646 // the various subitems falling in that column and get
647 // the biggest one's size.
648 foreach (ListViewItem item in items) {
649 if (col >= item.SubItems.Count)
652 temp = Size.Ceiling (this.DeviceContext.MeasureString
653 (item.SubItems [col].Text, this.Font));
654 if (temp.Width > ret_size.Width)
658 // adjustment for space
659 if (!ret_size.IsEmpty)
665 // Sets the size of the biggest item text as per the view
666 private void CalcTextSize ()
668 // clear the old value
669 text_size = Size.Empty;
671 if (items.Count == 0)
674 text_size = BiggestItem (0);
676 if (view == View.LargeIcon && this.label_wrap) {
677 Size temp = Size.Empty;
678 if (this.check_boxes)
679 temp.Width += 2 * this.CheckBoxSize.Width;
680 if (large_image_list != null)
681 temp.Width += large_image_list.ImageSize.Width;
684 // wrapping is done for two lines only
685 if (text_size.Width > temp.Width) {
686 text_size.Width = temp.Width;
687 text_size.Height *= 2;
690 else if (view == View.List) {
691 // in list view max text shown in determined by the
692 // control width, even if scolling is enabled.
693 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
694 if (this.small_image_list != null)
695 max_wd -= this.small_image_list.ImageSize.Width;
697 if (text_size.Width > max_wd)
698 text_size.Width = max_wd;
701 // we do the default settings, if we have got 0's
702 if (text_size.Height <= 0)
703 text_size.Height = this.Font.Height;
704 if (text_size.Width <= 0)
705 text_size.Width = this.Width;
708 text_size.Width += 4;
709 text_size.Height += 2;
712 private void CalculateScrollBars ()
714 Rectangle client_area = ClientRectangle;
716 if (!this.scrollable || this.items.Count <= 0) {
717 h_scroll.Visible = false;
718 v_scroll.Visible = false;
722 // making a scroll bar visible might make
723 // other scroll bar visible
724 if (layout_wd > client_area.Right) {
725 h_scroll.Visible = true;
726 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
727 v_scroll.Visible = true;
729 v_scroll.Visible = false;
730 } else if (layout_ht > client_area.Bottom) {
731 v_scroll.Visible = true;
732 if ((layout_wd + v_scroll.Width) > client_area.Right)
733 h_scroll.Visible = true;
735 h_scroll.Visible = false;
737 h_scroll.Visible = false;
738 v_scroll.Visible = false;
741 item_control.Height = ClientRectangle.Height - header_control.Height;
743 if (h_scroll.Visible) {
744 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
745 h_scroll.Minimum = 0;
747 // if v_scroll is visible, adjust the maximum of the
748 // h_scroll to account for the width of v_scroll
749 if (v_scroll.Visible) {
750 h_scroll.Maximum = layout_wd + v_scroll.Width;
751 h_scroll.Width = client_area.Width - v_scroll.Width;
754 h_scroll.Maximum = layout_wd;
755 h_scroll.Width = client_area.Width;
758 h_scroll.LargeChange = client_area.Width;
759 h_scroll.SmallChange = Font.Height;
760 item_control.Height -= h_scroll.Height;
763 if (header_control.Visible)
764 header_control.Width = ClientRectangle.Width;
765 item_control.Width = ClientRectangle.Width;
767 if (v_scroll.Visible) {
768 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
769 v_scroll.Minimum = 0;
771 // if h_scroll is visible, adjust the maximum of the
772 // v_scroll to account for the height of h_scroll
773 if (h_scroll.Visible) {
774 v_scroll.Maximum = layout_ht + h_scroll.Height;
775 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
777 v_scroll.Maximum = layout_ht;
778 v_scroll.Height = client_area.Height;
781 v_scroll.LargeChange = client_area.Height;
782 v_scroll.SmallChange = Font.Height;
783 if (header_control.Visible)
784 header_control.Width -= v_scroll.Width;
785 item_control.Width -= v_scroll.Width;
789 ColumnHeader GetReorderedColumn (int index)
791 if (reordered_column_indices == null)
792 return Columns [index];
794 return Columns [reordered_column_indices [index]];
797 void ReorderColumn (ColumnHeader col, int index)
799 if (reordered_column_indices == null) {
800 reordered_column_indices = new int [Columns.Count];
801 for (int i = 0; i < Columns.Count; i++)
802 reordered_column_indices [i] = i;
805 if (reordered_column_indices [index] == col.Index)
808 int[] curr = reordered_column_indices;
809 int[] result = new int [Columns.Count];
811 for (int i = 0; i < Columns.Count; i++) {
812 if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
816 result [i] = col.Index;
818 result [i] = curr [curr_idx++];
821 reordered_column_indices = result;
823 header_control.Invalidate ();
824 item_control.Invalidate ();
827 Size LargeIconItemSize {
829 int w = Math.Max (text_size.Width, 2 + CheckBoxSize.Width + LargeImageList.ImageSize.Width);
830 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, LargeImageList.ImageSize.Height);
831 return new Size (w, h);
835 Size SmallIconItemSize {
837 int w = text_size.Width + 2 + CheckBoxSize.Width + SmallImageList.ImageSize.Width;
838 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, SmallImageList.ImageSize.Height));
839 return new Size (w, h);
845 ListViewItem[,] item_matrix;
847 void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
849 header_control.Visible = false;
850 header_control.Size = Size.Empty;
851 item_control.Location = Point.Empty;
853 if (items.Count == 0)
856 Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
858 Rectangle area = ClientRectangle;
861 rows = (int) Math.Floor ((double)area.Height / (double)(sz.Height + y_spacing));
864 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
866 cols = (int) Math.Floor ((double)area.Width / (double)(sz.Width + x_spacing));
869 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
872 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
873 layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
874 item_matrix = new ListViewItem [rows, cols];
877 foreach (ListViewItem item in items) {
878 int x = col * (sz.Width + x_spacing);
879 int y = row * (sz.Height + y_spacing);
880 item.Location = new Point (x, y);
884 item_matrix [row, col] = item;
898 item_control.Size = new Size (layout_wd, layout_ht);
903 if (columns.Count == 0 || header_style == ColumnHeaderStyle.None) {
904 header_control.Visible = false;
905 header_control.Size = Size.Empty;
910 for (int i = 0; i < Columns.Count; i++) {
911 ColumnHeader col = GetReorderedColumn (i);
914 col.CalcColumnHeader ();
918 header_control.Width = x;
919 header_control.Height = columns [0].Ht;
920 header_control.Visible = true;
923 void LayoutDetails ()
927 item_control.Location = new Point (0, header_control.Height);
930 if (items.Count > 0) {
931 foreach (ListViewItem item in items) {
933 item.Location = new Point (0, y);
934 y += item.Bounds.Height + 2;
937 // some space for bottom gridline
942 layout_wd = Math.Max (header_control.Width, item_control.Width);
943 layout_ht = y + header_control.Height;
946 private void CalculateListView (ListViewAlignment align)
956 LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
960 LayoutIcons (true, alignment == ListViewAlignment.Left,
961 ThemeEngine.Current.ListViewHorizontalSpacing,
962 ThemeEngine.Current.ListViewVerticalSpacing);
966 LayoutIcons (false, true, 4, 2);
970 CalculateScrollBars ();
973 internal void UpdateSelection (ListViewItem item)
977 if (!CanMultiselect && SelectedItems.Count > 0) {
978 SelectedItems.Clear ();
979 SelectedIndices.list.Clear ();
982 if (!SelectedItems.Contains (item)) {
983 SelectedItems.list.Add (item);
984 SelectedIndices.list.Add (item.Index);
987 SelectedItems.list.Remove (item);
988 SelectedIndices.list.Remove (item.Index);
992 private bool KeySearchString (KeyEventArgs ke)
994 int current_tickcnt = Environment.TickCount;
995 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
996 keysearch_text = string.Empty;
999 keysearch_text += (char) ke.KeyData;
1000 keysearch_tickcnt = current_tickcnt;
1002 int start = FocusedItem == null ? 0 : FocusedItem.Index;
1005 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1006 CompareOptions.IgnoreCase)) {
1007 SetFocusedItem (Items [i]);
1008 items [i].Selected = true;
1012 i = (i + 1 < Items.Count) ? i+1 : 0;
1020 int GetAdjustedIndex (Keys key)
1024 if (View == View.Details) {
1026 result = FocusedItem.Index - 1;
1027 else if (key == Keys.Down) {
1028 result = FocusedItem.Index + 1;
1029 if (result == items.Count)
1035 int row = FocusedItem.row;
1036 int col = FocusedItem.col;
1042 return item_matrix [row, col - 1].Index;
1045 if (col == (cols - 1))
1047 while (item_matrix [row, col + 1] == null)
1049 return item_matrix [row, col + 1].Index;
1054 return item_matrix [row - 1, col].Index;
1057 if (row == (rows - 1))
1059 while (item_matrix [row + 1, col] == null)
1061 return item_matrix [row + 1, col].Index;
1068 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1070 if (ke.Handled || Items.Count == 0)
1076 switch (ke.KeyCode) {
1079 index = Items.Count - 1;
1090 index = GetAdjustedIndex (ke.KeyCode);
1094 if (KeySearchString (ke)) {
1103 items [index].Selected = true;
1104 SetFocusedItem (items [index]);
1105 EnsureVisible (index);
1110 internal class ItemControl : Control {
1113 ListViewItem clicked_item;
1114 ListViewItem last_clicked_item;
1116 public ItemControl (ListView owner)
1119 DoubleClick += new EventHandler(ItemsDoubleClick);
1120 KeyDown += new KeyEventHandler (ItemsKeyDown);
1121 KeyUp += new KeyEventHandler (ItemsKeyUp);
1122 MouseDown += new MouseEventHandler(ItemsMouseDown);
1123 MouseHover += new EventHandler(ItemsMouseHover);
1124 MouseUp += new MouseEventHandler(ItemsMouseUp);
1125 Paint += new PaintEventHandler (ItemsPaint);
1128 void ItemsDoubleClick (object sender, EventArgs e)
1130 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1131 owner.ItemActivate (this, e);
1134 void ItemsKeyDown (object sender, KeyEventArgs args)
1136 owner.OnKeyDown (args);
1139 void ItemsKeyUp (object sender, KeyEventArgs args)
1141 owner.OnKeyUp (args);
1144 private void ItemsMouseDown (object sender, MouseEventArgs me)
1146 if (owner.items.Count == 0)
1149 Point pt = new Point (me.X, me.Y);
1150 foreach (ListViewItem item in owner.items) {
1151 if (item.CheckRectReal.Contains (pt)) {
1152 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1153 item.Checked = !item.Checked;
1155 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1157 // Raise the ItemCheck event
1158 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1159 owner.OnItemCheck (ice);
1163 if (owner.View == View.Details && !owner.FullRowSelect) {
1164 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1165 clicked_item = item;
1169 if (item.Bounds.Contains (pt)) {
1170 clicked_item = item;
1176 owner.SetFocusedItem (clicked_item);
1178 if (clicked_item != null) {
1179 bool changed = !clicked_item.Selected;
1180 clicked_item.Selected = true;;
1183 owner.OnSelectedIndexChanged (EventArgs.Empty);
1185 // Raise double click if the item was clicked. On MS the
1186 // double click is only raised if you double click an item
1187 if (me.Clicks > 1 && clicked_item != null)
1188 owner.OnDoubleClick (EventArgs.Empty);
1189 else if (me.Clicks == 1 && clicked_item != null)
1190 owner.OnClick (EventArgs.Empty);
1191 } else if (owner.selected_indices.Count > 0) {
1192 // Raise the event if there was at least one item
1193 // selected and the user click on a dead area (unselecting all)
1194 owner.SelectedItems.Clear ();
1195 owner.SelectedIndices.list.Clear ();
1196 owner.OnSelectedIndexChanged (EventArgs.Empty);
1200 private void ItemsMouseHover (object sender, EventArgs e)
1202 if (Capture || !owner.hover_selection)
1205 Point pt = PointToClient (Control.MousePosition);
1206 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1211 item.Selected = true;
1212 owner.OnSelectedIndexChanged (new EventArgs ());
1215 private void ItemsMouseUp (object sender, MouseEventArgs me)
1218 if (owner.Items.Count == 0)
1221 Point pt = new Point (me.X, me.Y);
1223 Rectangle rect = Rectangle.Empty;
1224 if (clicked_item != null) {
1225 if (owner.view == View.Details && !owner.full_row_select)
1226 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1228 rect = clicked_item.Bounds;
1230 if (rect.Contains (pt)) {
1231 switch (owner.activation) {
1232 case ItemActivation.OneClick:
1233 owner.ItemActivate (this, EventArgs.Empty);
1236 case ItemActivation.TwoClick:
1237 if (last_clicked_item == clicked_item) {
1238 owner.ItemActivate (this, EventArgs.Empty);
1239 last_clicked_item = null;
1241 last_clicked_item = clicked_item;
1244 // DoubleClick activation is handled in another handler
1250 clicked_item = null;
1253 private void ItemsPaint (object sender, PaintEventArgs pe)
1255 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1259 private void ListView_Paint (object sender, PaintEventArgs pe)
1261 if (Width <= 0 || Height <= 0 || !Visible || updating)
1264 CalculateScrollBars ();
1267 private void ListView_SizeChanged (object sender, EventArgs e)
1269 CalculateListView (alignment);
1272 private void SetFocusedItem (ListViewItem item)
1274 if (focused_item != null)
1275 focused_item.Focused = false;
1278 item.Focused = true;
1280 focused_item = item;
1283 private void HorizontalScroller (object sender, EventArgs e)
1285 // Avoid unnecessary flickering, when button is
1286 // kept pressed at the end
1287 if (h_marker != h_scroll.Value) {
1289 int pixels = h_marker - h_scroll.Value;
1291 h_marker = h_scroll.Value;
1292 if (header_control.Visible)
1293 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1295 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1299 private void VerticalScroller (object sender, EventArgs e)
1301 // Avoid unnecessary flickering, when button is
1302 // kept pressed at the end
1303 if (v_marker != v_scroll.Value) {
1304 int pixels = v_marker - v_scroll.Value;
1305 Rectangle area = item_control.ClientRectangle;
1306 v_marker = v_scroll.Value;
1307 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1310 #endregion // Internal Methods Properties
1312 #region Protected Methods
1313 protected override void CreateHandle ()
1315 base.CreateHandle ();
1318 protected override void Dispose (bool disposing)
1321 h_scroll.Dispose ();
1322 v_scroll.Dispose ();
1324 large_image_list = null;
1325 small_image_list = null;
1326 state_image_list = null;
1329 base.Dispose (disposing);
1332 protected override bool IsInputKey (Keys keyData)
1349 return base.IsInputKey (keyData);
1352 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1354 if (AfterLabelEdit != null)
1355 AfterLabelEdit (this, e);
1358 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1360 if (BeforeLabelEdit != null)
1361 BeforeLabelEdit (this, e);
1364 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1366 if (ColumnClick != null)
1367 ColumnClick (this, e);
1370 protected override void OnEnabledChanged (EventArgs e)
1372 base.OnEnabledChanged (e);
1375 protected override void OnFontChanged (EventArgs e)
1377 base.OnFontChanged (e);
1381 protected override void OnHandleCreated (EventArgs e)
1383 base.OnHandleCreated (e);
1385 Controls.AddImplicit (header_control);
1386 Controls.AddImplicit (item_control);
1387 Controls.AddImplicit (this.v_scroll);
1388 Controls.AddImplicit (this.h_scroll);
1392 protected override void OnHandleDestroyed (EventArgs e)
1394 base.OnHandleDestroyed (e);
1397 protected virtual void OnItemActivate (EventArgs e)
1399 if (ItemActivate != null)
1400 ItemActivate (this, e);
1403 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1405 if (ItemCheck != null)
1406 ItemCheck (this, ice);
1409 protected virtual void OnItemDrag (ItemDragEventArgs e)
1411 if (ItemDrag != null)
1415 protected virtual void OnSelectedIndexChanged (EventArgs e)
1417 if (SelectedIndexChanged != null)
1418 SelectedIndexChanged (this, e);
1421 protected override void OnSystemColorsChanged (EventArgs e)
1423 base.OnSystemColorsChanged (e);
1426 protected void RealizeProperties ()
1431 protected void UpdateExtendedStyles ()
1436 protected override void WndProc (ref Message m)
1438 base.WndProc (ref m);
1440 #endregion // Protected Methods
1442 #region Public Instance Methods
1443 public void ArrangeIcons ()
1445 ArrangeIcons (this.alignment);
1448 public void ArrangeIcons (ListViewAlignment alignment)
1450 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1451 if (view == View.LargeIcon || view == View.SmallIcon) {
1452 this.CalculateListView (alignment);
1453 // we have done the calculations already
1454 this.Redraw (false);
1458 public void BeginUpdate ()
1460 // flag to avoid painting
1464 public void Clear ()
1467 items.Clear (); // Redraw (true) called here
1470 public void EndUpdate ()
1472 // flag to avoid painting
1475 // probably, now we need a redraw with recalculations
1479 public void EnsureVisible (int index)
1481 if (index < 0 || index >= items.Count || scrollable == false)
1484 Rectangle view_rect = item_control.ClientRectangle;
1485 Rectangle bounds = items [index].Bounds;
1487 if (view_rect.Contains (bounds))
1490 if (bounds.Left < 0)
1491 h_scroll.Value += bounds.Left;
1492 else if (bounds.Right > view_rect.Right)
1493 h_scroll.Value += (bounds.Right - view_rect.Right);
1496 v_scroll.Value += bounds.Top;
1497 else if (bounds.Bottom > view_rect.Bottom)
1498 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1501 public ListViewItem GetItemAt (int x, int y)
1503 foreach (ListViewItem item in items) {
1504 if (item.Bounds.Contains (x, y))
1510 public Rectangle GetItemRect (int index)
1512 return GetItemRect (index, ItemBoundsPortion.Entire);
1515 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1517 if (index < 0 || index >= items.Count)
1518 throw new IndexOutOfRangeException ("Invalid Index");
1520 return items [index].GetBounds (portion);
1525 if (sort_order != SortOrder.None)
1526 items.list.Sort (item_sorter);
1528 if (sort_order == SortOrder.Descending)
1529 items.list.Reverse ();
1534 public override string ToString ()
1536 int count = this.Items.Count;
1539 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1541 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1543 #endregion // Public Instance Methods
1548 class HeaderControl : Control {
1551 bool column_resize_active = false;
1552 ColumnHeader resize_column;
1553 ColumnHeader clicked_column;
1554 ColumnHeader drag_column;
1556 int drag_to_index = -1;
1558 public HeaderControl (ListView owner)
1561 MouseDown += new MouseEventHandler (HeaderMouseDown);
1562 MouseMove += new MouseEventHandler (HeaderMouseMove);
1563 MouseUp += new MouseEventHandler (HeaderMouseUp);
1564 Paint += new PaintEventHandler (HeaderPaint);
1567 private ColumnHeader ColumnAtX (int x)
1569 Point pt = new Point (x, 0);
1570 ColumnHeader result = null;
1571 foreach (ColumnHeader col in owner.Columns) {
1572 if (col.Rect.Contains (pt)) {
1580 private int GetReorderedIndex (ColumnHeader col)
1582 if (owner.reordered_column_indices == null)
1585 for (int i = 0; i < owner.Columns.Count; i++)
1586 if (owner.reordered_column_indices [i] == col.Index)
1588 throw new Exception ("Column index missing from reordered array");
1591 private void HeaderMouseDown (object sender, MouseEventArgs me)
1593 if (resize_column != null) {
1594 column_resize_active = true;
1599 clicked_column = ColumnAtX (me.X + owner.h_marker);
1601 if (clicked_column != null) {
1603 if (owner.AllowColumnReorder) {
1605 drag_column = (ColumnHeader) clicked_column.Clone ();
1606 drag_column.column_rect = clicked_column.Rect;
1607 drag_to_index = GetReorderedIndex (clicked_column);
1609 clicked_column.pressed = true;
1610 Rectangle bounds = clicked_column.Rect;
1611 bounds.X -= owner.h_marker;
1612 Invalidate (bounds);
1617 private void HeaderMouseMove (object sender, MouseEventArgs me)
1619 Point pt = new Point (me.X + owner.h_marker, me.Y);
1621 if (column_resize_active) {
1622 resize_column.Width = pt.X - resize_column.X;
1623 if (resize_column.Width < 0)
1624 resize_column.Width = 0;
1628 resize_column = null;
1630 if (clicked_column != null) {
1631 if (owner.AllowColumnReorder) {
1634 r = drag_column.column_rect;
1635 r.X = clicked_column.Rect.X + me.X - drag_x;
1636 drag_column.column_rect = r;
1638 int x = me.X + owner.h_marker;
1639 ColumnHeader over = ColumnAtX (x);
1640 if (x < over.X + over.Width / 2)
1641 drag_to_index = GetReorderedIndex (over);
1643 drag_to_index = GetReorderedIndex (over) + 1;
1646 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1647 bool pressed = clicked_column.pressed;
1648 clicked_column.pressed = over == clicked_column;
1649 if (clicked_column.pressed ^ pressed) {
1650 Rectangle bounds = clicked_column.Rect;
1651 bounds.X -= owner.h_marker;
1652 Invalidate (bounds);
1658 for (int i = 0; i < owner.Columns.Count; i++) {
1659 Rectangle zone = owner.Columns [i].Rect;
1660 zone.X = zone.Right - 5;
1662 if (zone.Contains (pt)) {
1663 resize_column = owner.Columns [i];
1668 if (resize_column == null)
1669 Cursor = Cursors.Default;
1671 Cursor = Cursors.VSplit;
1674 void HeaderMouseUp (object sender, MouseEventArgs me)
1678 if (column_resize_active) {
1679 column_resize_active = false;
1680 resize_column = null;
1681 Cursor = Cursors.Default;
1685 if (clicked_column != null && clicked_column.pressed) {
1686 clicked_column.pressed = false;
1687 Rectangle bounds = clicked_column.Rect;
1688 bounds.X -= owner.h_marker;
1689 Invalidate (bounds);
1690 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1693 if (drag_column != null && owner.AllowColumnReorder) {
1695 if (drag_to_index > GetReorderedIndex (clicked_column))
1697 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1698 owner.ReorderColumn (clicked_column, drag_to_index);
1703 clicked_column = null;
1706 void HeaderPaint (object sender, PaintEventArgs pe)
1708 if (Width <= 0 || Height <= 0 || !Visible || owner.updating)
1711 Theme theme = ThemeEngine.Current;
1712 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1714 if (drag_column == null)
1718 if (drag_to_index == owner.Columns.Count)
1719 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1721 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1722 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1727 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1729 internal ArrayList list;
1730 private ListView owner;
1732 #region Public Constructor
1733 public CheckedIndexCollection (ListView owner)
1735 list = new ArrayList ();
1738 #endregion // Public Constructor
1740 #region Public Properties
1742 public virtual int Count {
1743 get { return list.Count; }
1746 public virtual bool IsReadOnly {
1747 get { return true; }
1750 public int this [int index] {
1752 if (index < 0 || index >= list.Count)
1753 throw new ArgumentOutOfRangeException ("Index out of range.");
1754 return (int) list [index];
1758 bool ICollection.IsSynchronized {
1759 get { return false; }
1762 object ICollection.SyncRoot {
1763 get { return this; }
1766 bool IList.IsFixedSize {
1767 get { return true; }
1770 object IList.this [int index] {
1771 get { return this [index]; }
1772 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1774 #endregion // Public Properties
1776 #region Public Methods
1777 public bool Contains (int checkedIndex)
1779 return list.Contains (checkedIndex);
1782 public virtual IEnumerator GetEnumerator ()
1784 return list.GetEnumerator ();
1787 void ICollection.CopyTo (Array dest, int index)
1789 list.CopyTo (dest, index);
1792 int IList.Add (object value)
1794 throw new NotSupportedException ("Add operation is not supported.");
1799 throw new NotSupportedException ("Clear operation is not supported.");
1802 bool IList.Contains (object checkedIndex)
1804 return list.Contains (checkedIndex);
1807 int IList.IndexOf (object checkedIndex)
1809 return list.IndexOf (checkedIndex);
1812 void IList.Insert (int index, object value)
1814 throw new NotSupportedException ("Insert operation is not supported.");
1817 void IList.Remove (object value)
1819 throw new NotSupportedException ("Remove operation is not supported.");
1822 void IList.RemoveAt (int index)
1824 throw new NotSupportedException ("RemoveAt operation is not supported.");
1827 public int IndexOf (int checkedIndex)
1829 return list.IndexOf (checkedIndex);
1831 #endregion // Public Methods
1833 } // CheckedIndexCollection
1835 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1837 internal ArrayList list;
1838 private ListView owner;
1840 #region Public Constructor
1841 public CheckedListViewItemCollection (ListView owner)
1843 list = new ArrayList ();
1846 #endregion // Public Constructor
1848 #region Public Properties
1850 public virtual int Count {
1851 get { return list.Count; }
1854 public virtual bool IsReadOnly {
1855 get { return true; }
1858 public ListViewItem this [int index] {
1860 if (index < 0 || index >= list.Count)
1861 throw new ArgumentOutOfRangeException ("Index out of range.");
1862 return (ListViewItem) list [index];
1866 bool ICollection.IsSynchronized {
1867 get { return list.IsSynchronized; }
1870 object ICollection.SyncRoot {
1871 get { return this; }
1874 bool IList.IsFixedSize {
1875 get { return true; }
1878 object IList.this [int index] {
1879 get { return this [index]; }
1880 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1882 #endregion // Public Properties
1884 #region Public Methods
1885 public bool Contains (ListViewItem item)
1887 return list.Contains (item);
1890 public virtual void CopyTo (Array dest, int index)
1892 list.CopyTo (dest, index);
1895 public virtual IEnumerator GetEnumerator ()
1897 return list.GetEnumerator ();
1900 int IList.Add (object value)
1902 throw new NotSupportedException ("Add operation is not supported.");
1907 throw new NotSupportedException ("Clear operation is not supported.");
1910 bool IList.Contains (object item)
1912 return list.Contains (item);
1915 int IList.IndexOf (object item)
1917 return list.IndexOf (item);
1920 void IList.Insert (int index, object value)
1922 throw new NotSupportedException ("Insert operation is not supported.");
1925 void IList.Remove (object value)
1927 throw new NotSupportedException ("Remove operation is not supported.");
1930 void IList.RemoveAt (int index)
1932 throw new NotSupportedException ("RemoveAt operation is not supported.");
1935 public int IndexOf (ListViewItem item)
1937 return list.IndexOf (item);
1939 #endregion // Public Methods
1941 } // CheckedListViewItemCollection
1943 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
1945 internal ArrayList list;
1946 private ListView owner;
1948 #region Public Constructor
1949 public ColumnHeaderCollection (ListView owner)
1951 list = new ArrayList ();
1954 #endregion // Public Constructor
1956 #region Public Properties
1958 public virtual int Count {
1959 get { return list.Count; }
1962 public virtual bool IsReadOnly {
1963 get { return false; }
1966 public virtual ColumnHeader this [int index] {
1968 if (index < 0 || index >= list.Count)
1969 throw new ArgumentOutOfRangeException ("Index out of range.");
1970 return (ColumnHeader) list [index];
1974 bool ICollection.IsSynchronized {
1975 get { return true; }
1978 object ICollection.SyncRoot {
1979 get { return this; }
1982 bool IList.IsFixedSize {
1983 get { return list.IsFixedSize; }
1986 object IList.this [int index] {
1987 get { return this [index]; }
1988 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1990 #endregion // Public Properties
1992 #region Public Methods
1993 public virtual int Add (ColumnHeader value)
1996 value.owner = this.owner;
1997 idx = list.Add (value);
1998 owner.Redraw (true);
2002 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
2004 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2005 this.Add (colHeader);
2009 public virtual void AddRange (ColumnHeader [] values)
2011 foreach (ColumnHeader colHeader in values) {
2012 colHeader.owner = this.owner;
2016 owner.Redraw (true);
2019 public virtual void Clear ()
2022 owner.Redraw (true);
2025 public bool Contains (ColumnHeader value)
2027 return list.Contains (value);
2030 public virtual IEnumerator GetEnumerator ()
2032 return list.GetEnumerator ();
2035 void ICollection.CopyTo (Array dest, int index)
2037 list.CopyTo (dest, index);
2040 int IList.Add (object value)
2042 if (! (value is ColumnHeader)) {
2043 throw new ArgumentException ("Not of type ColumnHeader", "value");
2046 return this.Add ((ColumnHeader) value);
2049 bool IList.Contains (object value)
2051 if (! (value is ColumnHeader)) {
2052 throw new ArgumentException ("Not of type ColumnHeader", "value");
2055 return this.Contains ((ColumnHeader) value);
2058 int IList.IndexOf (object value)
2060 if (! (value is ColumnHeader)) {
2061 throw new ArgumentException ("Not of type ColumnHeader", "value");
2064 return this.IndexOf ((ColumnHeader) value);
2067 void IList.Insert (int index, object value)
2069 if (! (value is ColumnHeader)) {
2070 throw new ArgumentException ("Not of type ColumnHeader", "value");
2073 this.Insert (index, (ColumnHeader) value);
2076 void IList.Remove (object value)
2078 if (! (value is ColumnHeader)) {
2079 throw new ArgumentException ("Not of type ColumnHeader", "value");
2082 this.Remove ((ColumnHeader) value);
2085 public int IndexOf (ColumnHeader value)
2087 return list.IndexOf (value);
2090 public void Insert (int index, ColumnHeader value)
2092 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2093 // but it's really only greater.
2094 if (index < 0 || index > list.Count)
2095 throw new ArgumentOutOfRangeException ("Index out of range.");
2097 value.owner = this.owner;
2098 list.Insert (index, value);
2099 owner.Redraw (true);
2102 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2104 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2105 this.Insert (index, colHeader);
2108 public virtual void Remove (ColumnHeader column)
2110 // TODO: Update Column internal index ?
2111 list.Remove (column);
2112 owner.Redraw (true);
2115 public virtual void RemoveAt (int index)
2117 if (index < 0 || index >= list.Count)
2118 throw new ArgumentOutOfRangeException ("Index out of range.");
2120 // TODO: Update Column internal index ?
2121 list.RemoveAt (index);
2122 owner.Redraw (true);
2124 #endregion // Public Methods
2127 } // ColumnHeaderCollection
2129 public class ListViewItemCollection : IList, ICollection, IEnumerable
2131 internal ArrayList list;
2132 private ListView owner;
2134 #region Public Constructor
2135 public ListViewItemCollection (ListView owner)
2137 list = new ArrayList ();
2140 #endregion // Public Constructor
2142 #region Public Properties
2144 public virtual int Count {
2145 get { return list.Count; }
2148 public virtual bool IsReadOnly {
2149 get { return false; }
2152 public virtual ListViewItem this [int displayIndex] {
2154 if (displayIndex < 0 || displayIndex >= list.Count)
2155 throw new ArgumentOutOfRangeException ("Index out of range.");
2156 return (ListViewItem) list [displayIndex];
2160 if (displayIndex < 0 || displayIndex >= list.Count)
2161 throw new ArgumentOutOfRangeException ("Index out of range.");
2163 if (list.Contains (value))
2164 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2166 value.Owner = owner;
2167 list [displayIndex] = value;
2169 owner.Redraw (true);
2173 bool ICollection.IsSynchronized {
2174 get { return true; }
2177 object ICollection.SyncRoot {
2178 get { return this; }
2181 bool IList.IsFixedSize {
2182 get { return list.IsFixedSize; }
2185 object IList.this [int index] {
2186 get { return this [index]; }
2188 if (value is ListViewItem)
2189 this [index] = (ListViewItem) value;
2191 this [index] = new ListViewItem (value.ToString ());
2194 #endregion // Public Properties
2196 #region Public Methods
2197 public virtual ListViewItem Add (ListViewItem value)
2199 if (list.Contains (value))
2200 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2202 value.Owner = owner;
2205 if (owner.Sorting != SortOrder.None)
2208 owner.Redraw (true);
2213 public virtual ListViewItem Add (string text)
2215 ListViewItem item = new ListViewItem (text);
2216 return this.Add (item);
2219 public virtual ListViewItem Add (string text, int imageIndex)
2221 ListViewItem item = new ListViewItem (text, imageIndex);
2222 return this.Add (item);
2225 public void AddRange (ListViewItem [] values)
2228 owner.SelectedItems.list.Clear ();
2229 owner.SelectedIndices.list.Clear ();
2230 owner.CheckedItems.list.Clear ();
2231 owner.CheckedIndices.list.Clear ();
2233 foreach (ListViewItem item in values) {
2238 if (owner.Sorting != SortOrder.None)
2241 owner.Redraw (true);
2244 public virtual void Clear ()
2246 owner.SetFocusedItem (null);
2247 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2249 owner.SelectedItems.list.Clear ();
2250 owner.SelectedIndices.list.Clear ();
2251 owner.CheckedItems.list.Clear ();
2252 owner.CheckedIndices.list.Clear ();
2253 owner.Redraw (true);
2256 public bool Contains (ListViewItem item)
2258 return list.Contains (item);
2261 public virtual void CopyTo (Array dest, int index)
2263 list.CopyTo (dest, index);
2266 public virtual IEnumerator GetEnumerator ()
2268 return list.GetEnumerator ();
2271 int IList.Add (object item)
2276 if (item is ListViewItem) {
2277 li = (ListViewItem) item;
2278 if (list.Contains (li))
2279 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2282 li = new ListViewItem (item.ToString ());
2285 result = list.Add (li);
2286 owner.Redraw (true);
2291 bool IList.Contains (object item)
2293 return list.Contains (item);
2296 int IList.IndexOf (object item)
2298 return list.IndexOf (item);
2301 void IList.Insert (int index, object item)
2303 if (item is ListViewItem)
2304 this.Insert (index, (ListViewItem) item);
2306 this.Insert (index, item.ToString ());
2309 void IList.Remove (object item)
2311 Remove ((ListViewItem) item);
2314 public int IndexOf (ListViewItem item)
2316 return list.IndexOf (item);
2319 public ListViewItem Insert (int index, ListViewItem item)
2321 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2322 // but it's really only greater.
2323 if (index < 0 || index > list.Count)
2324 throw new ArgumentOutOfRangeException ("Index out of range.");
2326 if (list.Contains (item))
2327 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2330 list.Insert (index, item);
2331 owner.Redraw (true);
2335 public ListViewItem Insert (int index, string text)
2337 return this.Insert (index, new ListViewItem (text));
2340 public ListViewItem Insert (int index, string text, int imageIndex)
2342 return this.Insert (index, new ListViewItem (text, imageIndex));
2345 public virtual void Remove (ListViewItem item)
2347 if (!list.Contains (item))
2350 owner.SelectedItems.list.Remove (item);
2351 owner.SelectedIndices.list.Remove (item.Index);
2352 owner.CheckedItems.list.Remove (item);
2353 owner.CheckedIndices.list.Remove (item.Index);
2355 owner.Redraw (true);
2358 public virtual void RemoveAt (int index)
2360 if (index < 0 || index >= list.Count)
2361 throw new ArgumentOutOfRangeException ("Index out of range.");
2363 list.RemoveAt (index);
2364 owner.SelectedItems.list.RemoveAt (index);
2365 owner.SelectedIndices.list.RemoveAt (index);
2366 owner.CheckedItems.list.RemoveAt (index);
2367 owner.CheckedIndices.list.RemoveAt (index);
2368 owner.Redraw (false);
2370 #endregion // Public Methods
2372 } // ListViewItemCollection
2374 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2376 internal ArrayList list;
2377 private ListView owner;
2379 #region Public Constructor
2380 public SelectedIndexCollection (ListView owner)
2382 list = new ArrayList ();
2385 #endregion // Public Constructor
2387 #region Public Properties
2389 public virtual int Count {
2390 get { return list.Count; }
2393 public virtual bool IsReadOnly {
2394 get { return true; }
2397 public int this [int index] {
2399 if (index < 0 || index >= list.Count)
2400 throw new ArgumentOutOfRangeException ("Index out of range.");
2401 return (int) list [index];
2405 bool ICollection.IsSynchronized {
2406 get { return list.IsSynchronized; }
2409 object ICollection.SyncRoot {
2410 get { return this; }
2413 bool IList.IsFixedSize {
2414 get { return true; }
2417 object IList.this [int index] {
2418 get { return this [index]; }
2419 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2421 #endregion // Public Properties
2423 #region Public Methods
2424 public bool Contains (int selectedIndex)
2426 return list.Contains (selectedIndex);
2429 public virtual void CopyTo (Array dest, int index)
2431 list.CopyTo (dest, index);
2434 public virtual IEnumerator GetEnumerator ()
2436 return list.GetEnumerator ();
2439 int IList.Add (object value)
2441 throw new NotSupportedException ("Add operation is not supported.");
2446 throw new NotSupportedException ("Clear operation is not supported.");
2449 bool IList.Contains (object selectedIndex)
2451 return list.Contains (selectedIndex);
2454 int IList.IndexOf (object selectedIndex)
2456 return list.IndexOf (selectedIndex);
2459 void IList.Insert (int index, object value)
2461 throw new NotSupportedException ("Insert operation is not supported.");
2464 void IList.Remove (object value)
2466 throw new NotSupportedException ("Remove operation is not supported.");
2469 void IList.RemoveAt (int index)
2471 throw new NotSupportedException ("RemoveAt operation is not supported.");
2474 public int IndexOf (int selectedIndex)
2476 return list.IndexOf (selectedIndex);
2478 #endregion // Public Methods
2480 } // SelectedIndexCollection
2482 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2484 internal ArrayList list;
2485 private ListView owner;
2487 #region Public Constructor
2488 public SelectedListViewItemCollection (ListView owner)
2490 list = new ArrayList ();
2493 #endregion // Public Constructor
2495 #region Public Properties
2497 public virtual int Count {
2498 get { return list.Count; }
2501 public virtual bool IsReadOnly {
2502 get { return true; }
2505 public ListViewItem this [int index] {
2507 if (index < 0 || index >= list.Count)
2508 throw new ArgumentOutOfRangeException ("Index out of range.");
2509 return (ListViewItem) list [index];
2513 bool ICollection.IsSynchronized {
2514 get { return list.IsSynchronized; }
2517 object ICollection.SyncRoot {
2518 get { return this; }
2521 bool IList.IsFixedSize {
2522 get { return true; }
2525 object IList.this [int index] {
2526 get { return this [index]; }
2527 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2529 #endregion // Public Properties
2531 #region Public Methods
2532 public virtual void Clear ()
2534 for (int i = 0; i < list.Count; i++)
2535 ((ListViewItem) list [i]).Selected = false;
2540 public bool Contains (ListViewItem item)
2542 return list.Contains (item);
2545 public virtual void CopyTo (Array dest, int index)
2547 list.CopyTo (dest, index);
2550 public virtual IEnumerator GetEnumerator ()
2552 return list.GetEnumerator ();
2555 int IList.Add (object value)
2557 throw new NotSupportedException ("Add operation is not supported.");
2560 bool IList.Contains (object item)
2562 return list.Contains (item);
2565 int IList.IndexOf (object item)
2567 return list.IndexOf (item);
2570 void IList.Insert (int index, object value)
2572 throw new NotSupportedException ("Insert operation is not supported.");
2575 void IList.Remove (object value)
2577 throw new NotSupportedException ("Remove operation is not supported.");
2580 void IList.RemoveAt (int index)
2582 throw new NotSupportedException ("RemoveAt operation is not supported.");
2585 public int IndexOf (ListViewItem item)
2587 return list.IndexOf (item);
2589 #endregion // Public Methods
2591 } // SelectedListViewItemCollection
2593 #endregion // Subclasses