1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2005 Novell, Inc. (http://www.novell.com)
23 // Ravindra Kumar (rkumar@novell.com)
24 // Jordi Mas i Hernandez, jordi@ximian.com
25 // Mike Kestner (mkestner@novell.com)
28 // - Feedback for item activation, change in cursor types as mouse moves.
37 using System.Collections;
38 using System.ComponentModel;
39 using System.ComponentModel.Design;
41 using System.Runtime.InteropServices;
42 using System.Globalization;
44 namespace System.Windows.Forms
46 [DefaultEvent ("SelectedIndexChanged")]
47 [DefaultProperty ("Items")]
48 [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
49 public class ListView : Control
51 private ItemActivation activation = ItemActivation.Standard;
52 private ListViewAlignment alignment = ListViewAlignment.Top;
53 private bool allow_column_reorder = false;
54 private bool auto_arrange = true;
55 private bool check_boxes = false;
56 private CheckedIndexCollection checked_indices;
57 private CheckedListViewItemCollection checked_items;
58 private ColumnHeaderCollection columns;
59 internal ListViewItem focused_item;
60 private bool full_row_select = false;
61 private bool grid_lines = false;
62 private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
63 private bool hide_selection = true;
64 private bool hover_selection = false;
65 private IComparer item_sorter;
66 private ListViewItemCollection items;
67 private bool label_edit = false;
68 private bool label_wrap = true;
69 private bool multiselect = true;
70 private bool scrollable = true;
71 private SelectedIndexCollection selected_indices;
72 private SelectedListViewItemCollection selected_items;
73 private SortOrder sort_order = SortOrder.None;
74 private ImageList state_image_list;
75 private bool updating = false;
76 private View view = View.LargeIcon;
77 private int layout_wd; // We might draw more than our client area
78 private int layout_ht; // therefore we need to have these two.
79 //private TextBox editor; // Used for editing an item text
80 HeaderControl header_control;
81 internal ItemControl item_control;
82 internal ScrollBar h_scroll; // used for scrolling horizontally
83 internal ScrollBar v_scroll; // used for scrolling vertically
84 internal int h_marker; // Position markers for scrolling
85 internal int v_marker;
86 private int keysearch_tickcnt;
87 private string keysearch_text;
88 static private readonly int keysearch_keydelay = 1000;
89 private int[] reordered_column_indices;
92 internal ImageList large_image_list;
93 internal ImageList small_image_list;
94 internal Size text_size = Size.Empty;
97 public event LabelEditEventHandler AfterLabelEdit;
100 [EditorBrowsable (EditorBrowsableState.Never)]
101 public new event EventHandler BackgroundImageChanged {
102 add { base.BackgroundImageChanged += value; }
103 remove { base.BackgroundImageChanged -= value; }
106 public event LabelEditEventHandler BeforeLabelEdit;
107 public event ColumnClickEventHandler ColumnClick;
108 public event EventHandler ItemActivate;
109 public event ItemCheckEventHandler ItemCheck;
110 public event ItemDragEventHandler ItemDrag;
113 [EditorBrowsable (EditorBrowsableState.Never)]
114 public new event PaintEventHandler Paint {
115 add { base.Paint += value; }
116 remove { base.Paint -= value; }
119 public event EventHandler SelectedIndexChanged;
122 [EditorBrowsable (EditorBrowsableState.Never)]
123 public new event EventHandler TextChanged {
124 add { base.TextChanged += value; }
125 remove { base.TextChanged -= value; }
130 #region Public Constructors
133 background_color = ThemeEngine.Current.ColorWindow;
134 checked_indices = new CheckedIndexCollection (this);
135 checked_items = new CheckedListViewItemCollection (this);
136 columns = new ColumnHeaderCollection (this);
137 foreground_color = SystemColors.WindowText;
138 items = new ListViewItemCollection (this);
139 selected_indices = new SelectedIndexCollection (this);
140 selected_items = new SelectedListViewItemCollection (this);
142 border_style = BorderStyle.Fixed3D;
144 header_control = new HeaderControl (this);
145 header_control.Visible = false;
146 item_control = new ItemControl (this);
147 item_control.Visible = true;
149 h_scroll = new HScrollBar ();
150 v_scroll = new VScrollBar ();
151 h_marker = v_marker = 0;
152 keysearch_tickcnt = 0;
154 // scroll bars are disabled initially
155 h_scroll.Visible = false;
156 h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
157 v_scroll.Visible = false;
158 v_scroll.ValueChanged += new EventHandler(VerticalScroller);
161 base.KeyDown += new KeyEventHandler(ListView_KeyDown);
162 base.Paint += new PaintEventHandler (ListView_Paint);
163 SizeChanged += new EventHandler (ListView_SizeChanged);
165 this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
167 #endregion // Public Constructors
169 #region Private Internal Properties
170 internal Size CheckBoxSize {
172 if (this.check_boxes) {
173 if (this.state_image_list != null)
174 return this.state_image_list.ImageSize;
176 return ThemeEngine.Current.ListViewCheckBoxSize;
182 internal bool CanMultiselect {
184 if (multiselect && (XplatUI.State.ModifierKeys & (Keys.Control | Keys.Shift)) != 0)
191 #endregion // Private Internal Properties
193 #region Protected Properties
194 protected override CreateParams CreateParams {
195 get { return base.CreateParams; }
198 protected override Size DefaultSize {
199 get { return ThemeEngine.Current.ListViewDefaultSize; }
201 #endregion // Protected Properties
203 #region Public Instance Properties
204 [DefaultValue (ItemActivation.Standard)]
205 public ItemActivation Activation {
206 get { return activation; }
208 if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
209 value != ItemActivation.TwoClick) {
210 throw new InvalidEnumArgumentException (string.Format
211 ("Enum argument value '{0}' is not valid for Activation", value));
218 [DefaultValue (ListViewAlignment.Top)]
220 public ListViewAlignment Alignment {
221 get { return alignment; }
223 if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
224 value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
225 throw new InvalidEnumArgumentException (string.Format
226 ("Enum argument value '{0}' is not valid for Alignment", value));
229 if (this.alignment != value) {
231 // alignment does not matter in Details/List views
232 if (this.view == View.LargeIcon ||
233 this.View == View.SmallIcon)
239 [DefaultValue (false)]
240 public bool AllowColumnReorder {
241 get { return allow_column_reorder; }
242 set { allow_column_reorder = value; }
245 [DefaultValue (true)]
246 public bool AutoArrange {
247 get { return auto_arrange; }
249 if (auto_arrange != value) {
250 auto_arrange = value;
251 // autoarrange does not matter in Details/List views
252 if (this.view == View.LargeIcon || this.View == View.SmallIcon)
258 public override Color BackColor {
260 if (background_color.IsEmpty)
261 return ThemeEngine.Current.ColorWindow;
263 return background_color;
265 set { background_color = value; }
269 [EditorBrowsable (EditorBrowsableState.Never)]
270 public override Image BackgroundImage {
271 get { return background_image; }
273 if (value == background_image)
276 background_image = value;
277 OnBackgroundImageChanged (EventArgs.Empty);
281 [DefaultValue (BorderStyle.Fixed3D)]
283 public BorderStyle BorderStyle {
284 get { return InternalBorderStyle; }
285 set { InternalBorderStyle = value; }
288 [DefaultValue (false)]
289 public bool CheckBoxes {
290 get { return check_boxes; }
292 if (check_boxes != value) {
300 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
301 public CheckedIndexCollection CheckedIndices {
302 get { return checked_indices; }
306 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
307 public CheckedListViewItemCollection CheckedItems {
308 get { return checked_items; }
311 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
313 [MergableProperty (false)]
314 public ColumnHeaderCollection Columns {
315 get { return columns; }
319 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
320 public ListViewItem FocusedItem {
322 if (focused_item == null && Focused && items.Count > 0)
323 focused_item = items [0];
328 public override Color ForeColor {
330 if (foreground_color.IsEmpty)
331 return ThemeEngine.Current.ColorWindowText;
333 return foreground_color;
335 set { foreground_color = value; }
338 [DefaultValue (false)]
339 public bool FullRowSelect {
340 get { return full_row_select; }
341 set { full_row_select = value; }
344 [DefaultValue (false)]
345 public bool GridLines {
346 get { return grid_lines; }
348 if (grid_lines != value) {
355 [DefaultValue (ColumnHeaderStyle.Clickable)]
356 public ColumnHeaderStyle HeaderStyle {
357 get { return header_style; }
359 if (header_style == value)
363 case ColumnHeaderStyle.Clickable:
364 case ColumnHeaderStyle.Nonclickable:
365 case ColumnHeaderStyle.None:
368 throw new InvalidEnumArgumentException (string.Format
369 ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
372 header_style = value;
373 if (view == View.Details)
378 [DefaultValue (true)]
379 public bool HideSelection {
380 get { return hide_selection; }
382 if (hide_selection != value) {
383 hide_selection = value;
389 [DefaultValue (false)]
390 public bool HoverSelection {
391 get { return hover_selection; }
392 set { hover_selection = value; }
395 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
397 [MergableProperty (false)]
398 public ListViewItemCollection Items {
399 get { return items; }
402 [DefaultValue (false)]
403 public bool LabelEdit {
404 get { return label_edit; }
405 set { label_edit = value; }
408 [DefaultValue (true)]
410 public bool LabelWrap {
411 get { return label_wrap; }
413 if (label_wrap != value) {
420 [DefaultValue (null)]
421 public ImageList LargeImageList {
422 get { return large_image_list; }
424 large_image_list = value;
430 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
431 public IComparer ListViewItemSorter {
432 get { return item_sorter; }
433 set { item_sorter = value; }
436 [DefaultValue (true)]
437 public bool MultiSelect {
438 get { return multiselect; }
439 set { multiselect = value; }
442 [DefaultValue (true)]
443 public bool Scrollable {
444 get { return scrollable; }
446 if (scrollable != value) {
454 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
455 public SelectedIndexCollection SelectedIndices {
456 get { return selected_indices; }
460 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
461 public SelectedListViewItemCollection SelectedItems {
462 get { return selected_items; }
465 [DefaultValue (null)]
466 public ImageList SmallImageList {
467 get { return small_image_list; }
469 small_image_list = value;
474 [DefaultValue (SortOrder.None)]
475 public SortOrder Sorting {
476 get { return sort_order; }
478 if (value != SortOrder.Ascending && value != SortOrder.Descending &&
479 value != SortOrder.None) {
480 throw new InvalidEnumArgumentException (string.Format
481 ("Enum argument value '{0}' is not valid for Sorting", value));
484 if (sort_order != value) {
491 [DefaultValue (null)]
492 public ImageList StateImageList {
493 get { return state_image_list; }
495 state_image_list = value;
502 [EditorBrowsable (EditorBrowsableState.Never)]
503 public override string Text {
512 OnTextChanged (EventArgs.Empty);
517 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
518 public ListViewItem TopItem {
521 if (this.items.Count == 0)
523 // if contents are not scrolled
524 // it is the first item
525 else if (h_marker == 0 && v_marker == 0)
526 return this.items [0];
527 // do a hit test for the scrolled position
529 foreach (ListViewItem item in this.items) {
530 if (item.Bounds.X >= 0 && item.Bounds.Y >= 0)
538 [DefaultValue (View.LargeIcon)]
542 if (value != View.Details && value != View.LargeIcon &&
543 value != View.List && value != View.SmallIcon ) {
544 throw new InvalidEnumArgumentException (string.Format
545 ("Enum argument value '{0}' is not valid for View", value));
549 h_scroll.Value = v_scroll.Value = 0;
555 #endregion // Public Instance Properties
557 #region Internal Methods Properties
559 internal int FirstVisibleIndex {
562 if (this.items.Count == 0)
565 if (h_marker == 0 && v_marker == 0)
568 foreach (ListViewItem item in this.items) {
569 if (item.Bounds.Right >= 0 && item.Bounds.Bottom >= 0)
578 internal int LastVisibleIndex {
580 for (int i = FirstVisibleIndex; i < Items.Count; i++) {
581 if (Items[i].Bounds.Y > ClientRectangle.Bottom)
585 return Items.Count - 1;
589 internal int TotalWidth {
590 get { return Math.Max (this.Width, this.layout_wd); }
593 internal int TotalHeight {
594 get { return Math.Max (this.Height, this.layout_ht); }
597 internal void Redraw (bool recalculate)
599 // Avoid calculations when control is being updated
604 CalculateListView (this.alignment);
609 internal Size GetChildColumnSize (int index)
611 Size ret_size = Size.Empty;
612 ColumnHeader col = this.columns [index];
614 if (col.Width == -2) { // autosize = max(items, columnheader)
615 Size size = Size.Ceiling (this.DeviceContext.MeasureString
616 (col.Text, this.Font));
617 ret_size = BiggestItem (index);
618 if (size.Width > ret_size.Width)
621 else { // -1 and all the values < -2 are put under one category
622 ret_size = BiggestItem (index);
623 // fall back to empty columns' width if no subitem is available for a column
624 if (ret_size.IsEmpty) {
625 ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
626 if (col.Text.Length > 0)
627 ret_size.Height = Size.Ceiling (this.DeviceContext.MeasureString
628 (col.Text, this.Font)).Height;
630 ret_size.Height = this.Font.Height;
634 // adjust the size for icon and checkbox for 0th column
636 ret_size.Width += (this.CheckBoxSize.Width + 4);
637 if (this.small_image_list != null)
638 ret_size.Width += this.small_image_list.ImageSize.Width;
643 // Returns the size of biggest item text in a column.
644 private Size BiggestItem (int col)
646 Size temp = Size.Empty;
647 Size ret_size = Size.Empty;
649 // 0th column holds the item text, we check the size of
650 // the various subitems falling in that column and get
651 // the biggest one's size.
652 foreach (ListViewItem item in items) {
653 if (col >= item.SubItems.Count)
656 temp = Size.Ceiling (this.DeviceContext.MeasureString
657 (item.SubItems [col].Text, this.Font));
658 if (temp.Width > ret_size.Width)
662 // adjustment for space
663 if (!ret_size.IsEmpty)
669 // Sets the size of the biggest item text as per the view
670 private void CalcTextSize ()
672 // clear the old value
673 text_size = Size.Empty;
675 if (items.Count == 0)
678 text_size = BiggestItem (0);
680 if (view == View.LargeIcon && this.label_wrap) {
681 Size temp = Size.Empty;
682 if (this.check_boxes)
683 temp.Width += 2 * this.CheckBoxSize.Width;
684 if (large_image_list != null)
685 temp.Width += large_image_list.ImageSize.Width;
688 // wrapping is done for two lines only
689 if (text_size.Width > temp.Width) {
690 text_size.Width = temp.Width;
691 text_size.Height *= 2;
694 else if (view == View.List) {
695 // in list view max text shown in determined by the
696 // control width, even if scolling is enabled.
697 int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
698 if (this.small_image_list != null)
699 max_wd -= this.small_image_list.ImageSize.Width;
701 if (text_size.Width > max_wd)
702 text_size.Width = max_wd;
705 // we do the default settings, if we have got 0's
706 if (text_size.Height <= 0)
707 text_size.Height = this.Font.Height;
708 if (text_size.Width <= 0)
709 text_size.Width = this.Width;
712 text_size.Width += 4;
713 text_size.Height += 2;
716 private void Scroll (ScrollBar scrollbar, int delta)
718 if (delta == 0 || !scrollbar.Visible)
722 if (scrollbar == h_scroll)
723 max = h_scroll.Maximum - item_control.Width;
725 max = v_scroll.Maximum - item_control.Height;
727 int val = scrollbar.Value + delta;
730 else if (val < scrollbar.Minimum)
731 val = scrollbar.Minimum;
732 scrollbar.Value = val;
735 private void CalculateScrollBars ()
737 Rectangle client_area = ClientRectangle;
739 if (!this.scrollable || this.items.Count <= 0) {
740 h_scroll.Visible = false;
741 v_scroll.Visible = false;
745 // making a scroll bar visible might make
746 // other scroll bar visible
747 if (layout_wd > client_area.Right) {
748 h_scroll.Visible = true;
749 if ((layout_ht + h_scroll.Height) > client_area.Bottom)
750 v_scroll.Visible = true;
752 v_scroll.Visible = false;
753 } else if (layout_ht > client_area.Bottom) {
754 v_scroll.Visible = true;
755 if ((layout_wd + v_scroll.Width) > client_area.Right)
756 h_scroll.Visible = true;
758 h_scroll.Visible = false;
760 h_scroll.Visible = false;
761 v_scroll.Visible = false;
764 item_control.Height = ClientRectangle.Height - header_control.Height;
766 if (h_scroll.Visible) {
767 h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
768 h_scroll.Minimum = 0;
770 // if v_scroll is visible, adjust the maximum of the
771 // h_scroll to account for the width of v_scroll
772 if (v_scroll.Visible) {
773 h_scroll.Maximum = layout_wd + v_scroll.Width;
774 h_scroll.Width = client_area.Width - v_scroll.Width;
777 h_scroll.Maximum = layout_wd;
778 h_scroll.Width = client_area.Width;
781 h_scroll.LargeChange = client_area.Width;
782 h_scroll.SmallChange = Font.Height;
783 item_control.Height -= h_scroll.Height;
786 if (header_control.Visible)
787 header_control.Width = ClientRectangle.Width;
788 item_control.Width = ClientRectangle.Width;
790 if (v_scroll.Visible) {
791 v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
792 v_scroll.Minimum = 0;
794 // if h_scroll is visible, adjust the maximum of the
795 // v_scroll to account for the height of h_scroll
796 if (h_scroll.Visible) {
797 v_scroll.Maximum = layout_ht + h_scroll.Height;
798 v_scroll.Height = client_area.Height; // - h_scroll.Height already done
800 v_scroll.Maximum = layout_ht;
801 v_scroll.Height = client_area.Height;
804 v_scroll.LargeChange = client_area.Height;
805 v_scroll.SmallChange = Font.Height;
806 if (header_control.Visible)
807 header_control.Width -= v_scroll.Width;
808 item_control.Width -= v_scroll.Width;
812 ColumnHeader GetReorderedColumn (int index)
814 if (reordered_column_indices == null)
815 return Columns [index];
817 return Columns [reordered_column_indices [index]];
820 void ReorderColumn (ColumnHeader col, int index)
822 if (reordered_column_indices == null) {
823 reordered_column_indices = new int [Columns.Count];
824 for (int i = 0; i < Columns.Count; i++)
825 reordered_column_indices [i] = i;
828 if (reordered_column_indices [index] == col.Index)
831 int[] curr = reordered_column_indices;
832 int[] result = new int [Columns.Count];
834 for (int i = 0; i < Columns.Count; i++) {
835 if (curr_idx < Columns.Count && curr [curr_idx] == col.Index)
839 result [i] = col.Index;
841 result [i] = curr [curr_idx++];
844 reordered_column_indices = result;
846 header_control.Invalidate ();
847 item_control.Invalidate ();
850 Size LargeIconItemSize {
852 int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
853 int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
854 int w = CheckBoxSize.Width + 2 + Math.Max (text_size.Width, image_w);
855 int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
856 return new Size (w, h);
860 Size SmallIconItemSize {
862 int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
863 int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
864 int w = text_size.Width + 2 + CheckBoxSize.Width + image_w;
865 int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
866 return new Size (w, h);
872 ListViewItem[,] item_matrix;
874 void LayoutIcons (bool large_icons, bool left_aligned, int x_spacing, int y_spacing)
876 header_control.Visible = false;
877 header_control.Size = Size.Empty;
878 item_control.Location = Point.Empty;
880 if (items.Count == 0)
883 Size sz = large_icons ? LargeIconItemSize : SmallIconItemSize;
885 Rectangle area = ClientRectangle;
888 rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(sz.Height + y_spacing));
891 cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
893 cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(sz.Width + x_spacing));
896 rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
899 layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
900 layout_wd = cols * (sz.Width + x_spacing) - x_spacing;
901 item_matrix = new ListViewItem [rows, cols];
904 foreach (ListViewItem item in items) {
905 int x = col * (sz.Width + x_spacing);
906 int y = row * (sz.Height + y_spacing);
907 item.Location = new Point (x, y);
911 item_matrix [row, col] = item;
925 item_control.Size = new Size (layout_wd, layout_ht);
930 if (columns.Count == 0 || header_style == ColumnHeaderStyle.None) {
931 header_control.Visible = false;
932 header_control.Size = Size.Empty;
937 for (int i = 0; i < Columns.Count; i++) {
938 ColumnHeader col = GetReorderedColumn (i);
941 col.CalcColumnHeader ();
945 header_control.Width = x;
946 header_control.Height = columns [0].Ht;
947 header_control.Visible = true;
950 void LayoutDetails ()
954 item_control.Location = new Point (0, header_control.Height);
957 if (items.Count > 0) {
958 foreach (ListViewItem item in items) {
960 item.Location = new Point (0, y);
961 y += item.Bounds.Height + 2;
964 // some space for bottom gridline
969 layout_wd = Math.Max (header_control.Width, item_control.Width);
970 layout_ht = y + header_control.Height;
973 private void CalculateListView (ListViewAlignment align)
983 LayoutIcons (false, alignment == ListViewAlignment.Left, 4, 2);
987 LayoutIcons (true, alignment == ListViewAlignment.Left,
988 ThemeEngine.Current.ListViewHorizontalSpacing,
989 ThemeEngine.Current.ListViewVerticalSpacing);
993 LayoutIcons (false, true, 4, 2);
997 CalculateScrollBars ();
1000 internal void UpdateSelection (ListViewItem item)
1002 if (item.Selected) {
1004 if (!CanMultiselect && SelectedItems.Count > 0) {
1005 SelectedItems.Clear ();
1006 SelectedIndices.list.Clear ();
1009 if (!SelectedItems.Contains (item)) {
1010 SelectedItems.list.Add (item);
1011 SelectedIndices.list.Add (item.Index);
1014 SelectedItems.list.Remove (item);
1015 SelectedIndices.list.Remove (item.Index);
1019 private bool KeySearchString (KeyEventArgs ke)
1021 int current_tickcnt = Environment.TickCount;
1022 if (keysearch_tickcnt > 0 && current_tickcnt - keysearch_tickcnt > keysearch_keydelay) {
1023 keysearch_text = string.Empty;
1026 keysearch_text += (char) ke.KeyData;
1027 keysearch_tickcnt = current_tickcnt;
1029 int start = FocusedItem == null ? 0 : FocusedItem.Index;
1032 if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (Items[i].Text, keysearch_text,
1033 CompareOptions.IgnoreCase)) {
1034 SetFocusedItem (Items [i]);
1035 items [i].Selected = true;
1039 i = (i + 1 < Items.Count) ? i+1 : 0;
1047 int GetAdjustedIndex (Keys key)
1051 if (View == View.Details) {
1053 result = FocusedItem.Index - 1;
1054 else if (key == Keys.Down) {
1055 result = FocusedItem.Index + 1;
1056 if (result == items.Count)
1062 int row = FocusedItem.row;
1063 int col = FocusedItem.col;
1069 return item_matrix [row, col - 1].Index;
1072 if (col == (cols - 1))
1074 while (item_matrix [row, col + 1] == null)
1076 return item_matrix [row, col + 1].Index;
1081 return item_matrix [row - 1, col].Index;
1084 if (row == (rows - 1))
1086 while (item_matrix [row + 1, col] == null)
1088 return item_matrix [row + 1, col].Index;
1095 ListViewItem selection_start;
1097 private void SelectItems (ArrayList sel_items)
1099 SelectedItems.Clear ();
1100 SelectedIndices.list.Clear ();
1101 foreach (ListViewItem item in sel_items)
1102 item.Selected = true;
1105 private void UpdateMultiSelection (int index)
1107 bool shift_pressed = (XplatUI.State.ModifierKeys & Keys.Shift) != 0;
1108 bool ctrl_pressed = (XplatUI.State.ModifierKeys & Keys.Control) != 0;
1109 ListViewItem item = items [index];
1111 if (shift_pressed && selection_start != null) {
1112 ArrayList list = new ArrayList ();
1113 int start = Math.Min (selection_start.Index, index);
1114 int end = Math.Max (selection_start.Index, index);
1115 if (View == View.Details) {
1116 for (int i = start; i <= end; i++)
1117 list.Add (items [i]);
1119 int left = Math.Min (items [start].col, items [end].col);
1120 int right = Math.Max (items [start].col, items [end].col);
1121 int top = Math.Min (items [start].row, items [end].row);
1122 int bottom = Math.Max (items [start].row, items [end].row);
1123 foreach (ListViewItem curr in items)
1124 if (curr.row >= top && curr.row <= bottom &&
1125 curr.col >= left && curr.col <= right)
1129 } else if (!ctrl_pressed) {
1130 SelectedItems.Clear ();
1131 SelectedIndices.list.Clear ();
1132 item.Selected = true;
1133 selection_start = item;
1137 private void ListView_KeyDown (object sender, KeyEventArgs ke)
1139 if (ke.Handled || Items.Count == 0)
1145 switch (ke.KeyCode) {
1148 index = Items.Count - 1;
1159 index = GetAdjustedIndex (ke.KeyCode);
1163 ke.Handled = KeySearchString (ke);
1171 UpdateMultiSelection (index);
1173 items [index].Selected = true;
1175 SetFocusedItem (items [index]);
1176 EnsureVisible (index);
1180 internal class ItemControl : Control {
1183 ListViewItem clicked_item;
1184 ListViewItem last_clicked_item;
1185 bool hover_processed = false;
1187 public ItemControl (ListView owner)
1190 DoubleClick += new EventHandler(ItemsDoubleClick);
1191 KeyDown += new KeyEventHandler (ItemsKeyDown);
1192 KeyUp += new KeyEventHandler (ItemsKeyUp);
1193 MouseDown += new MouseEventHandler(ItemsMouseDown);
1194 MouseMove += new MouseEventHandler(ItemsMouseMove);
1195 MouseHover += new EventHandler(ItemsMouseHover);
1196 MouseUp += new MouseEventHandler(ItemsMouseUp);
1197 MouseWheel += new MouseEventHandler(ItemsMouseWheel);
1198 Paint += new PaintEventHandler (ItemsPaint);
1201 void ItemsDoubleClick (object sender, EventArgs e)
1203 if (owner.activation == ItemActivation.Standard && owner.ItemActivate != null)
1204 owner.ItemActivate (this, e);
1207 void ItemsKeyDown (object sender, KeyEventArgs args)
1209 owner.OnKeyDown (args);
1212 void ItemsKeyUp (object sender, KeyEventArgs args)
1214 owner.OnKeyUp (args);
1217 private void ItemsMouseDown (object sender, MouseEventArgs me)
1219 if (owner.items.Count == 0)
1222 Point pt = new Point (me.X, me.Y);
1223 foreach (ListViewItem item in owner.items) {
1224 if (item.CheckRectReal.Contains (pt)) {
1225 CheckState curr_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1226 item.Checked = !item.Checked;
1228 CheckState new_state = item.Checked ? CheckState.Checked : CheckState.Unchecked;
1230 // Raise the ItemCheck event
1231 ItemCheckEventArgs ice = new ItemCheckEventArgs (item.Index, curr_state, new_state);
1232 owner.OnItemCheck (ice);
1236 if (owner.View == View.Details && !owner.FullRowSelect) {
1237 if (item.GetBounds (ItemBoundsPortion.Label).Contains (pt)) {
1238 clicked_item = item;
1242 if (item.Bounds.Contains (pt)) {
1243 clicked_item = item;
1249 owner.SetFocusedItem (clicked_item);
1251 if (clicked_item != null) {
1252 bool changed = !clicked_item.Selected;
1253 if (owner.MultiSelect && (XplatUI.State.ModifierKeys & Keys.Control) == 0)
1254 owner.UpdateMultiSelection (clicked_item.Index);
1256 clicked_item.Selected = true;
1259 owner.OnSelectedIndexChanged (EventArgs.Empty);
1261 // Raise double click if the item was clicked. On MS the
1262 // double click is only raised if you double click an item
1263 if (me.Clicks > 1 && clicked_item != null)
1264 owner.OnDoubleClick (EventArgs.Empty);
1265 else if (me.Clicks == 1 && clicked_item != null)
1266 owner.OnClick (EventArgs.Empty);
1267 } else if (owner.selected_indices.Count > 0) {
1268 // Raise the event if there was at least one item
1269 // selected and the user click on a dead area (unselecting all)
1270 owner.SelectedItems.Clear ();
1271 owner.SelectedIndices.list.Clear ();
1272 owner.OnSelectedIndexChanged (EventArgs.Empty);
1276 private void ItemsMouseMove (object sender, MouseEventArgs me)
1278 if (owner.HoverSelection && hover_processed) {
1280 Point pt = PointToClient (Control.MousePosition);
1281 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1282 if (item == null || item.Selected)
1285 hover_processed = false;
1286 XplatUI.ResetMouseHover (Handle);
1291 private void ItemsMouseHover (object sender, EventArgs e)
1293 if (Capture || !owner.HoverSelection)
1296 hover_processed = true;
1297 Point pt = PointToClient (Control.MousePosition);
1298 ListViewItem item = owner.GetItemAt (pt.X, pt.Y);
1303 item.Selected = true;
1304 owner.OnSelectedIndexChanged (new EventArgs ());
1307 private void ItemsMouseUp (object sender, MouseEventArgs me)
1310 if (owner.Items.Count == 0)
1313 Point pt = new Point (me.X, me.Y);
1315 Rectangle rect = Rectangle.Empty;
1316 if (clicked_item != null) {
1317 if (owner.view == View.Details && !owner.full_row_select)
1318 rect = clicked_item.GetBounds (ItemBoundsPortion.Label);
1320 rect = clicked_item.Bounds;
1322 if (rect.Contains (pt)) {
1323 switch (owner.activation) {
1324 case ItemActivation.OneClick:
1325 owner.OnItemActivate (EventArgs.Empty);
1328 case ItemActivation.TwoClick:
1329 if (last_clicked_item == clicked_item) {
1330 owner.OnItemActivate (EventArgs.Empty);
1331 last_clicked_item = null;
1333 last_clicked_item = clicked_item;
1336 // DoubleClick activation is handled in another handler
1342 clicked_item = null;
1345 private void ItemsMouseWheel (object sender, MouseEventArgs me)
1347 if (owner.Items.Count == 0)
1350 int lines = me.Delta / 120;
1355 switch (owner.View) {
1357 case View.SmallIcon:
1358 owner.Scroll (owner.v_scroll, -owner.Items [0].Bounds.Height * SystemInformation.MouseWheelScrollLines * lines);
1360 case View.LargeIcon:
1361 owner.Scroll (owner.v_scroll, -(owner.Items [0].Bounds.Height + ThemeEngine.Current.ListViewVerticalSpacing) * lines);
1364 owner.Scroll (owner.h_scroll, -owner.Items [0].Bounds.Width * lines);
1369 private void ItemsPaint (object sender, PaintEventArgs pe)
1371 ThemeEngine.Current.DrawListViewItems (pe.Graphics, pe.ClipRectangle, owner);
1375 private void ListView_Paint (object sender, PaintEventArgs pe)
1377 if (Width <= 0 || Height <= 0 || !Visible || updating)
1380 CalculateScrollBars ();
1383 private void ListView_SizeChanged (object sender, EventArgs e)
1385 CalculateListView (alignment);
1388 private void SetFocusedItem (ListViewItem item)
1390 if (focused_item != null)
1391 focused_item.Focused = false;
1394 item.Focused = true;
1396 focused_item = item;
1399 private void HorizontalScroller (object sender, EventArgs e)
1401 // Avoid unnecessary flickering, when button is
1402 // kept pressed at the end
1403 if (h_marker != h_scroll.Value) {
1405 int pixels = h_marker - h_scroll.Value;
1407 h_marker = h_scroll.Value;
1408 if (header_control.Visible)
1409 XplatUI.ScrollWindow (header_control.Handle, pixels, 0, false);
1411 XplatUI.ScrollWindow (item_control.Handle, pixels, 0, false);
1415 private void VerticalScroller (object sender, EventArgs e)
1417 // Avoid unnecessary flickering, when button is
1418 // kept pressed at the end
1419 if (v_marker != v_scroll.Value) {
1420 int pixels = v_marker - v_scroll.Value;
1421 Rectangle area = item_control.ClientRectangle;
1422 v_marker = v_scroll.Value;
1423 XplatUI.ScrollWindow (item_control.Handle, area, 0, pixels, false);
1426 #endregion // Internal Methods Properties
1428 #region Protected Methods
1429 protected override void CreateHandle ()
1431 base.CreateHandle ();
1434 protected override void Dispose (bool disposing)
1437 h_scroll.Dispose ();
1438 v_scroll.Dispose ();
1440 large_image_list = null;
1441 small_image_list = null;
1442 state_image_list = null;
1445 base.Dispose (disposing);
1448 protected override bool IsInputKey (Keys keyData)
1465 return base.IsInputKey (keyData);
1468 protected virtual void OnAfterLabelEdit (LabelEditEventArgs e)
1470 if (AfterLabelEdit != null)
1471 AfterLabelEdit (this, e);
1474 protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e)
1476 if (BeforeLabelEdit != null)
1477 BeforeLabelEdit (this, e);
1480 protected virtual void OnColumnClick (ColumnClickEventArgs e)
1482 if (ColumnClick != null)
1483 ColumnClick (this, e);
1486 protected override void OnEnabledChanged (EventArgs e)
1488 base.OnEnabledChanged (e);
1491 protected override void OnFontChanged (EventArgs e)
1493 base.OnFontChanged (e);
1497 protected override void OnHandleCreated (EventArgs e)
1499 base.OnHandleCreated (e);
1501 Controls.AddImplicit (header_control);
1502 Controls.AddImplicit (item_control);
1503 Controls.AddImplicit (this.v_scroll);
1504 Controls.AddImplicit (this.h_scroll);
1508 protected override void OnHandleDestroyed (EventArgs e)
1510 base.OnHandleDestroyed (e);
1513 protected virtual void OnItemActivate (EventArgs e)
1515 if (ItemActivate != null)
1516 ItemActivate (this, e);
1519 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
1521 if (ItemCheck != null)
1522 ItemCheck (this, ice);
1525 protected virtual void OnItemDrag (ItemDragEventArgs e)
1527 if (ItemDrag != null)
1531 protected virtual void OnSelectedIndexChanged (EventArgs e)
1533 if (SelectedIndexChanged != null)
1534 SelectedIndexChanged (this, e);
1537 protected override void OnSystemColorsChanged (EventArgs e)
1539 base.OnSystemColorsChanged (e);
1542 protected void RealizeProperties ()
1547 protected void UpdateExtendedStyles ()
1552 protected override void WndProc (ref Message m)
1554 base.WndProc (ref m);
1556 #endregion // Protected Methods
1558 #region Public Instance Methods
1559 public void ArrangeIcons ()
1561 ArrangeIcons (this.alignment);
1564 public void ArrangeIcons (ListViewAlignment alignment)
1566 // Icons are arranged only if view is set to LargeIcon or SmallIcon
1567 if (view == View.LargeIcon || view == View.SmallIcon) {
1568 this.CalculateListView (alignment);
1569 // we have done the calculations already
1570 this.Redraw (false);
1574 public void BeginUpdate ()
1576 // flag to avoid painting
1580 public void Clear ()
1583 items.Clear (); // Redraw (true) called here
1586 public void EndUpdate ()
1588 // flag to avoid painting
1591 // probably, now we need a redraw with recalculations
1595 public void EnsureVisible (int index)
1597 if (index < 0 || index >= items.Count || scrollable == false)
1600 Rectangle view_rect = item_control.ClientRectangle;
1601 Rectangle bounds = items [index].Bounds;
1603 if (view_rect.Contains (bounds))
1606 if (bounds.Left < 0)
1607 h_scroll.Value += bounds.Left;
1608 else if (bounds.Right > view_rect.Right)
1609 h_scroll.Value += (bounds.Right - view_rect.Right);
1612 v_scroll.Value += bounds.Top;
1613 else if (bounds.Bottom > view_rect.Bottom)
1614 v_scroll.Value += (bounds.Bottom - view_rect.Bottom);
1617 public ListViewItem GetItemAt (int x, int y)
1619 foreach (ListViewItem item in items) {
1620 if (item.Bounds.Contains (x, y))
1626 public Rectangle GetItemRect (int index)
1628 return GetItemRect (index, ItemBoundsPortion.Entire);
1631 public Rectangle GetItemRect (int index, ItemBoundsPortion portion)
1633 if (index < 0 || index >= items.Count)
1634 throw new IndexOutOfRangeException ("Invalid Index");
1636 return items [index].GetBounds (portion);
1641 if (sort_order != SortOrder.None)
1642 items.list.Sort (item_sorter);
1644 if (sort_order == SortOrder.Descending)
1645 items.list.Reverse ();
1650 public override string ToString ()
1652 int count = this.Items.Count;
1655 return string.Format ("System.Windows.Forms.ListView, Items.Count: 0");
1657 return string.Format ("System.Windows.Forms.ListView, Items.Count: {0}, Items[0]: {1}", count, this.Items [0].ToString ());
1659 #endregion // Public Instance Methods
1664 class HeaderControl : Control {
1667 bool column_resize_active = false;
1668 ColumnHeader resize_column;
1669 ColumnHeader clicked_column;
1670 ColumnHeader drag_column;
1672 int drag_to_index = -1;
1674 public HeaderControl (ListView owner)
1677 MouseDown += new MouseEventHandler (HeaderMouseDown);
1678 MouseMove += new MouseEventHandler (HeaderMouseMove);
1679 MouseUp += new MouseEventHandler (HeaderMouseUp);
1680 Paint += new PaintEventHandler (HeaderPaint);
1683 private ColumnHeader ColumnAtX (int x)
1685 Point pt = new Point (x, 0);
1686 ColumnHeader result = null;
1687 foreach (ColumnHeader col in owner.Columns) {
1688 if (col.Rect.Contains (pt)) {
1696 private int GetReorderedIndex (ColumnHeader col)
1698 if (owner.reordered_column_indices == null)
1701 for (int i = 0; i < owner.Columns.Count; i++)
1702 if (owner.reordered_column_indices [i] == col.Index)
1704 throw new Exception ("Column index missing from reordered array");
1707 private void HeaderMouseDown (object sender, MouseEventArgs me)
1709 if (resize_column != null) {
1710 column_resize_active = true;
1715 clicked_column = ColumnAtX (me.X + owner.h_marker);
1717 if (clicked_column != null) {
1719 if (owner.AllowColumnReorder) {
1721 drag_column = (ColumnHeader) (clicked_column as ICloneable).Clone ();
1722 drag_column.column_rect = clicked_column.Rect;
1723 drag_to_index = GetReorderedIndex (clicked_column);
1725 clicked_column.pressed = true;
1726 Rectangle bounds = clicked_column.Rect;
1727 bounds.X -= owner.h_marker;
1728 Invalidate (bounds);
1733 private void HeaderMouseMove (object sender, MouseEventArgs me)
1735 Point pt = new Point (me.X + owner.h_marker, me.Y);
1737 if (column_resize_active) {
1738 resize_column.Width = pt.X - resize_column.X;
1739 if (resize_column.Width < 0)
1740 resize_column.Width = 0;
1744 resize_column = null;
1746 if (clicked_column != null) {
1747 if (owner.AllowColumnReorder) {
1750 r = drag_column.column_rect;
1751 r.X = clicked_column.Rect.X + me.X - drag_x;
1752 drag_column.column_rect = r;
1754 int x = me.X + owner.h_marker;
1755 ColumnHeader over = ColumnAtX (x);
1757 drag_to_index = owner.Columns.Count;
1758 else if (x < over.X + over.Width / 2)
1759 drag_to_index = GetReorderedIndex (over);
1761 drag_to_index = GetReorderedIndex (over) + 1;
1764 ColumnHeader over = ColumnAtX (me.X + owner.h_marker);
1765 bool pressed = clicked_column.pressed;
1766 clicked_column.pressed = over == clicked_column;
1767 if (clicked_column.pressed ^ pressed) {
1768 Rectangle bounds = clicked_column.Rect;
1769 bounds.X -= owner.h_marker;
1770 Invalidate (bounds);
1776 for (int i = 0; i < owner.Columns.Count; i++) {
1777 Rectangle zone = owner.Columns [i].Rect;
1778 zone.X = zone.Right - 5;
1780 if (zone.Contains (pt)) {
1781 resize_column = owner.Columns [i];
1786 if (resize_column == null)
1787 Cursor = Cursors.Default;
1789 Cursor = Cursors.VSplit;
1792 void HeaderMouseUp (object sender, MouseEventArgs me)
1796 if (column_resize_active) {
1797 column_resize_active = false;
1798 resize_column = null;
1799 Cursor = Cursors.Default;
1803 if (clicked_column != null && clicked_column.pressed) {
1804 clicked_column.pressed = false;
1805 Rectangle bounds = clicked_column.Rect;
1806 bounds.X -= owner.h_marker;
1807 Invalidate (bounds);
1808 owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index));
1811 if (drag_column != null && owner.AllowColumnReorder) {
1813 if (drag_to_index > GetReorderedIndex (clicked_column))
1815 if (owner.GetReorderedColumn (drag_to_index) != clicked_column)
1816 owner.ReorderColumn (clicked_column, drag_to_index);
1821 clicked_column = null;
1824 void HeaderPaint (object sender, PaintEventArgs pe)
1826 if (Width <= 0 || Height <= 0 || !Visible || owner.updating)
1829 Theme theme = ThemeEngine.Current;
1830 theme.DrawListViewHeader (pe.Graphics, pe.ClipRectangle, this.owner);
1832 if (drag_column == null)
1836 if (drag_to_index == owner.Columns.Count)
1837 target_x = owner.GetReorderedColumn (drag_to_index - 1).Rect.Right - owner.h_marker;
1839 target_x = owner.GetReorderedColumn (drag_to_index).Rect.X - owner.h_marker;
1840 theme.DrawListViewHeaderDragDetails (pe.Graphics, owner, drag_column, target_x);
1845 public class CheckedIndexCollection : IList, ICollection, IEnumerable
1847 internal ArrayList list;
1848 private ListView owner;
1850 #region Public Constructor
1851 public CheckedIndexCollection (ListView owner)
1853 list = new ArrayList ();
1856 #endregion // Public Constructor
1858 #region Public Properties
1861 get { return list.Count; }
1864 public bool IsReadOnly {
1865 get { return true; }
1868 public int this [int index] {
1870 if (index < 0 || index >= list.Count)
1871 throw new ArgumentOutOfRangeException ("Index out of range.");
1872 return (int) list [index];
1876 bool ICollection.IsSynchronized {
1877 get { return false; }
1880 object ICollection.SyncRoot {
1881 get { return this; }
1884 bool IList.IsFixedSize {
1885 get { return true; }
1888 object IList.this [int index] {
1889 get { return this [index]; }
1890 set { throw new NotSupportedException ("SetItem operation is not supported."); }
1892 #endregion // Public Properties
1894 #region Public Methods
1895 public bool Contains (int checkedIndex)
1897 return list.Contains (checkedIndex);
1900 public IEnumerator GetEnumerator ()
1902 return list.GetEnumerator ();
1905 void ICollection.CopyTo (Array dest, int index)
1907 list.CopyTo (dest, index);
1910 int IList.Add (object value)
1912 throw new NotSupportedException ("Add operation is not supported.");
1917 throw new NotSupportedException ("Clear operation is not supported.");
1920 bool IList.Contains (object checkedIndex)
1922 return list.Contains (checkedIndex);
1925 int IList.IndexOf (object checkedIndex)
1927 return list.IndexOf (checkedIndex);
1930 void IList.Insert (int index, object value)
1932 throw new NotSupportedException ("Insert operation is not supported.");
1935 void IList.Remove (object value)
1937 throw new NotSupportedException ("Remove operation is not supported.");
1940 void IList.RemoveAt (int index)
1942 throw new NotSupportedException ("RemoveAt operation is not supported.");
1945 public int IndexOf (int checkedIndex)
1947 return list.IndexOf (checkedIndex);
1949 #endregion // Public Methods
1951 } // CheckedIndexCollection
1953 public class CheckedListViewItemCollection : IList, ICollection, IEnumerable
1955 internal ArrayList list;
1956 private ListView owner;
1958 #region Public Constructor
1959 public CheckedListViewItemCollection (ListView owner)
1961 list = new ArrayList ();
1964 #endregion // Public Constructor
1966 #region Public Properties
1969 get { return list.Count; }
1972 public bool IsReadOnly {
1973 get { return true; }
1976 public ListViewItem this [int index] {
1978 if (index < 0 || index >= list.Count)
1979 throw new ArgumentOutOfRangeException ("Index out of range.");
1980 return (ListViewItem) list [index];
1984 bool ICollection.IsSynchronized {
1985 get { return list.IsSynchronized; }
1988 object ICollection.SyncRoot {
1989 get { return this; }
1992 bool IList.IsFixedSize {
1993 get { return true; }
1996 object IList.this [int index] {
1997 get { return this [index]; }
1998 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2000 #endregion // Public Properties
2002 #region Public Methods
2003 public bool Contains (ListViewItem item)
2005 return list.Contains (item);
2008 public void CopyTo (Array dest, int index)
2010 list.CopyTo (dest, index);
2013 public IEnumerator GetEnumerator ()
2015 return list.GetEnumerator ();
2018 int IList.Add (object value)
2020 throw new NotSupportedException ("Add operation is not supported.");
2025 throw new NotSupportedException ("Clear operation is not supported.");
2028 bool IList.Contains (object item)
2030 return list.Contains (item);
2033 int IList.IndexOf (object item)
2035 return list.IndexOf (item);
2038 void IList.Insert (int index, object value)
2040 throw new NotSupportedException ("Insert operation is not supported.");
2043 void IList.Remove (object value)
2045 throw new NotSupportedException ("Remove operation is not supported.");
2048 void IList.RemoveAt (int index)
2050 throw new NotSupportedException ("RemoveAt operation is not supported.");
2053 public int IndexOf (ListViewItem item)
2055 return list.IndexOf (item);
2057 #endregion // Public Methods
2059 } // CheckedListViewItemCollection
2061 public class ColumnHeaderCollection : IList, ICollection, IEnumerable
2063 internal ArrayList list;
2064 private ListView owner;
2066 #region Public Constructor
2067 public ColumnHeaderCollection (ListView owner)
2069 list = new ArrayList ();
2072 #endregion // Public Constructor
2074 #region Public Properties
2077 get { return list.Count; }
2080 public bool IsReadOnly {
2081 get { return false; }
2084 public virtual ColumnHeader this [int index] {
2086 if (index < 0 || index >= list.Count)
2087 throw new ArgumentOutOfRangeException ("Index out of range.");
2088 return (ColumnHeader) list [index];
2092 bool ICollection.IsSynchronized {
2093 get { return true; }
2096 object ICollection.SyncRoot {
2097 get { return this; }
2100 bool IList.IsFixedSize {
2101 get { return list.IsFixedSize; }
2104 object IList.this [int index] {
2105 get { return this [index]; }
2106 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2108 #endregion // Public Properties
2110 #region Public Methods
2111 public virtual int Add (ColumnHeader value)
2114 value.owner = this.owner;
2115 idx = list.Add (value);
2116 owner.Redraw (true);
2120 public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign)
2122 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2123 this.Add (colHeader);
2127 public virtual void AddRange (ColumnHeader [] values)
2129 foreach (ColumnHeader colHeader in values) {
2130 colHeader.owner = this.owner;
2134 owner.Redraw (true);
2137 public virtual void Clear ()
2140 owner.Redraw (true);
2143 public bool Contains (ColumnHeader value)
2145 return list.Contains (value);
2148 public IEnumerator GetEnumerator ()
2150 return list.GetEnumerator ();
2153 void ICollection.CopyTo (Array dest, int index)
2155 list.CopyTo (dest, index);
2158 int IList.Add (object value)
2160 if (! (value is ColumnHeader)) {
2161 throw new ArgumentException ("Not of type ColumnHeader", "value");
2164 return this.Add ((ColumnHeader) value);
2167 bool IList.Contains (object value)
2169 if (! (value is ColumnHeader)) {
2170 throw new ArgumentException ("Not of type ColumnHeader", "value");
2173 return this.Contains ((ColumnHeader) value);
2176 int IList.IndexOf (object value)
2178 if (! (value is ColumnHeader)) {
2179 throw new ArgumentException ("Not of type ColumnHeader", "value");
2182 return this.IndexOf ((ColumnHeader) value);
2185 void IList.Insert (int index, object value)
2187 if (! (value is ColumnHeader)) {
2188 throw new ArgumentException ("Not of type ColumnHeader", "value");
2191 this.Insert (index, (ColumnHeader) value);
2194 void IList.Remove (object value)
2196 if (! (value is ColumnHeader)) {
2197 throw new ArgumentException ("Not of type ColumnHeader", "value");
2200 this.Remove ((ColumnHeader) value);
2203 public int IndexOf (ColumnHeader value)
2205 return list.IndexOf (value);
2208 public void Insert (int index, ColumnHeader value)
2210 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2211 // but it's really only greater.
2212 if (index < 0 || index > list.Count)
2213 throw new ArgumentOutOfRangeException ("Index out of range.");
2215 value.owner = this.owner;
2216 list.Insert (index, value);
2217 owner.Redraw (true);
2220 public void Insert (int index, string str, int width, HorizontalAlignment textAlign)
2222 ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width);
2223 this.Insert (index, colHeader);
2226 public virtual void Remove (ColumnHeader column)
2228 // TODO: Update Column internal index ?
2229 list.Remove (column);
2230 owner.Redraw (true);
2233 public virtual void RemoveAt (int index)
2235 if (index < 0 || index >= list.Count)
2236 throw new ArgumentOutOfRangeException ("Index out of range.");
2238 // TODO: Update Column internal index ?
2239 list.RemoveAt (index);
2240 owner.Redraw (true);
2242 #endregion // Public Methods
2245 } // ColumnHeaderCollection
2247 public class ListViewItemCollection : IList, ICollection, IEnumerable
2249 internal ArrayList list;
2250 private ListView owner;
2252 #region Public Constructor
2253 public ListViewItemCollection (ListView owner)
2255 list = new ArrayList ();
2258 #endregion // Public Constructor
2260 #region Public Properties
2263 get { return list.Count; }
2266 public bool IsReadOnly {
2267 get { return false; }
2270 public virtual ListViewItem this [int displayIndex] {
2272 if (displayIndex < 0 || displayIndex >= list.Count)
2273 throw new ArgumentOutOfRangeException ("Index out of range.");
2274 return (ListViewItem) list [displayIndex];
2278 if (displayIndex < 0 || displayIndex >= list.Count)
2279 throw new ArgumentOutOfRangeException ("Index out of range.");
2281 if (list.Contains (value))
2282 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2284 value.Owner = owner;
2285 list [displayIndex] = value;
2287 owner.Redraw (true);
2291 bool ICollection.IsSynchronized {
2292 get { return true; }
2295 object ICollection.SyncRoot {
2296 get { return this; }
2299 bool IList.IsFixedSize {
2300 get { return list.IsFixedSize; }
2303 object IList.this [int index] {
2304 get { return this [index]; }
2306 if (value is ListViewItem)
2307 this [index] = (ListViewItem) value;
2309 this [index] = new ListViewItem (value.ToString ());
2312 #endregion // Public Properties
2314 #region Public Methods
2315 public virtual ListViewItem Add (ListViewItem value)
2317 if (list.Contains (value))
2318 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value");
2320 value.Owner = owner;
2323 if (owner.Sorting != SortOrder.None)
2326 owner.Redraw (true);
2331 public virtual ListViewItem Add (string text)
2333 ListViewItem item = new ListViewItem (text);
2334 return this.Add (item);
2337 public virtual ListViewItem Add (string text, int imageIndex)
2339 ListViewItem item = new ListViewItem (text, imageIndex);
2340 return this.Add (item);
2343 public void AddRange (ListViewItem [] values)
2346 owner.SelectedItems.list.Clear ();
2347 owner.SelectedIndices.list.Clear ();
2348 owner.CheckedItems.list.Clear ();
2349 owner.CheckedIndices.list.Clear ();
2351 foreach (ListViewItem item in values) {
2356 if (owner.Sorting != SortOrder.None)
2359 owner.Redraw (true);
2362 public virtual void Clear ()
2364 owner.SetFocusedItem (null);
2365 owner.h_scroll.Value = owner.v_scroll.Value = 0;
2367 owner.SelectedItems.list.Clear ();
2368 owner.SelectedIndices.list.Clear ();
2369 owner.CheckedItems.list.Clear ();
2370 owner.CheckedIndices.list.Clear ();
2371 owner.Redraw (true);
2374 public bool Contains (ListViewItem item)
2376 return list.Contains (item);
2379 public void CopyTo (Array dest, int index)
2381 list.CopyTo (dest, index);
2384 public IEnumerator GetEnumerator ()
2386 return list.GetEnumerator ();
2389 int IList.Add (object item)
2394 if (item is ListViewItem) {
2395 li = (ListViewItem) item;
2396 if (list.Contains (li))
2397 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2400 li = new ListViewItem (item.ToString ());
2403 result = list.Add (li);
2404 owner.Redraw (true);
2409 bool IList.Contains (object item)
2411 return list.Contains (item);
2414 int IList.IndexOf (object item)
2416 return list.IndexOf (item);
2419 void IList.Insert (int index, object item)
2421 if (item is ListViewItem)
2422 this.Insert (index, (ListViewItem) item);
2424 this.Insert (index, item.ToString ());
2427 void IList.Remove (object item)
2429 Remove ((ListViewItem) item);
2432 public int IndexOf (ListViewItem item)
2434 return list.IndexOf (item);
2437 public ListViewItem Insert (int index, ListViewItem item)
2439 // LAMESPEC: MSDOCS say greater than or equal to the value of the Count property
2440 // but it's really only greater.
2441 if (index < 0 || index > list.Count)
2442 throw new ArgumentOutOfRangeException ("Index out of range.");
2444 if (list.Contains (item))
2445 throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item");
2448 list.Insert (index, item);
2449 owner.Redraw (true);
2453 public ListViewItem Insert (int index, string text)
2455 return this.Insert (index, new ListViewItem (text));
2458 public ListViewItem Insert (int index, string text, int imageIndex)
2460 return this.Insert (index, new ListViewItem (text, imageIndex));
2463 public virtual void Remove (ListViewItem item)
2465 if (!list.Contains (item))
2468 owner.SelectedItems.list.Remove (item);
2469 owner.SelectedIndices.list.Remove (item.Index);
2470 owner.CheckedItems.list.Remove (item);
2471 owner.CheckedIndices.list.Remove (item.Index);
2473 owner.Redraw (true);
2476 public virtual void RemoveAt (int index)
2478 if (index < 0 || index >= list.Count)
2479 throw new ArgumentOutOfRangeException ("Index out of range.");
2481 list.RemoveAt (index);
2482 owner.SelectedItems.list.RemoveAt (index);
2483 owner.SelectedIndices.list.RemoveAt (index);
2484 owner.CheckedItems.list.RemoveAt (index);
2485 owner.CheckedIndices.list.RemoveAt (index);
2486 owner.Redraw (false);
2488 #endregion // Public Methods
2490 } // ListViewItemCollection
2492 public class SelectedIndexCollection : IList, ICollection, IEnumerable
2494 internal ArrayList list;
2495 private ListView owner;
2497 #region Public Constructor
2498 public SelectedIndexCollection (ListView owner)
2500 list = new ArrayList ();
2503 #endregion // Public Constructor
2505 #region Public Properties
2508 get { return list.Count; }
2511 public bool IsReadOnly {
2512 get { return true; }
2515 public int this [int index] {
2517 if (index < 0 || index >= list.Count)
2518 throw new ArgumentOutOfRangeException ("Index out of range.");
2519 return (int) list [index];
2523 bool ICollection.IsSynchronized {
2524 get { return list.IsSynchronized; }
2527 object ICollection.SyncRoot {
2528 get { return this; }
2531 bool IList.IsFixedSize {
2532 get { return true; }
2535 object IList.this [int index] {
2536 get { return this [index]; }
2537 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2539 #endregion // Public Properties
2541 #region Public Methods
2542 public bool Contains (int selectedIndex)
2544 return list.Contains (selectedIndex);
2547 public void CopyTo (Array dest, int index)
2549 list.CopyTo (dest, index);
2552 public IEnumerator GetEnumerator ()
2554 return list.GetEnumerator ();
2557 int IList.Add (object value)
2559 throw new NotSupportedException ("Add operation is not supported.");
2564 throw new NotSupportedException ("Clear operation is not supported.");
2567 bool IList.Contains (object selectedIndex)
2569 return list.Contains (selectedIndex);
2572 int IList.IndexOf (object selectedIndex)
2574 return list.IndexOf (selectedIndex);
2577 void IList.Insert (int index, object value)
2579 throw new NotSupportedException ("Insert operation is not supported.");
2582 void IList.Remove (object value)
2584 throw new NotSupportedException ("Remove operation is not supported.");
2587 void IList.RemoveAt (int index)
2589 throw new NotSupportedException ("RemoveAt operation is not supported.");
2592 public int IndexOf (int selectedIndex)
2594 return list.IndexOf (selectedIndex);
2596 #endregion // Public Methods
2598 } // SelectedIndexCollection
2600 public class SelectedListViewItemCollection : IList, ICollection, IEnumerable
2602 internal ArrayList list;
2603 private ListView owner;
2605 #region Public Constructor
2606 public SelectedListViewItemCollection (ListView owner)
2608 list = new ArrayList ();
2611 #endregion // Public Constructor
2613 #region Public Properties
2616 get { return list.Count; }
2619 public bool IsReadOnly {
2620 get { return true; }
2623 public ListViewItem this [int index] {
2625 if (index < 0 || index >= list.Count)
2626 throw new ArgumentOutOfRangeException ("Index out of range.");
2627 return (ListViewItem) list [index];
2631 bool ICollection.IsSynchronized {
2632 get { return list.IsSynchronized; }
2635 object ICollection.SyncRoot {
2636 get { return this; }
2639 bool IList.IsFixedSize {
2640 get { return true; }
2643 object IList.this [int index] {
2644 get { return this [index]; }
2645 set { throw new NotSupportedException ("SetItem operation is not supported."); }
2647 #endregion // Public Properties
2649 #region Public Methods
2650 public void Clear ()
2652 ArrayList copy = (ArrayList) list.Clone ();
2653 for (int i = 0; i < copy.Count; i++)
2654 ((ListViewItem) copy [i]).Selected = false;
2659 public bool Contains (ListViewItem item)
2661 return list.Contains (item);
2664 public void CopyTo (Array dest, int index)
2666 list.CopyTo (dest, index);
2669 public IEnumerator GetEnumerator ()
2671 return list.GetEnumerator ();
2674 int IList.Add (object value)
2676 throw new NotSupportedException ("Add operation is not supported.");
2679 bool IList.Contains (object item)
2681 return list.Contains (item);
2684 int IList.IndexOf (object item)
2686 return list.IndexOf (item);
2689 void IList.Insert (int index, object value)
2691 throw new NotSupportedException ("Insert operation is not supported.");
2694 void IList.Remove (object value)
2696 throw new NotSupportedException ("Remove operation is not supported.");
2699 void IList.RemoveAt (int index)
2701 throw new NotSupportedException ("RemoveAt operation is not supported.");
2704 public int IndexOf (ListViewItem item)
2706 return list.IndexOf (item);
2708 #endregion // Public Methods
2710 } // SelectedListViewItemCollection
2712 #endregion // Subclasses