1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc. (http://www.novell.com)
23 // Ravindra Kumar (rkumar@novell.com)
24 // Jordi Mas i Hernandez, jordi@ximian.com
25 // Mike Kestner (mkestner@novell.com)
28 // - Feedback for item activation, change in cursor types as mouse moves.
37 using System.Collections;
38 using System.ComponentModel;
39 using System.ComponentModel.Design;
41 using System.Runtime.InteropServices;
42 using System.Globalization;
44 namespace System.Windows.Forms
46 [DefaultEvent ("SelectedIndexChanged")]
47 [DefaultProperty ("Items")]
48 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
49 public class ListView : Control
51 private ItemActivation activation = ItemActivation.Standard;
52 private ListViewAlignment alignment = ListViewAlignment.Top;
53 private bool allow_column_reorder = false;
54 private bool auto_arrange = true;
55 private bool check_boxes = false;
56 private CheckedIndexCollection checked_indices;
57 private CheckedListViewItemCollection checked_items;
58 private ColumnHeaderCollection columns;
59 internal ListViewItem focused_item;
60 private bool full_row_select = false;
61 private bool grid_lines = false;
62 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
63 private bool hide_selection = true;
64 private bool hover_selection = false;
65 private IComparer item_sorter;
66 private ListViewItemCollection items;
67 private bool label_edit = false;
68 private bool label_wrap = true;
69 private bool multiselect = true;
70 private bool scrollable = true;
71 private SelectedIndexCollection selected_indices;
72 private SelectedListViewItemCollection selected_items;
73 private SortOrder sort_order = SortOrder.None;
74 private ImageList state_image_list;
75 private bool updating = false;
76 private View view = View.LargeIcon;
77 private int layout_wd; // We might draw more than our client area
78 private int layout_ht; // therefore we need to have these two.
79 //private TextBox editor; // Used for editing an item text
80 HeaderControl header_control;
81 internal ItemControl item_control;
82 internal ScrollBar h_scroll; // used for scrolling horizontally
83 internal ScrollBar v_scroll; // used for scrolling vertically
84 internal int h_marker; // Position markers for scrolling
85 internal int v_marker;
86 private int keysearch_tickcnt;
87 private string keysearch_text;
88 static private readonly int keysearch_keydelay = 1000;
89 private int[] reordered_column_indices;
92 internal ImageList large_image_list;
93 internal ImageList small_image_list;
94 internal Size text_size = Size.Empty;
97 public event LabelEditEventHandler AfterLabelEdit;
100 [EditorBrowsable (EditorBrowsableState.Never)]
101 public new event EventHandler BackgroundImageChanged {
102 add { base.BackgroundImageChanged += value; }
103 remove { base.BackgroundImageChanged -= value; }
106 public event LabelEditEventHandler BeforeLabelEdit;
107 public event ColumnClickEventHandler ColumnClick;
108 public event EventHandler ItemActivate;
109 public event ItemCheckEventHandler ItemCheck;
110 public event ItemDragEventHandler ItemDrag;
113 [EditorBrowsable (EditorBrowsableState.Never)]
114 public new event PaintEventHandler Paint {
115 add { base.Paint += value; }
116 remove { base.Paint -= value; }
119 public event EventHandler SelectedIndexChanged;
122 [EditorBrowsable (EditorBrowsableState.Never)]
123 public new event EventHandler TextChanged {
124 add { base.TextChanged += value; }
125 remove { base.TextChanged -= value; }
130 #region Public Constructors
133 background_color = ThemeEngine.Current.ColorWindow;
134 checked_indices = new CheckedIndexCollection (this);
135 checked_items = new CheckedListViewItemCollection (this);
136 columns = new ColumnHeaderCollection (this);
137 foreground_color = SystemColors.WindowText;
138 items = new ListViewItemCollection (this);
139 selected_indices = new SelectedIndexCollection (this);
140 selected_items = new SelectedListViewItemCollection (this);
142 border_style = BorderStyle.Fixed3D;
144 header_control = new HeaderControl (this);
145 header_control.Visible = false;
146 item_control = new ItemControl (this);
147 item_control.Visible = true;
149 h_scroll = new HScrollBar ();
150 v_scroll = new VScrollBar ();
151 h_marker = v_marker = 0;
152 keysearch_tickcnt = 0;
154 // scroll bars are disabled initially
155 h_scroll.Visible = false;
156 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
157 v_scroll.Visible = false;
158 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
161 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
162 SizeChanged += new EventHandler (ListView_SizeChanged);
164 this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
166 #endregion // Public Constructors
168 #region Private Internal Properties
169 internal Size CheckBoxSize {
171 if (this.check_boxes) {
172 if (this.state_image_list != null)
173 return this.state_image_list.ImageSize;
175 return ThemeEngine.Current.ListViewCheckBoxSize;
181 internal bool CanMultiselect {
183 if (multiselect && (XplatUI.State.ModifierKeys & (Keys.Control | Keys.Shift)) != 0)
190 #endregion // Private Internal Properties
192 #region Protected Properties
193 protected override CreateParams CreateParams {
194 get { return base.CreateParams; }
197 protected override Size DefaultSize {
198 get { return ThemeEngine.Current.ListViewDefaultSize; }
200 #endregion // Protected Properties
202 #region Public Instance Properties
203 [DefaultValue (ItemActivation.Standard)]
204 public ItemActivation Activation {
205 get { return activation; }
207 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
208 value != ItemActivation.TwoClick) {
209 throw new InvalidEnumArgumentException (string.Format
210 ("Enum argument value '{0}' is not valid for Activation", value));
217 [DefaultValue (ListViewAlignment.Top)]
219 public ListViewAlignment Alignment {
220 get { return alignment; }
222 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
223 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
224 throw new InvalidEnumArgumentException (string.Format
225 ("Enum argument value '{0}' is not valid for Alignment", value));
228 if (this.alignment != value) {
230 // alignment does not matter in Details/List views
231 if (this.view == View.LargeIcon ||
232 this.View == View.SmallIcon)
238 [DefaultValue (false)]
239 public bool AllowColumnReorder {
240 get { return allow_column_reorder; }
241 set { allow_column_reorder = value; }
244 [DefaultValue (true)]
245 public bool AutoArrange {
246 get { return auto_arrange; }
248 if (auto_arrange != value) {
249 auto_arrange = value;
250 // autoarrange does not matter in Details/List views
251 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
257 public override Color BackColor {
259 if (background_color.IsEmpty)
260 return ThemeEngine.Current.ColorWindow;
262 return background_color;
264 set { background_color = value; }
268 [EditorBrowsable (EditorBrowsableState.Never)]
269 public override Image BackgroundImage {
270 get { return background_image; }
272 if (value == background_image)
275 background_image = value;
276 OnBackgroundImageChanged (EventArgs.Empty);
280 [DefaultValue (BorderStyle.Fixed3D)]
282 public BorderStyle BorderStyle {
283 get { return InternalBorderStyle; }
284 set { InternalBorderStyle = value; }
287 [DefaultValue (false)]
288 public bool CheckBoxes {
289 get { return check_boxes; }
291 if (check_boxes != value) {
299 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
300 public CheckedIndexCollection CheckedIndices {
301 get { return checked_indices; }
305 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
306 public CheckedListViewItemCollection CheckedItems {
307 get { return checked_items; }
310 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
312 [MergableProperty (false)]
313 public ColumnHeaderCollection Columns {
314 get { return columns; }
318 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
319 public ListViewItem FocusedItem {
321 if (focused_item == null && Focused && items.Count > 0)
322 focused_item = items [0];
327 public override Color ForeColor {
329 if (foreground_color.IsEmpty)
330 return ThemeEngine.Current.ColorWindowText;
332 return foreground_color;
334 set { foreground_color = value; }
337 [DefaultValue (false)]
338 public bool FullRowSelect {
339 get { return full_row_select; }
340 set { full_row_select = value; }
343 [DefaultValue (false)]
344 public bool GridLines {
345 get { return grid_lines; }
347 if (grid_lines != value) {
354 [DefaultValue (ColumnHeaderStyle.Clickable)]
355 public ColumnHeaderStyle HeaderStyle {
356 get { return header_style; }
358 if (header_style == value)
362 case ColumnHeaderStyle.Clickable:
363 case ColumnHeaderStyle.Nonclickable:
364 case ColumnHeaderStyle.None:
367 throw new InvalidEnumArgumentException (string.Format
368 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
371 header_style = value;
372 if (view == View.Details)
377 [DefaultValue (true)]
378 public bool HideSelection {
379 get { return hide_selection; }
381 if (hide_selection != value) {
382 hide_selection = value;
388 [DefaultValue (false)]
389 public bool HoverSelection {
390 get { return hover_selection; }
391 set { hover_selection = value; }
394 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
396 [MergableProperty (false)]
397 public ListViewItemCollection Items {
398 get { return items; }
401 [DefaultValue (false)]
402 public bool LabelEdit {
403 get { return label_edit; }
404 set { label_edit = value; }
407 [DefaultValue (true)]
409 public bool LabelWrap {
410 get { return label_wrap; }
412 if (label_wrap != value) {
419 [DefaultValue (null)]
420 public ImageList LargeImageList {
421 get { return large_image_list; }
423 large_image_list = value;
429 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
430 public IComparer ListViewItemSorter {
431 get { return item_sorter; }
432 set { item_sorter = value; }
435 [DefaultValue (true)]
436 public bool MultiSelect {
437 get { return multiselect; }
438 set { multiselect = value; }
441 [DefaultValue (true)]
442 public bool Scrollable {
443 get { return scrollable; }
445 if (scrollable != value) {
453 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
454 public SelectedIndexCollection SelectedIndices {
455 get { return selected_indices; }
459 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
460 public SelectedListViewItemCollection SelectedItems {
461 get { return selected_items; }
464 [DefaultValue (null)]
465 public ImageList SmallImageList {
466 get { return small_image_list; }
468 small_image_list = value;
473 [DefaultValue (SortOrder.None)]
474 public SortOrder Sorting {
475 get { return sort_order; }
477 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
478 value != SortOrder.None) {
479 throw new InvalidEnumArgumentException (string.Format
480 ("Enum argument value '{0}' is not valid for Sorting", value));
483 if (sort_order != value) {
490 [DefaultValue (null)]
491 public ImageList StateImageList {
492 get { return state_image_list; }
494 state_image_list = value;
501 [EditorBrowsable (EditorBrowsableState.Never)]
502 public override string Text {
511 OnTextChanged (EventArgs.Empty);
516 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
517 public ListViewItem TopItem {
520 if (this.items.Count == 0)
522 // if contents are not scrolled
523 // it is the first item
524 else if (h_marker == 0 && v_marker == 0)
525 return this.items [0];
526 // do a hit test for the scrolled position
528 foreach (ListViewItem item in this.items) {
529 if (item.Bounds.X >= 0 && item.Bounds.Y >= 0)
537 [DefaultValue (View.LargeIcon)]
541 if (value != View.Details && value != View.LargeIcon &&
542 value != View.List && value != View.SmallIcon ) {
543 throw new InvalidEnumArgumentException (string.Format
544 ("Enum argument value '{0}' is not valid for View", value));
548 h_scroll.Value = v_scroll.Value = 0;
554 #endregion // Public Instance Properties
556 #region Internal Methods Properties
558 internal int FirstVisibleIndex {
561 if (this.items.Count == 0)
564 if (h_marker == 0 && v_marker == 0)
567 foreach (ListViewItem item in this.items) {
568 if (item.Bounds.Right >= 0 && item.Bounds.Bottom >= 0)
577 internal int LastVisibleIndex {
579 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
580 if (Items[i].Bounds.Y > ClientRectangle.Bottom)
584 return Items.Count - 1;
588 internal int TotalWidth {
589 get { return Math.Max (this.Width, this.layout_wd); }
592 internal int TotalHeight {
593 get { return Math.Max (this.Height, this.layout_ht); }
596 internal void Redraw (bool recalculate)
598 // Avoid calculations when control is being updated
603 CalculateListView (this.alignment);
608 internal Size GetChildColumnSize (int index)
610 Size ret_size = Size.Empty;
611 ColumnHeader col = this.columns [index];
613 if (col.Width == -2) { // autosize = max(items, columnheader)
614 Size size = Size.Ceiling (this.DeviceContext.MeasureString
615 (col.Text, this.Font));
616 ret_size = BiggestItem (index);
617 if (size.Width > ret_size.Width)
620 else { // -1 and all the values < -2 are put under one category
621 ret_size = BiggestItem (index);
622 // fall back to empty columns' width if no subitem is available for a column
623 if (ret_size.IsEmpty) {
624 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
625 if (col.Text.Length > 0)
626 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
627 (col.Text, this.Font)).Height;
629 ret_size.Height = this.Font.Height;
633 // adjust the size for icon and checkbox for 0th column
635 ret_size.Width += (this.CheckBoxSize.Width + 4);
636 if (this.small_image_list != null)
637 ret_size.Width += this.small_image_list.ImageSize.Width;
642 // Returns the size of biggest item text in a column.
643 private Size BiggestItem (int col)
645 Size temp = Size.Empty;
646 Size ret_size = Size.Empty;
648 // 0th column holds the item text, we check the size of
649 // the various subitems falling in that column and get
650 // the biggest one's size.
651 foreach (ListViewItem item in items) {
652 if (col >= item.SubItems.Count)
655 temp = Size.Ceiling (this.DeviceContext.MeasureString
656 (item.SubItems [col].Text, this.Font));
657 if (temp.Width > ret_size.Width)
661 // adjustment for space
662 if (!ret_size.IsEmpty)
668 // Sets the size of the biggest item text as per the view
669 private void CalcTextSize ()
671 // clear the old value
672 text_size = Size.Empty;
674 if (items.Count == 0)
677 text_size = BiggestItem (0);
679 if (view == View.LargeIcon && this.label_wrap) {
680 Size temp = Size.Empty;
681 if (this.check_boxes)
682 temp.Width += 2 * this.CheckBoxSize.Width;
683 if (large_image_list != null)
684 temp.Width += large_image_list.ImageSize.Width;
687 // wrapping is done for two lines only
688 if (text_size.Width > temp.Width) {
689 text_size.Width = temp.Width;
690 text_size.Height *= 2;
693 else if (view == View.List) {
694 // in list view max text shown in determined by the
695 // control width, even if scolling is enabled.
696 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
697 if (this.small_image_list != null)
698 max_wd -= this.small_image_list.ImageSize.Width;
700 if (text_size.Width > max_wd)
701 text_size.Width = max_wd;
704 // we do the default settings, if we have got 0's
705 if (text_size.Height <= 0)
706 text_size.Height = this.Font.Height;
707 if (text_size.Width <= 0)
708 text_size.Width = this.Width;
711 text_size.Width += 4;
712 text_size.Height += 2;
715 private void Scroll (ScrollBar scrollbar, int delta)
717 if (delta == 0 || !scrollbar.Visible)
721 if (scrollbar == h_scroll)
722 max = h_scroll.Maximum - item_control.Width;
724 max = v_scroll.Maximum - item_control.Height;
726 int val = scrollbar.Value + delta;
729 else if (val < scrollbar.Minimum)
730 val = scrollbar.Minimum;
731 scrollbar.Value = val;
734 private void CalculateScrollBars ()
736 Rectangle client_area = ClientRectangle;
738 if (!this.scrollable || this.items.Count <= 0) {
739 h_scroll.Visible = false;
740 v_scroll.Visible = false;
744 // making a scroll bar visible might make
745 // other scroll bar visible
746 if (layout_wd > client_area.Right) {
747 h_scroll.Visible = true;
748 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
749 v_scroll.Visible = true;
751 v_scroll.Visible = false;
752 } else if (layout_ht > client_area.Bottom) {
753 v_scroll.Visible = true;
754 if ((layout_wd + v_scroll.Width) > client_area.Right)
755 h_scroll.Visible = true;
757 h_scroll.Visible = false;
759 h_scroll.Visible = false;
760 v_scroll.Visible = false;
763 item_control.Height = ClientRectangle.Height - header_control.Height;
765 if (h_scroll.Visible) {
766 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
767 h_scroll.Minimum = 0;
769 // if v_scroll is visible, adjust the maximum of the
770 // h_scroll to account for the width of v_scroll
771 if (v_scroll.Visible) {
772 h_scroll.Maximum = layout_wd + v_scroll.Width;
773 h_scroll.Width = client_area.Width - v_scroll.Width;
776 h_scroll.Maximum = layout_wd;
777 h_scroll.Width = client_area.Width;
780 h_scroll.LargeChange = client_area.Width;
781 h_scroll.SmallChange = Font.Height;
782 item_control.Height -= h_scroll.Height;
785 if (header_control.Visible)
786 header_control.Width = ClientRectangle.Width;
787 item_control.Width = ClientRectangle.Width;
789 if (v_scroll.Visible) {
790 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
791 v_scroll.Minimum = 0;
793 // if h_scroll is visible, adjust the maximum of the
794 // v_scroll to account for the height of h_scroll
795 if (h_scroll.Visible) {
796 v_scroll.Maximum = layout_ht + h_scroll.Height;
797 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
799 v_scroll.Maximum = layout_ht;
800 v_scroll.Height = client_area.Height;
803 v_scroll.LargeChange = client_area.Height;
804 v_scroll.SmallChange = Font.Height;
805 if (header_control.Visible)
806 header_control.Width -= v_scroll.Width;
807 item_control.Width -= v_scroll.Width;
811 ColumnHeader GetReorderedColumn (int index)
813 if (reordered_column_indices == null)
814 return Columns [index];
816 return Columns [reordered_column_indices [index]];
819 void ReorderColumn (ColumnHeader col, int index)
821 if (reordered_column_indices == null) {
822 reordered_column_indices = new int [Columns.Count];
823 for (int i = 0; i < Columns.Count; i++)
824 reordered_column_indices [i] = i;
827 if (reordered_column_indices [index] == col.Index)
830 int[] curr = reordered_column_indices;
831 int[] result = new int [Columns.Count];
833 for (int i = 0; i < Columns.Count; i++) {
834 if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
838 result [i] = col.Index;
840 result [i] = curr [curr_idx++];
843 reordered_column_indices = result;
845 header_control.Invalidate ();
846 item_control.Invalidate ();
849 Size LargeIconItemSize {
851 int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
852 int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
853 int w = CheckBoxSize.Width + 2 + Math.Max (text_size.Width, image_w);
854 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
855 return new Size (w, h);
859 Size SmallIconItemSize {
861 int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
862 int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
863 int w = text_size.Width + 2 + CheckBoxSize.Width + image_w;
864 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
865 return new Size (w, h);
871 ListViewItem[,] item_matrix;
873 void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
875 header_control.Visible = false;
876 header_control.Size = Size.Empty;
877 item_control.Location = Point.Empty;
879 if (items.Count == 0)
882 Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
884 Rectangle area = ClientRectangle;
887 rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(sz.Height + y_spacing));
890 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
892 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(sz.Width + x_spacing));
895 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
898 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
899 layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
900 item_matrix = new ListViewItem [rows, cols];
903 foreach (ListViewItem item in items) {
904 int x = col * (sz.Width + x_spacing);
905 int y = row * (sz.Height + y_spacing);
906 item.Location = new Point (x, y);
910 item_matrix [row, col] = item;
924 item_control.Size = new Size (layout_wd, layout_ht);
929 if (columns.Count == 0 || header_style == ColumnHeaderStyle.None) {
930 header_control.Visible = false;
931 header_control.Size = Size.Empty;
936 for (int i = 0; i < Columns.Count; i++) {
937 ColumnHeader col = GetReorderedColumn (i);
940 col.CalcColumnHeader ();
944 header_control.Width = x;
945 header_control.Height = columns [0].Ht;
946 header_control.Visible = true;
949 void LayoutDetails ()
953 item_control.Location = new Point (0, header_control.Height);
956 if (items.Count > 0) {
957 foreach (ListViewItem item in items) {
959 item.Location = new Point (0, y);
960 y += item.Bounds.Height + 2;
963 // some space for bottom gridline
968 layout_wd = Math.Max (header_control.Width, item_control.Width);
969 layout_ht = y + header_control.Height;
972 private void CalculateListView (ListViewAlignment align)
982 LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
986 LayoutIcons (true, alignment == ListViewAlignment.Left,
987 ThemeEngine.Current.ListViewHorizontalSpacing,
988 ThemeEngine.Current.ListViewVerticalSpacing);
992 LayoutIcons (false, true, 4, 2);
996 CalculateScrollBars ();
999 internal void UpdateSelection (ListViewItem item)
1001 if (item.Selected) {
1003 if (!CanMultiselect && SelectedItems.Count > 0) {
1004 SelectedItems.Clear ();
1005 SelectedIndices.list.Clear ();
1008 if (!SelectedItems.Contains (item)) {
1009 SelectedItems.list.Add (item);
1010 SelectedIndices.list.Add (item.Index);
1013 SelectedItems.list.Remove (item);
1014 SelectedIndices.list.Remove (item.Index);
1018 private bool KeySearchString (KeyEventArgs ke)
1020 int current_tickcnt = Environment.TickCount;
1021 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
1022 keysearch_text = string.Empty;
1025 keysearch_text += (char) ke.KeyData;
1026 keysearch_tickcnt = current_tickcnt;
1028 int start = FocusedItem == null ? 0 : FocusedItem.Index;
1031 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1032 CompareOptions.IgnoreCase)) {
1033 SetFocusedItem (Items [i]);
1034 items [i].Selected = true;
1038 i = (i + 1 < Items.Count) ? i+1 : 0;
1046 int GetAdjustedIndex (Keys key)
1050 if (View == View.Details) {
1052 result = FocusedItem.Index - 1;
1053 else if (key == Keys.Down) {
1054 result = FocusedItem.Index + 1;
1055 if (result == items.Count)
1061 int row = FocusedItem.row;
1062 int col = FocusedItem.col;
1068 return item_matrix [row, col - 1].Index;
1071 if (col == (cols - 1))
1073 while (item_matrix [row, col + 1] == null)
1075 return item_matrix [row, col + 1].Index;
1080 return item_matrix [row - 1, col].Index;
1083 if (row == (rows - 1))
1085 while (item_matrix [row + 1, col] == null)
1087 return item_matrix [row + 1, col].Index;
1094 ListViewItem selection_start;
1096 private void SelectItems (ArrayList sel_items)
1098 SelectedItems.Clear ();
1099 SelectedIndices.list.Clear ();
1100 foreach (ListViewItem item in sel_items)
1101 item.Selected = true;
1104 private void UpdateMultiSelection (int index)
1106 bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
1107 bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
1108 ListViewItem item = items [index];
1110 if (shift_pressed && selection_start != null) {
1111 ArrayList list = new ArrayList ();
1112 int start = Math.Min (selection_start.Index, index);
1113 int end = Math.Max (selection_start.Index, index);
1114 if (View == View.Details) {
1115 for (int i = start; i <= end; i++)
1116 list.Add (items [i]);
1118 int left = Math.Min (items [start].col, items [end].col);
1119 int right = Math.Max (items [start].col, items [end].col);
1120 int top = Math.Min (items [start].row, items [end].row);
1121 int bottom = Math.Max (items [start].row, items [end].row);
1122 foreach (ListViewItem curr in items)
1123 if (curr.row >= top && curr.row <= bottom &&
1124 curr.col >= left && curr.col <= right)
1128 } else if (!ctrl_pressed) {
1129 SelectedItems.Clear ();
1130 SelectedIndices.list.Clear ();
1131 item.Selected = true;
1132 selection_start = item;
1136 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1138 if (ke.Handled || Items.Count == 0)
1144 switch (ke.KeyCode) {
1147 index = Items.Count - 1;
1158 index = GetAdjustedIndex (ke.KeyCode);
1162 ke.Handled = KeySearchString (ke);
1170 UpdateMultiSelection (index);
1172 items [index].Selected = true;
1174 SetFocusedItem (items [index]);
1175 EnsureVisible (index);
1179 internal class ItemControl : Control {
1182 ListViewItem clicked_item;
1183 ListViewItem last_clicked_item;
1184 bool hover_processed = false;
1186 public ItemControl (ListView owner)
1189 DoubleClick += new EventHandler(ItemsDoubleClick);
1190 KeyDown += new KeyEventHandler (ItemsKeyDown);
1191 KeyUp += new KeyEventHandler (ItemsKeyUp);
1192 MouseDown += new MouseEventHandler(ItemsMouseDown);
1193 MouseMove += new MouseEventHandler(ItemsMouseMove);
1194 MouseHover += new EventHandler(ItemsMouseHover);
1195 MouseUp += new MouseEventHandler(ItemsMouseUp);
1196 MouseWheel += new MouseEventHandler(ItemsMouseWheel);
1199 void ItemsDoubleClick (object sender, EventArgs e)
1201 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1202 owner.ItemActivate (this, e);
1205 void ItemsKeyDown (object sender, KeyEventArgs args)
1207 owner.OnKeyDown (args);
1210 void ItemsKeyUp (object sender, KeyEventArgs args)
1212 owner.OnKeyUp (args);
1215 private void ItemsMouseDown (object sender, MouseEventArgs me)
1217 if (owner.items.Count == 0)
1220 Point pt = new Point (me.X, me.Y);
1221 foreach (ListViewItem item in owner.items) {
1222 if (item.CheckRectReal.Contains (pt)) {
1223 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1224 item.Checked = !item.Checked;
1226 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1228 // Raise the ItemCheck event
1229 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1230 owner.OnItemCheck (ice);
1234 if (owner.View == View.Details && !owner.FullRowSelect) {
1235 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1236 clicked_item = item;
1240 if (item.Bounds.Contains (pt)) {
1241 clicked_item = item;
1247 owner.SetFocusedItem (clicked_item);
1249 if (clicked_item != null) {
1250 bool changed = !clicked_item.Selected;
1251 if (owner.MultiSelect && (XplatUI.State.ModifierKeys & Keys.Control) == 0)
1252 owner.UpdateMultiSelection (clicked_item.Index);
1254 clicked_item.Selected = true;
1257 owner.OnSelectedIndexChanged (EventArgs.Empty);
1259 // Raise double click if the item was clicked. On MS the
1260 // double click is only raised if you double click an item
1261 if (me.Clicks > 1 && clicked_item != null)
1262 owner.OnDoubleClick (EventArgs.Empty);
1263 else if (me.Clicks == 1 && clicked_item != null)
1264 owner.OnClick (EventArgs.Empty);
1265 } else if (owner.selected_indices.Count > 0) {
1266 // Raise the event if there was at least one item
1267 // selected and the user click on a dead area (unselecting all)
1268 owner.SelectedItems.Clear ();
1269 owner.SelectedIndices.list.Clear ();
1270 owner.OnSelectedIndexChanged (EventArgs.Empty);
1274 private void ItemsMouseMove (object sender, MouseEventArgs me)
1276 if (owner.HoverSelection && hover_processed) {
1278 Point pt = PointToClient (Control.MousePosition);
1279 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1280 if (item == null || item.Selected)
1283 hover_processed = false;
1284 XplatUI.ResetMouseHover (Handle);
1289 private void ItemsMouseHover (object sender, EventArgs e)
1291 if (Capture || !owner.HoverSelection)
1294 hover_processed = true;
1295 Point pt = PointToClient (Control.MousePosition);
1296 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1301 item.Selected = true;
1302 owner.OnSelectedIndexChanged (new EventArgs ());
1305 private void ItemsMouseUp (object sender, MouseEventArgs me)
1308 if (owner.Items.Count == 0)
1311 Point pt = new Point (me.X, me.Y);
1313 Rectangle rect = Rectangle.Empty;
1314 if (clicked_item != null) {
1315 if (owner.view == View.Details && !owner.full_row_select)
1316 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1318 rect = clicked_item.Bounds;
1320 if (rect.Contains (pt)) {
1321 switch (owner.activation) {
1322 case ItemActivation.OneClick:
1323 owner.OnItemActivate (EventArgs.Empty);
1326 case ItemActivation.TwoClick:
1327 if (last_clicked_item == clicked_item) {
1328 owner.OnItemActivate (EventArgs.Empty);
1329 last_clicked_item = null;
1331 last_clicked_item = clicked_item;
1334 // DoubleClick activation is handled in another handler
1340 clicked_item = null;
1343 private void ItemsMouseWheel (object sender, MouseEventArgs me)
1345 if (owner.Items.Count == 0)
1348 int lines = me.Delta / 120;
1353 switch (owner.View) {
1355 case View.SmallIcon:
1356 owner.Scroll (owner.v_scroll, -owner.Items [0].Bounds.Height * SystemInformation.MouseWheelScrollLines * lines);
1358 case View.LargeIcon:
1359 owner.Scroll (owner.v_scroll, -(owner.Items [0].Bounds.Height + ThemeEngine.Current.ListViewVerticalSpacing) * lines);
1362 owner.Scroll (owner.h_scroll, -owner.Items [0].Bounds.Width * lines);
1367 internal override void OnPaintInternal (PaintEventArgs pe)
1369 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1373 internal override void OnPaintInternal (PaintEventArgs pe)
1378 CalculateScrollBars ();
1381 private void ListView_SizeChanged (object sender, EventArgs e)
1383 CalculateListView (alignment);
1386 private void SetFocusedItem (ListViewItem item)
1388 if (focused_item != null)
1389 focused_item.Focused = false;
1392 item.Focused = true;
1394 focused_item = item;
1397 private void HorizontalScroller (object sender, EventArgs e)
1399 // Avoid unnecessary flickering, when button is
1400 // kept pressed at the end
1401 if (h_marker != h_scroll.Value) {
1403 int pixels = h_marker - h_scroll.Value;
1405 h_marker = h_scroll.Value;
1406 if (header_control.Visible)
1407 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1409 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1413 private void VerticalScroller (object sender, EventArgs e)
1415 // Avoid unnecessary flickering, when button is
1416 // kept pressed at the end
1417 if (v_marker != v_scroll.Value) {
1418 int pixels = v_marker - v_scroll.Value;
1419 Rectangle area = item_control.ClientRectangle;
1420 v_marker = v_scroll.Value;
1421 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1424 #endregion // Internal Methods Properties
1426 #region Protected Methods
1427 protected override void CreateHandle ()
1429 base.CreateHandle ();
1432 protected override void Dispose (bool disposing)
1435 h_scroll.Dispose ();
1436 v_scroll.Dispose ();
1438 large_image_list = null;
1439 small_image_list = null;
1440 state_image_list = null;
1443 base.Dispose (disposing);
1446 protected override bool IsInputKey (Keys keyData)
1463 return base.IsInputKey (keyData);
1466 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1468 if (AfterLabelEdit != null)
1469 AfterLabelEdit (this, e);
1472 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1474 if (BeforeLabelEdit != null)
1475 BeforeLabelEdit (this, e);
1478 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1480 if (ColumnClick != null)
1481 ColumnClick (this, e);
1484 protected override void OnEnabledChanged (EventArgs e)
1486 base.OnEnabledChanged (e);
1489 protected override void OnFontChanged (EventArgs e)
1491 base.OnFontChanged (e);
1495 protected override void OnHandleCreated (EventArgs e)
1497 base.OnHandleCreated (e);
1499 Controls.AddImplicit (header_control);
1500 Controls.AddImplicit (item_control);
1501 Controls.AddImplicit (this.v_scroll);
1502 Controls.AddImplicit (this.h_scroll);
1506 protected override void OnHandleDestroyed (EventArgs e)
1508 base.OnHandleDestroyed (e);
1511 protected virtual void OnItemActivate (EventArgs e)
1513 if (ItemActivate != null)
1514 ItemActivate (this, e);
1517 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1519 if (ItemCheck != null)
1520 ItemCheck (this, ice);
1523 protected virtual void OnItemDrag (ItemDragEventArgs e)
1525 if (ItemDrag != null)
1529 protected virtual void OnSelectedIndexChanged (EventArgs e)
1531 if (SelectedIndexChanged != null)
1532 SelectedIndexChanged (this, e);
1535 protected override void OnSystemColorsChanged (EventArgs e)
1537 base.OnSystemColorsChanged (e);
1540 protected void RealizeProperties ()
1545 protected void UpdateExtendedStyles ()
1550 protected override void WndProc (ref Message m)
1552 base.WndProc (ref m);
1554 #endregion // Protected Methods
1556 #region Public Instance Methods
1557 public void ArrangeIcons ()
1559 ArrangeIcons (this.alignment);
1562 public void ArrangeIcons (ListViewAlignment alignment)
1564 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1565 if (view == View.LargeIcon || view == View.SmallIcon) {
1566 this.CalculateListView (alignment);
1567 // we have done the calculations already
1568 this.Redraw (false);
1572 public void BeginUpdate ()
1574 // flag to avoid painting
1578 public void Clear ()
1581 items.Clear (); // Redraw (true) called here
1584 public void EndUpdate ()
1586 // flag to avoid painting
1589 // probably, now we need a redraw with recalculations
1593 public void EnsureVisible (int index)
1595 if (index < 0 || index >= items.Count || scrollable == false)
1598 Rectangle view_rect = item_control.ClientRectangle;
1599 Rectangle bounds = items [index].Bounds;
1601 if (view_rect.Contains (bounds))
1604 if (bounds.Left < 0)
1605 h_scroll.Value += bounds.Left;
1606 else if (bounds.Right > view_rect.Right)
1607 h_scroll.Value += (bounds.Right - view_rect.Right);
1610 v_scroll.Value += bounds.Top;
1611 else if (bounds.Bottom > view_rect.Bottom)
1612 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1615 public ListViewItem GetItemAt (int x, int y)
1617 foreach (ListViewItem item in items) {
1618 if (item.Bounds.Contains (x, y))
1624 public Rectangle GetItemRect (int index)
1626 return GetItemRect (index, ItemBoundsPortion.Entire);
1629 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1631 if (index < 0 || index >= items.Count)
1632 throw new IndexOutOfRangeException ("Invalid Index");
1634 return items [index].GetBounds (portion);
1639 if (sort_order != SortOrder.None)
1640 items.list.Sort (item_sorter);
1642 if (sort_order == SortOrder.Descending)
1643 items.list.Reverse ();
1648 public override string ToString ()
1650 int count = this.Items.Count;
1653 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1655 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1657 #endregion // Public Instance Methods
1662 class HeaderControl : Control {
1665 bool column_resize_active = false;
1666 ColumnHeader resize_column;
1667 ColumnHeader clicked_column;
1668 ColumnHeader drag_column;
1670 int drag_to_index = -1;
1672 public HeaderControl (ListView owner)
1675 MouseDown += new MouseEventHandler (HeaderMouseDown);
1676 MouseMove += new MouseEventHandler (HeaderMouseMove);
1677 MouseUp += new MouseEventHandler (HeaderMouseUp);
1680 private ColumnHeader ColumnAtX (int x)
1682 Point pt = new Point (x, 0);
1683 ColumnHeader result = null;
1684 foreach (ColumnHeader col in owner.Columns) {
1685 if (col.Rect.Contains (pt)) {
1693 private int GetReorderedIndex (ColumnHeader col)
1695 if (owner.reordered_column_indices == null)
1698 for (int i = 0; i < owner.Columns.Count; i++)
1699 if (owner.reordered_column_indices [i] == col.Index)
1701 throw new Exception ("Column index missing from reordered array");
1704 private void HeaderMouseDown (object sender, MouseEventArgs me)
1706 if (resize_column != null) {
1707 column_resize_active = true;
1712 clicked_column = ColumnAtX (me.X + owner.h_marker);
1714 if (clicked_column != null) {
1716 if (owner.AllowColumnReorder) {
1718 drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
1719 drag_column.column_rect = clicked_column.Rect;
1720 drag_to_index = GetReorderedIndex (clicked_column);
1722 clicked_column.pressed = true;
1723 Rectangle bounds = clicked_column.Rect;
1724 bounds.X -= owner.h_marker;
1725 Invalidate (bounds);
1730 private void HeaderMouseMove (object sender, MouseEventArgs me)
1732 Point pt = new Point (me.X + owner.h_marker, me.Y);
1734 if (column_resize_active) {
1735 resize_column.Width = pt.X - resize_column.X;
1736 if (resize_column.Width < 0)
1737 resize_column.Width = 0;
1741 resize_column = null;
1743 if (clicked_column != null) {
1744 if (owner.AllowColumnReorder) {
1747 r = drag_column.column_rect;
1748 r.X = clicked_column.Rect.X + me.X - drag_x;
1749 drag_column.column_rect = r;
1751 int x = me.X + owner.h_marker;
1752 ColumnHeader over = ColumnAtX (x);
1754 drag_to_index = owner.Columns.Count;
1755 else if (x < over.X + over.Width / 2)
1756 drag_to_index = GetReorderedIndex (over);
1758 drag_to_index = GetReorderedIndex (over) + 1;
1761 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1762 bool pressed = clicked_column.pressed;
1763 clicked_column.pressed = over == clicked_column;
1764 if (clicked_column.pressed ^ pressed) {
1765 Rectangle bounds = clicked_column.Rect;
1766 bounds.X -= owner.h_marker;
1767 Invalidate (bounds);
1773 for (int i = 0; i < owner.Columns.Count; i++) {
1774 Rectangle zone = owner.Columns [i].Rect;
1775 zone.X = zone.Right - 5;
1777 if (zone.Contains (pt)) {
1778 resize_column = owner.Columns [i];
1783 if (resize_column == null)
1784 Cursor = Cursors.Default;
1786 Cursor = Cursors.VSplit;
1789 void HeaderMouseUp (object sender, MouseEventArgs me)
1793 if (column_resize_active) {
1794 column_resize_active = false;
1795 resize_column = null;
1796 Cursor = Cursors.Default;
1800 if (clicked_column != null && clicked_column.pressed) {
1801 clicked_column.pressed = false;
1802 Rectangle bounds = clicked_column.Rect;
1803 bounds.X -= owner.h_marker;
1804 Invalidate (bounds);
1805 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1808 if (drag_column != null && owner.AllowColumnReorder) {
1810 if (drag_to_index > GetReorderedIndex (clicked_column))
1812 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1813 owner.ReorderColumn (clicked_column, drag_to_index);
1818 clicked_column = null;
1821 internal override void OnPaintInternal (PaintEventArgs pe)
1826 Theme theme = ThemeEngine.Current;
1827 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1829 if (drag_column == null)
1833 if (drag_to_index == owner.Columns.Count)
1834 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1836 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1837 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1842 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1844 internal ArrayList list;
1845 private ListView owner;
1847 #region Public Constructor
1848 public CheckedIndexCollection (ListView owner)
1850 list = new ArrayList ();
1853 #endregion // Public Constructor
1855 #region Public Properties
1858 get { return list.Count; }
1861 public bool IsReadOnly {
1862 get { return true; }
1865 public int this [int index] {
1867 if (index < 0 || index >= list.Count)
1868 throw new ArgumentOutOfRangeException ("Index out of range.");
1869 return (int) list [index];
1873 bool ICollection.IsSynchronized {
1874 get { return false; }
1877 object ICollection.SyncRoot {
1878 get { return this; }
1881 bool IList.IsFixedSize {
1882 get { return true; }
1885 object IList.this [int index] {
1886 get { return this [index]; }
1887 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1889 #endregion // Public Properties
1891 #region Public Methods
1892 public bool Contains (int checkedIndex)
1894 return list.Contains (checkedIndex);
1897 public IEnumerator GetEnumerator ()
1899 return list.GetEnumerator ();
1902 void ICollection.CopyTo (Array dest, int index)
1904 list.CopyTo (dest, index);
1907 int IList.Add (object value)
1909 throw new NotSupportedException ("Add operation is not supported.");
1914 throw new NotSupportedException ("Clear operation is not supported.");
1917 bool IList.Contains (object checkedIndex)
1919 return list.Contains (checkedIndex);
1922 int IList.IndexOf (object checkedIndex)
1924 return list.IndexOf (checkedIndex);
1927 void IList.Insert (int index, object value)
1929 throw new NotSupportedException ("Insert operation is not supported.");
1932 void IList.Remove (object value)
1934 throw new NotSupportedException ("Remove operation is not supported.");
1937 void IList.RemoveAt (int index)
1939 throw new NotSupportedException ("RemoveAt operation is not supported.");
1942 public int IndexOf (int checkedIndex)
1944 return list.IndexOf (checkedIndex);
1946 #endregion // Public Methods
1948 } // CheckedIndexCollection
1950 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1952 internal ArrayList list;
1953 private ListView owner;
1955 #region Public Constructor
1956 public CheckedListViewItemCollection (ListView owner)
1958 list = new ArrayList ();
1961 #endregion // Public Constructor
1963 #region Public Properties
1966 get { return list.Count; }
1969 public bool IsReadOnly {
1970 get { return true; }
1973 public ListViewItem this [int index] {
1975 if (index < 0 || index >= list.Count)
1976 throw new ArgumentOutOfRangeException ("Index out of range.");
1977 return (ListViewItem) list [index];
1981 bool ICollection.IsSynchronized {
1982 get { return list.IsSynchronized; }
1985 object ICollection.SyncRoot {
1986 get { return this; }
1989 bool IList.IsFixedSize {
1990 get { return true; }
1993 object IList.this [int index] {
1994 get { return this [index]; }
1995 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1997 #endregion // Public Properties
1999 #region Public Methods
2000 public bool Contains (ListViewItem item)
2002 return list.Contains (item);
2005 public void CopyTo (Array dest, int index)
2007 list.CopyTo (dest, index);
2010 public IEnumerator GetEnumerator ()
2012 return list.GetEnumerator ();
2015 int IList.Add (object value)
2017 throw new NotSupportedException ("Add operation is not supported.");
2022 throw new NotSupportedException ("Clear operation is not supported.");
2025 bool IList.Contains (object item)
2027 return list.Contains (item);
2030 int IList.IndexOf (object item)
2032 return list.IndexOf (item);
2035 void IList.Insert (int index, object value)
2037 throw new NotSupportedException ("Insert operation is not supported.");
2040 void IList.Remove (object value)
2042 throw new NotSupportedException ("Remove operation is not supported.");
2045 void IList.RemoveAt (int index)
2047 throw new NotSupportedException ("RemoveAt operation is not supported.");
2050 public int IndexOf (ListViewItem item)
2052 return list.IndexOf (item);
2054 #endregion // Public Methods
2056 } // CheckedListViewItemCollection
2058 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
2060 internal ArrayList list;
2061 private ListView owner;
2063 #region Public Constructor
2064 public ColumnHeaderCollection (ListView owner)
2066 list = new ArrayList ();
2069 #endregion // Public Constructor
2071 #region Public Properties
2074 get { return list.Count; }
2077 public bool IsReadOnly {
2078 get { return false; }
2081 public virtual ColumnHeader this [int index] {
2083 if (index < 0 || index >= list.Count)
2084 throw new ArgumentOutOfRangeException ("Index out of range.");
2085 return (ColumnHeader) list [index];
2089 bool ICollection.IsSynchronized {
2090 get { return true; }
2093 object ICollection.SyncRoot {
2094 get { return this; }
2097 bool IList.IsFixedSize {
2098 get { return list.IsFixedSize; }
2101 object IList.this [int index] {
2102 get { return this [index]; }
2103 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2105 #endregion // Public Properties
2107 #region Public Methods
2108 public virtual int Add (ColumnHeader value)
2111 value.owner = this.owner;
2112 idx = list.Add (value);
2113 owner.Redraw (true);
2117 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
2119 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2120 this.Add (colHeader);
2124 public virtual void AddRange (ColumnHeader [] values)
2126 foreach (ColumnHeader colHeader in values) {
2127 colHeader.owner = this.owner;
2131 owner.Redraw (true);
2134 public virtual void Clear ()
2137 owner.Redraw (true);
2140 public bool Contains (ColumnHeader value)
2142 return list.Contains (value);
2145 public IEnumerator GetEnumerator ()
2147 return list.GetEnumerator ();
2150 void ICollection.CopyTo (Array dest, int index)
2152 list.CopyTo (dest, index);
2155 int IList.Add (object value)
2157 if (! (value is ColumnHeader)) {
2158 throw new ArgumentException ("Not of type ColumnHeader", "value");
2161 return this.Add ((ColumnHeader) value);
2164 bool IList.Contains (object value)
2166 if (! (value is ColumnHeader)) {
2167 throw new ArgumentException ("Not of type ColumnHeader", "value");
2170 return this.Contains ((ColumnHeader) value);
2173 int IList.IndexOf (object value)
2175 if (! (value is ColumnHeader)) {
2176 throw new ArgumentException ("Not of type ColumnHeader", "value");
2179 return this.IndexOf ((ColumnHeader) value);
2182 void IList.Insert (int index, object value)
2184 if (! (value is ColumnHeader)) {
2185 throw new ArgumentException ("Not of type ColumnHeader", "value");
2188 this.Insert (index, (ColumnHeader) value);
2191 void IList.Remove (object value)
2193 if (! (value is ColumnHeader)) {
2194 throw new ArgumentException ("Not of type ColumnHeader", "value");
2197 this.Remove ((ColumnHeader) value);
2200 public int IndexOf (ColumnHeader value)
2202 return list.IndexOf (value);
2205 public void Insert (int index, ColumnHeader value)
2207 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2208 // but it's really only greater.
2209 if (index < 0 || index > list.Count)
2210 throw new ArgumentOutOfRangeException ("Index out of range.");
2212 value.owner = this.owner;
2213 list.Insert (index, value);
2214 owner.Redraw (true);
2217 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2219 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2220 this.Insert (index, colHeader);
2223 public virtual void Remove (ColumnHeader column)
2225 // TODO: Update Column internal index ?
2226 list.Remove (column);
2227 owner.Redraw (true);
2230 public virtual void RemoveAt (int index)
2232 if (index < 0 || index >= list.Count)
2233 throw new ArgumentOutOfRangeException ("Index out of range.");
2235 // TODO: Update Column internal index ?
2236 list.RemoveAt (index);
2237 owner.Redraw (true);
2239 #endregion // Public Methods
2242 } // ColumnHeaderCollection
2244 public class ListViewItemCollection : IList, ICollection, IEnumerable
2246 internal ArrayList list;
2247 private ListView owner;
2249 #region Public Constructor
2250 public ListViewItemCollection (ListView owner)
2252 list = new ArrayList ();
2255 #endregion // Public Constructor
2257 #region Public Properties
2260 get { return list.Count; }
2263 public bool IsReadOnly {
2264 get { return false; }
2267 public virtual ListViewItem this [int displayIndex] {
2269 if (displayIndex < 0 || displayIndex >= list.Count)
2270 throw new ArgumentOutOfRangeException ("Index out of range.");
2271 return (ListViewItem) list [displayIndex];
2275 if (displayIndex < 0 || displayIndex >= list.Count)
2276 throw new ArgumentOutOfRangeException ("Index out of range.");
2278 if (list.Contains (value))
2279 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2281 value.Owner = owner;
2282 list [displayIndex] = value;
2284 owner.Redraw (true);
2288 bool ICollection.IsSynchronized {
2289 get { return true; }
2292 object ICollection.SyncRoot {
2293 get { return this; }
2296 bool IList.IsFixedSize {
2297 get { return list.IsFixedSize; }
2300 object IList.this [int index] {
2301 get { return this [index]; }
2303 if (value is ListViewItem)
2304 this [index] = (ListViewItem) value;
2306 this [index] = new ListViewItem (value.ToString ());
2309 #endregion // Public Properties
2311 #region Public Methods
2312 public virtual ListViewItem Add (ListViewItem value)
2314 if (list.Contains (value))
2315 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2317 value.Owner = owner;
2320 if (owner.Sorting != SortOrder.None)
2323 owner.Redraw (true);
2328 public virtual ListViewItem Add (string text)
2330 ListViewItem item = new ListViewItem (text);
2331 return this.Add (item);
2334 public virtual ListViewItem Add (string text, int imageIndex)
2336 ListViewItem item = new ListViewItem (text, imageIndex);
2337 return this.Add (item);
2340 public void AddRange (ListViewItem [] values)
2343 owner.SelectedItems.list.Clear ();
2344 owner.SelectedIndices.list.Clear ();
2345 owner.CheckedItems.list.Clear ();
2346 owner.CheckedIndices.list.Clear ();
2348 foreach (ListViewItem item in values) {
2353 if (owner.Sorting != SortOrder.None)
2356 owner.Redraw (true);
2359 public virtual void Clear ()
2361 owner.SetFocusedItem (null);
2362 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2364 owner.SelectedItems.list.Clear ();
2365 owner.SelectedIndices.list.Clear ();
2366 owner.CheckedItems.list.Clear ();
2367 owner.CheckedIndices.list.Clear ();
2368 owner.Redraw (true);
2371 public bool Contains (ListViewItem item)
2373 return list.Contains (item);
2376 public void CopyTo (Array dest, int index)
2378 list.CopyTo (dest, index);
2381 public IEnumerator GetEnumerator ()
2383 return list.GetEnumerator ();
2386 int IList.Add (object item)
2391 if (item is ListViewItem) {
2392 li = (ListViewItem) item;
2393 if (list.Contains (li))
2394 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2397 li = new ListViewItem (item.ToString ());
2400 result = list.Add (li);
2401 owner.Redraw (true);
2406 bool IList.Contains (object item)
2408 return list.Contains (item);
2411 int IList.IndexOf (object item)
2413 return list.IndexOf (item);
2416 void IList.Insert (int index, object item)
2418 if (item is ListViewItem)
2419 this.Insert (index, (ListViewItem) item);
2421 this.Insert (index, item.ToString ());
2424 void IList.Remove (object item)
2426 Remove ((ListViewItem) item);
2429 public int IndexOf (ListViewItem item)
2431 return list.IndexOf (item);
2434 public ListViewItem Insert (int index, ListViewItem item)
2436 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2437 // but it's really only greater.
2438 if (index < 0 || index > list.Count)
2439 throw new ArgumentOutOfRangeException ("Index out of range.");
2441 if (list.Contains (item))
2442 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2445 list.Insert (index, item);
2446 owner.Redraw (true);
2450 public ListViewItem Insert (int index, string text)
2452 return this.Insert (index, new ListViewItem (text));
2455 public ListViewItem Insert (int index, string text, int imageIndex)
2457 return this.Insert (index, new ListViewItem (text, imageIndex));
2460 public virtual void Remove (ListViewItem item)
2462 if (!list.Contains (item))
2465 owner.SelectedItems.list.Remove (item);
2466 owner.SelectedIndices.list.Remove (item.Index);
2467 owner.CheckedItems.list.Remove (item);
2468 owner.CheckedIndices.list.Remove (item.Index);
2470 owner.Redraw (true);
2473 public virtual void RemoveAt (int index)
2475 if (index < 0 || index >= list.Count)
2476 throw new ArgumentOutOfRangeException ("Index out of range.");
2478 list.RemoveAt (index);
2479 owner.SelectedItems.list.RemoveAt (index);
2480 owner.SelectedIndices.list.RemoveAt (index);
2481 owner.CheckedItems.list.RemoveAt (index);
2482 owner.CheckedIndices.list.RemoveAt (index);
2483 owner.Redraw (false);
2485 #endregion // Public Methods
2487 } // ListViewItemCollection
2489 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2491 internal ArrayList list;
2492 private ListView owner;
2494 #region Public Constructor
2495 public SelectedIndexCollection (ListView owner)
2497 list = new ArrayList ();
2500 #endregion // Public Constructor
2502 #region Public Properties
2505 get { return list.Count; }
2508 public bool IsReadOnly {
2509 get { return true; }
2512 public int this [int index] {
2514 if (index < 0 || index >= list.Count)
2515 throw new ArgumentOutOfRangeException ("Index out of range.");
2516 return (int) list [index];
2520 bool ICollection.IsSynchronized {
2521 get { return list.IsSynchronized; }
2524 object ICollection.SyncRoot {
2525 get { return this; }
2528 bool IList.IsFixedSize {
2529 get { return true; }
2532 object IList.this [int index] {
2533 get { return this [index]; }
2534 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2536 #endregion // Public Properties
2538 #region Public Methods
2539 public bool Contains (int selectedIndex)
2541 return list.Contains (selectedIndex);
2544 public void CopyTo (Array dest, int index)
2546 list.CopyTo (dest, index);
2549 public IEnumerator GetEnumerator ()
2551 return list.GetEnumerator ();
2554 int IList.Add (object value)
2556 throw new NotSupportedException ("Add operation is not supported.");
2561 throw new NotSupportedException ("Clear operation is not supported.");
2564 bool IList.Contains (object selectedIndex)
2566 return list.Contains (selectedIndex);
2569 int IList.IndexOf (object selectedIndex)
2571 return list.IndexOf (selectedIndex);
2574 void IList.Insert (int index, object value)
2576 throw new NotSupportedException ("Insert operation is not supported.");
2579 void IList.Remove (object value)
2581 throw new NotSupportedException ("Remove operation is not supported.");
2584 void IList.RemoveAt (int index)
2586 throw new NotSupportedException ("RemoveAt operation is not supported.");
2589 public int IndexOf (int selectedIndex)
2591 return list.IndexOf (selectedIndex);
2593 #endregion // Public Methods
2595 } // SelectedIndexCollection
2597 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2599 internal ArrayList list;
2600 private ListView owner;
2602 #region Public Constructor
2603 public SelectedListViewItemCollection (ListView owner)
2605 list = new ArrayList ();
2608 #endregion // Public Constructor
2610 #region Public Properties
2613 get { return list.Count; }
2616 public bool IsReadOnly {
2617 get { return true; }
2620 public ListViewItem this [int index] {
2622 if (index < 0 || index >= list.Count)
2623 throw new ArgumentOutOfRangeException ("Index out of range.");
2624 return (ListViewItem) list [index];
2628 bool ICollection.IsSynchronized {
2629 get { return list.IsSynchronized; }
2632 object ICollection.SyncRoot {
2633 get { return this; }
2636 bool IList.IsFixedSize {
2637 get { return true; }
2640 object IList.this [int index] {
2641 get { return this [index]; }
2642 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2644 #endregion // Public Properties
2646 #region Public Methods
2647 public void Clear ()
2649 ArrayList copy = (ArrayList) list.Clone ();
2650 for (int i = 0; i < copy.Count; i++)
2651 ((ListViewItem) copy [i]).Selected = false;
2656 public bool Contains (ListViewItem item)
2658 return list.Contains (item);
2661 public void CopyTo (Array dest, int index)
2663 list.CopyTo (dest, index);
2666 public IEnumerator GetEnumerator ()
2668 return list.GetEnumerator ();
2671 int IList.Add (object value)
2673 throw new NotSupportedException ("Add operation is not supported.");
2676 bool IList.Contains (object item)
2678 return list.Contains (item);
2681 int IList.IndexOf (object item)
2683 return list.IndexOf (item);
2686 void IList.Insert (int index, object value)
2688 throw new NotSupportedException ("Insert operation is not supported.");
2691 void IList.Remove (object value)
2693 throw new NotSupportedException ("Remove operation is not supported.");
2696 void IList.RemoveAt (int index)
2698 throw new NotSupportedException ("RemoveAt operation is not supported.");
2701 public int IndexOf (ListViewItem item)
2703 return list.IndexOf (item);
2705 #endregion // Public Methods
2707 } // SelectedListViewItemCollection
2709 #endregion // Subclasses