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-2006 Novell, Inc.
23 // Jordi Mas i Hernandez, jordi@ximian.com
24 // Mike Kestner <mkestner@novell.com>
31 using System
.Collections
;
32 using System
.ComponentModel
;
33 using System
.ComponentModel
.Design
;
34 using System
.ComponentModel
.Design
.Serialization
;
35 using System
.Reflection
;
36 using System
.Runtime
.InteropServices
;
38 namespace System
.Windows
.Forms
40 [DefaultProperty("Items")]
41 [DefaultEvent("SelectedIndexChanged")]
42 [Designer ("System.Windows.Forms.Design.ListBoxDesigner, " + Consts
.AssemblySystem_Design
, "System.ComponentModel.Design.IDesigner")]
43 public class ListBox
: ListControl
45 public const int DefaultItemHeight
= 13;
46 public const int NoMatches
= -1;
48 internal enum ItemNavigation
60 Hashtable item_heights
;
61 private int item_height
= -1;
62 private int column_width
= 0;
63 private int requested_height
= -1;
64 private DrawMode draw_mode
= DrawMode
.Normal
;
65 private int horizontal_extent
= 0;
66 private bool horizontal_scrollbar
= false;
67 private bool integral_height
= true;
68 private bool multicolumn
= false;
69 private bool scroll_always_visible
= false;
70 private int selected_index
= -1;
71 private SelectedIndexCollection selected_indices
;
72 private SelectedObjectCollection selected_items
;
73 private ArrayList selection
= new ArrayList ();
74 private SelectionMode selection_mode
= SelectionMode
.One
;
75 private bool sorted
= false;
76 private bool use_tabstops
= true;
77 private int column_width_internal
= 120;
78 private ImplicitVScrollBar vscrollbar
;
79 private ImplicitHScrollBar hscrollbar
;
80 private int hbar_offset
;
81 private bool suspend_layout
;
82 private bool ctrl_pressed
= false;
83 private bool shift_pressed
= false;
84 private bool explicit_item_height
= false;
85 private int top_index
= 0;
86 private int last_visible_index
= 0;
87 private Rectangle items_area
;
88 private int focused_item
= -1;
89 private ObjectCollection items
;
93 border_style
= BorderStyle
.Fixed3D
;
94 BackColor
= ThemeEngine
.Current
.ColorWindow
;
96 items
= CreateItemCollection ();
97 selected_indices
= new SelectedIndexCollection (this);
98 selected_items
= new SelectedObjectCollection (this);
100 /* Vertical scrollbar */
101 vscrollbar
= new ImplicitVScrollBar ();
102 vscrollbar
.Minimum
= 0;
103 vscrollbar
.SmallChange
= 1;
104 vscrollbar
.LargeChange
= 1;
105 vscrollbar
.Maximum
= 0;
106 vscrollbar
.ValueChanged
+= new EventHandler (VerticalScrollEvent
);
107 vscrollbar
.Visible
= false;
109 /* Horizontal scrollbar */
110 hscrollbar
= new ImplicitHScrollBar ();
111 hscrollbar
.Minimum
= 0;
112 hscrollbar
.SmallChange
= 1;
113 hscrollbar
.LargeChange
= 1;
114 hscrollbar
.Maximum
= 0;
115 hscrollbar
.Visible
= false;
116 hscrollbar
.ValueChanged
+= new EventHandler (HorizontalScrollEvent
);
119 MouseDown
+= new MouseEventHandler (OnMouseDownLB
);
120 MouseMove
+= new MouseEventHandler (OnMouseMoveLB
);
121 MouseUp
+= new MouseEventHandler (OnMouseUpLB
);
122 MouseWheel
+= new MouseEventHandler (OnMouseWheelLB
);
123 KeyDown
+= new KeyEventHandler (OnKeyDownLB
);
124 KeyUp
+= new KeyEventHandler (OnKeyUpLB
);
125 GotFocus
+= new EventHandler (OnGotFocus
);
126 LostFocus
+= new EventHandler (OnLostFocus
);
128 SetStyle (ControlStyles
.UserPaint
, false);
132 static object DrawItemEvent
= new object ();
133 static object MeasureItemEvent
= new object ();
134 static object SelectedIndexChangedEvent
= new object ();
137 [EditorBrowsable (EditorBrowsableState
.Never
)]
138 public new event EventHandler BackgroundImageChanged
{
139 add { base.BackgroundImageChanged += value; }
140 remove { base.BackgroundImageChanged -= value; }
144 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
145 public new event EventHandler Click
{
146 add { base.Click += value; }
147 remove { base.Click -= value; }
150 public event DrawItemEventHandler DrawItem
{
151 add { Events.AddHandler (DrawItemEvent, value); }
152 remove { Events.RemoveHandler (DrawItemEvent, value); }
155 public event MeasureItemEventHandler MeasureItem
{
156 add { Events.AddHandler (MeasureItemEvent, value); }
157 remove { Events.RemoveHandler (MeasureItemEvent, value); }
161 [EditorBrowsable (EditorBrowsableState
.Never
)]
162 public new event PaintEventHandler Paint
{
163 add { base.Paint += value; }
164 remove { base.Paint -= value; }
167 public event EventHandler SelectedIndexChanged
{
168 add { Events.AddHandler (SelectedIndexChangedEvent, value); }
169 remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
173 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
174 public new event EventHandler TextChanged
{
175 add { base.TextChanged += value; }
176 remove { base.TextChanged -= value; }
180 #region Public Properties
181 public override Color BackColor
{
182 get { return base.BackColor; }
184 if (base.BackColor
== value)
187 base.BackColor
= value;
188 base.Refresh (); // Careful. Calling the base method is not the same that calling
189 } // the overriden one that refresh also all the items
193 [EditorBrowsable (EditorBrowsableState
.Never
)]
194 public override Image BackgroundImage
{
195 get { return base.BackgroundImage; }
197 base.BackgroundImage
= value;
202 [DefaultValue (BorderStyle
.Fixed3D
)]
204 public BorderStyle BorderStyle
{
205 get { return InternalBorderStyle; }
207 InternalBorderStyle
= value;
208 UpdateListBoxBounds ();
214 public int ColumnWidth
{
215 get { return column_width; }
218 throw new ArgumentException ("A value less than zero is assigned to the property.");
220 column_width
= value;
223 ColumnWidthInternal
= 120;
225 ColumnWidthInternal
= value;
231 protected override CreateParams CreateParams
{
232 get { return base.CreateParams;}
235 protected override Size DefaultSize
{
236 get { return new Size (120, 96); }
239 [RefreshProperties(RefreshProperties
.Repaint
)]
240 [DefaultValue (DrawMode
.Normal
)]
241 public virtual DrawMode DrawMode
{
242 get { return draw_mode; }
245 if (!Enum
.IsDefined (typeof (DrawMode
), value))
246 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
248 if (value == DrawMode
.OwnerDrawVariable
&& multicolumn
== true)
249 throw new ArgumentException ("Cannot have variable height and multicolumn");
251 if (draw_mode
== value)
256 if (draw_mode
== DrawMode
.OwnerDrawVariable
)
257 item_heights
= new Hashtable ();
265 public override Color ForeColor
{
266 get { return base.ForeColor; }
269 if (base.ForeColor
== value)
272 base.ForeColor
= value;
279 public int HorizontalExtent
{
280 get { return horizontal_extent; }
282 if (horizontal_extent
== value)
285 horizontal_extent
= value;
290 [DefaultValue (false)]
292 public bool HorizontalScrollbar
{
293 get { return horizontal_scrollbar; }
295 if (horizontal_scrollbar
== value)
298 horizontal_scrollbar
= value;
304 [DefaultValue (true)]
306 [RefreshProperties(RefreshProperties
.Repaint
)]
307 public bool IntegralHeight
{
308 get { return integral_height; }
310 if (integral_height
== value)
313 integral_height
= value;
314 UpdateListBoxBounds ();
320 [RefreshProperties(RefreshProperties
.Repaint
)]
321 public virtual int ItemHeight
{
323 if (item_height
== -1) {
324 SizeF sz
= DeviceContext
.MeasureString ("The quick brown Fox", Font
);
325 item_height
= (int) sz
.Height
;
331 throw new ArgumentOutOfRangeException ("The ItemHeight property was set beyond 255 pixels");
333 explicit_item_height
= true;
334 if (item_height
== value)
339 UpdateListBoxBounds ();
344 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Content
)]
346 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts
.AssemblySystem_Design
, typeof (System
.Drawing
.Design
.UITypeEditor
))]
347 public ObjectCollection Items
{
348 get { return items; }
351 [DefaultValue (false)]
352 public bool MultiColumn
{
353 get { return multicolumn; }
355 if (multicolumn
== value)
358 if (value == true && DrawMode
== DrawMode
.OwnerDrawVariable
)
359 throw new ArgumentException ("A multicolumn ListBox cannot have a variable-sized height.");
367 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
368 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
369 public int PreferredHeight
{
372 if (draw_mode
== DrawMode
.Normal
)
373 itemsHeight
= FontHeight
* items
.Count
;
374 else if (draw_mode
== DrawMode
.OwnerDrawFixed
)
375 itemsHeight
= ItemHeight
* items
.Count
;
376 else if (draw_mode
== DrawMode
.OwnerDrawVariable
) {
377 for (int i
= 0; i
< items
.Count
; i
++)
378 itemsHeight
+= (int) item_heights
[Items
[i
]];
385 public override RightToLeft RightToLeft
{
386 get { return base.RightToLeft; }
388 base.RightToLeft
= value;
389 if (base.RightToLeft
== RightToLeft
.Yes
)
390 StringFormat
.Alignment
= StringAlignment
.Far
;
392 StringFormat
.Alignment
= StringAlignment
.Near
;
397 // Only affects the Vertical ScrollBar
398 [DefaultValue (false)]
400 public bool ScrollAlwaysVisible
{
401 get { return scroll_always_visible; }
403 if (scroll_always_visible
== value)
406 scroll_always_visible
= value;
413 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
414 public override int SelectedIndex
{
415 get { return selected_index;}
417 if (value < -1 || value >= Items
.Count
)
418 throw new ArgumentOutOfRangeException ("Index of out range");
420 if (SelectionMode
== SelectionMode
.None
)
421 throw new ArgumentException ("cannot call this method if SelectionMode is SelectionMode.None");
423 if (selected_index
== value)
428 else if (SelectionMode
== SelectionMode
.One
)
429 UnSelectItem (selected_index
, true);
431 if (value < top_index
)
436 int rows
= items_area
.Height
/ ItemHeight
;
437 if (value >= (top_index
+ rows
))
439 top_index
= value - rows
+ 1;
444 selected_index
= value;
446 OnSelectedIndexChanged (new EventArgs ());
447 OnSelectedValueChanged (new EventArgs ());
452 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
453 public SelectedIndexCollection SelectedIndices
{
454 get { return selected_indices; }
459 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
460 public object SelectedItem
{
462 if (SelectedItems
.Count
> 0)
463 return SelectedItems
[0];
468 if (value != null && !Items
.Contains (value))
469 return; // FIXME: this is probably an exception
471 SelectedIndex
= value == null ? - 1 : Items
.IndexOf (value);
476 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
477 public SelectedObjectCollection SelectedItems
{
478 get {return selected_items;}
481 [DefaultValue (SelectionMode
.One
)]
482 public virtual SelectionMode SelectionMode
{
483 get { return selection_mode; }
485 if (!Enum
.IsDefined (typeof (SelectionMode
), value))
486 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for SelectionMode", value));
488 if (selection_mode
== value)
491 selection_mode
= value;
493 switch (selection_mode
) {
494 case SelectionMode
.None
:
498 case SelectionMode
.One
:
499 while (SelectedIndices
.Count
> 1)
500 UnSelectItem (SelectedIndices
[SelectedIndices
.Count
- 1], true);
509 [DefaultValue (false)]
511 get { return sorted; }
525 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
526 [EditorBrowsable (EditorBrowsableState
.Advanced
)]
527 public override string Text
{
529 if (SelectionMode
!= SelectionMode
.None
&& SelectedIndex
!= -1)
530 return GetItemText (SelectedItem
);
538 if (SelectionMode
== SelectionMode
.None
)
543 index
= FindStringExact (value);
548 SelectedIndex
= index
;
553 [DesignerSerializationVisibility (DesignerSerializationVisibility
.Hidden
)]
554 public int TopIndex
{
555 get { return top_index; }
557 if (value == top_index
)
560 if (value < 0 || value >= Items
.Count
)
569 [DefaultValue (true)]
570 public bool UseTabStops
{
571 get { return use_tabstops; }
574 if (use_tabstops
== value)
577 use_tabstops
= value;
579 StringFormat
.SetTabStops (0, new float [] {(float)(Font.Height * 3.7)}
);
581 StringFormat
.SetTabStops (0, new float [0]);
586 #endregion Public Properties
588 #region Private Properties
590 private int ColumnWidthInternal
{
591 get { return column_width_internal; }
592 set { column_width_internal = value; }
595 private int row_count
= 1;
596 private int RowCount
{
598 return MultiColumn
? row_count
: Items
.Count
;
602 #endregion Private Properties
604 #region Public Methods
605 protected virtual void AddItemsCore (object[] value)
607 Items
.AddRange (value);
610 public void BeginUpdate ()
612 suspend_layout
= true;
615 public void ClearSelected ()
617 foreach (int i
in selected_indices
) {
618 UnSelectItem (i
, false);
624 protected virtual ObjectCollection
CreateItemCollection ()
626 return new ObjectCollection (this);
629 public void EndUpdate ()
631 suspend_layout
= false;
636 public int FindString (String s
)
638 return FindString (s
, -1);
641 public int FindString (string s
, int startIndex
)
643 if (Items
.Count
== 0)
644 return -1; // No exception throwing if empty
646 if (startIndex
< -1 || startIndex
>= Items
.Count
- 1)
647 throw new ArgumentOutOfRangeException ("Index of out range");
650 for (int i
= startIndex
; i
< Items
.Count
; i
++) {
651 if ((GetItemText (Items
[i
])).StartsWith (s
))
658 public int FindStringExact (string s
)
660 return FindStringExact (s
, -1);
663 public int FindStringExact (string s
, int startIndex
)
665 if (Items
.Count
== 0)
666 return -1; // No exception throwing if empty
668 if (startIndex
< -1 || startIndex
>= Items
.Count
- 1)
669 throw new ArgumentOutOfRangeException ("Index of out range");
672 for (int i
= startIndex
; i
< Items
.Count
; i
++) {
673 if ((GetItemText (Items
[i
])).Equals (s
))
680 public int GetItemHeight (int index
)
682 if (index
< 0 || index
>= Items
.Count
)
683 throw new ArgumentOutOfRangeException ("Index of out range");
685 if (DrawMode
== DrawMode
.OwnerDrawVariable
&& IsHandleCreated
== true) {
687 object o
= Items
[index
];
688 if (item_heights
.Contains (o
))
689 return (int) item_heights
[o
];
691 MeasureItemEventArgs args
= new MeasureItemEventArgs (DeviceContext
, index
, ItemHeight
);
692 OnMeasureItem (args
);
693 item_heights
[o
] = args
.ItemHeight
;
694 return args
.ItemHeight
;
700 public Rectangle
GetItemRectangle (int index
)
702 if (index
< 0 || index
>= Items
.Count
)
703 throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
705 Rectangle rect
= new Rectangle ();
708 int col
= index
/ RowCount
;
709 rect
.Y
= ((index
- top_index
) % RowCount
) * ItemHeight
;
710 rect
.X
= col
* ColumnWidthInternal
;
711 rect
.Height
= ItemHeight
;
712 rect
.Width
= ColumnWidthInternal
;
715 rect
.Height
= GetItemHeight (index
);
716 rect
.Width
= items_area
.Width
;
718 if (DrawMode
== DrawMode
.OwnerDrawVariable
) {
720 if (index
>= top_index
) {
721 for (int i
= top_index
; i
< index
; i
++) {
722 rect
.Y
+= GetItemHeight (i
);
725 for (int i
= index
; i
< top_index
; i
++) {
726 rect
.Y
-= GetItemHeight (i
);
730 rect
.Y
= ItemHeight
* (index
- top_index
);
737 public bool GetSelected (int index
)
739 if (index
< 0 || index
>= Items
.Count
)
740 throw new ArgumentOutOfRangeException ("Index of out range");
742 return SelectedIndices
.Contains (index
);
745 public int IndexFromPoint (Point p
)
747 return IndexFromPoint (p
.X
, p
.Y
);
750 // Only returns visible points
751 public int IndexFromPoint (int x
, int y
)
754 if (Items
.Count
== 0) {
758 for (int i
= top_index
; i
<= last_visible_index
; i
++) {
759 if (GetItemRectangle (i
).Contains (x
,y
) == true)
766 protected override void OnChangeUICues (UICuesEventArgs e
)
768 base.OnChangeUICues (e
);
771 protected override void OnDataSourceChanged (EventArgs e
)
773 base.OnDataSourceChanged (e
);
776 if (DataSource
== null || DataManager
== null) {
780 SelectedIndex
= DataManager
.Position
;
784 protected override void OnDisplayMemberChanged (EventArgs e
)
786 base.OnDisplayMemberChanged (e
);
788 if (DataManager
== null || !IsHandleCreated
)
795 protected virtual void OnDrawItem (DrawItemEventArgs e
)
798 case DrawMode
.OwnerDrawFixed
:
799 case DrawMode
.OwnerDrawVariable
:
800 DrawItemEventHandler eh
= (DrawItemEventHandler
)(Events
[DrawItemEvent
]);
807 ThemeEngine
.Current
.DrawListBoxItem (this, e
);
812 protected override void OnFontChanged (EventArgs e
)
814 base.OnFontChanged (e
);
817 StringFormat
.SetTabStops (0, new float [] {(float)(Font.Height * 3.7)}
);
819 if (explicit_item_height
) {
822 SizeF sz
= DeviceContext
.MeasureString ("The quick brown Fox", Font
);
823 item_height
= (int) sz
.Height
;
825 UpdateListBoxBounds ();
830 protected override void OnHandleCreated (EventArgs e
)
832 base.OnHandleCreated (e
);
835 Controls
.AddImplicit (vscrollbar
);
836 Controls
.AddImplicit (hscrollbar
);
841 protected override void OnHandleDestroyed (EventArgs e
)
843 base.OnHandleDestroyed (e
);
846 protected virtual void OnMeasureItem (MeasureItemEventArgs e
)
848 if (draw_mode
!= DrawMode
.OwnerDrawVariable
)
851 MeasureItemEventHandler eh
= (MeasureItemEventHandler
)(Events
[MeasureItemEvent
]);
856 protected override void OnParentChanged (EventArgs e
)
858 base.OnParentChanged (e
);
861 protected override void OnResize (EventArgs e
)
864 if (canvas_size
.IsEmpty
|| MultiColumn
)
868 protected override void OnSelectedIndexChanged (EventArgs e
)
870 base.OnSelectedIndexChanged (e
);
872 EventHandler eh
= (EventHandler
)(Events
[SelectedIndexChangedEvent
]);
877 protected override void OnSelectedValueChanged (EventArgs e
)
879 base.OnSelectedValueChanged (e
);
882 public override void Refresh ()
884 if (draw_mode
== DrawMode
.OwnerDrawVariable
)
885 item_heights
.Clear ();
890 protected override void RefreshItem (int index
)
892 if (index
< 0 || index
>= Items
.Count
)
893 throw new ArgumentOutOfRangeException ("Index of out range");
895 if (draw_mode
== DrawMode
.OwnerDrawVariable
)
896 item_heights
.Remove (Items
[index
]);
899 protected override void SetBoundsCore (int x
, int y
, int width
, int height
, BoundsSpecified specified
)
901 if ((specified
& BoundsSpecified
.Height
) == BoundsSpecified
.Height
)
902 requested_height
= height
;
904 if (IntegralHeight
) {
906 switch (border_style
) {
907 case BorderStyle
.Fixed3D
:
908 border
= ThemeEngine
.Current
.Border3DSize
.Height
;
910 case BorderStyle
.FixedSingle
:
911 border
= ThemeEngine
.Current
.BorderSize
.Height
;
913 case BorderStyle
.None
:
918 height
-= (2 * border
);
919 height
-= height
% ItemHeight
;
920 height
+= (2 * border
);
923 base.SetBoundsCore (x
, y
, width
, height
, specified
);
927 protected override void SetItemCore (int index
, object value)
929 if (index
< 0 || index
>= Items
.Count
)
932 Items
[index
] = value;
935 protected override void SetItemsCore (IList
value)
940 Items
.AddRange (value);
946 public void SetSelected (int index
, bool value)
948 if (index
< 0 || index
>= Items
.Count
)
949 throw new ArgumentOutOfRangeException ("Index of out range");
951 if (SelectionMode
== SelectionMode
.None
)
952 throw new InvalidOperationException ();
957 UnSelectItem (index
, true);
960 protected virtual void Sort ()
962 if (Items
.Count
== 0)
969 public override string ToString ()
971 return base.ToString ();
974 protected virtual void WmReflectCommand (ref Message m
)
978 protected override void WndProc (ref Message m
)
980 base.WndProc (ref m
);
983 #endregion Public Methods
985 #region Private Methods
987 private Size canvas_size
;
989 private void LayoutListBox ()
991 if (!IsHandleCreated
|| suspend_layout
)
995 LayoutMultiColumn ();
997 LayoutSingleColumn ();
1000 last_visible_index
= LastVisibleItem ();
1003 private void LayoutSingleColumn ()
1008 case DrawMode
.OwnerDrawVariable
:
1010 width
= HorizontalExtent
;
1011 for (int i
= 0; i
< Items
.Count
; i
++) {
1012 height
+= GetItemHeight (i
);
1016 case DrawMode
.OwnerDrawFixed
:
1017 height
= Items
.Count
* ItemHeight
;
1018 width
= HorizontalExtent
;
1021 case DrawMode
.Normal
:
1023 height
= Items
.Count
* ItemHeight
;
1025 for (int i
= 0; i
< Items
.Count
; i
++) {
1026 SizeF sz
= DeviceContext
.MeasureString (GetItemText (Items
[i
]), Font
);
1027 if ((int) sz
.Width
> width
)
1028 width
= (int) sz
.Width
;
1033 canvas_size
= new Size (width
, height
);
1036 private void LayoutMultiColumn ()
1038 int usable_height
= ClientRectangle
.Height
- (ScrollAlwaysVisible
? hscrollbar
.Height
: 0);
1039 row_count
= usable_height
/ ItemHeight
;
1042 int cols
= (int) Math
.Ceiling ((float)Items
.Count
/ (float) row_count
);
1043 Size sz
= new Size (cols
* ColumnWidthInternal
, row_count
* ItemHeight
);
1044 if (!ScrollAlwaysVisible
&& sz
.Width
> ClientRectangle
.Width
&& row_count
> 1) {
1045 usable_height
= ClientRectangle
.Height
- hscrollbar
.Height
;
1046 row_count
= usable_height
/ ItemHeight
;
1047 cols
= (int) Math
.Ceiling ((float)Items
.Count
/ (float) row_count
);
1048 sz
= new Size (cols
* ColumnWidthInternal
, row_count
* ItemHeight
);
1053 internal void Draw (Rectangle clip
, Graphics dc
)
1055 Theme theme
= ThemeEngine
.Current
;
1057 if (hscrollbar
.Visible
&& vscrollbar
.Visible
) {
1058 // Paint the dead space in the bottom right corner
1059 Rectangle rect
= new Rectangle (hscrollbar
.Right
, vscrollbar
.Bottom
, vscrollbar
.Width
, hscrollbar
.Height
);
1060 if (rect
.IntersectsWith (clip
))
1061 dc
.FillRectangle (theme
.ResPool
.GetSolidBrush (theme
.ColorControl
), rect
);
1064 dc
.FillRectangle (theme
.ResPool
.GetSolidBrush (BackColor
), items_area
);
1066 if (Items
.Count
== 0)
1069 for (int i
= top_index
; i
<= last_visible_index
; i
++) {
1070 Rectangle rect
= GetItemDisplayRectangle (i
, top_index
);
1072 if (!clip
.IntersectsWith (rect
))
1075 DrawItemState state
= DrawItemState
.None
;
1077 if (SelectedIndices
.Contains (i
))
1078 state
|= DrawItemState
.Selected
;
1080 if (has_focus
&& FocusedItem
== i
)
1081 state
|= DrawItemState
.Focus
;
1083 if (MultiColumn
== false && hscrollbar
!= null && hscrollbar
.Visible
) {
1084 rect
.X
-= hscrollbar
.Value
;
1085 rect
.Width
+= hscrollbar
.Value
;
1088 OnDrawItem (new DrawItemEventArgs (dc
, Font
, rect
, i
, state
, ForeColor
, BackColor
));
1092 // Converts a GetItemRectangle to a one that we can display
1093 internal Rectangle
GetItemDisplayRectangle (int index
, int first_displayble
)
1095 Rectangle item_rect
;
1096 Rectangle first_item_rect
= GetItemRectangle (first_displayble
);
1097 item_rect
= GetItemRectangle (index
);
1098 item_rect
.X
-= first_item_rect
.X
;
1099 item_rect
.Y
-= first_item_rect
.Y
;
1105 private void HorizontalScrollEvent (object sender
, EventArgs e
)
1108 int top_item
= top_index
;
1109 int last_item
= last_visible_index
;
1111 top_index
= RowCount
* hscrollbar
.Value
;
1112 last_visible_index
= LastVisibleItem ();
1114 if (top_item
!= top_index
|| last_item
!= last_visible_index
)
1115 Invalidate (items_area
);
1118 int old_offset
= hbar_offset
;
1119 hbar_offset
= hscrollbar
.Value
;
1121 if (hbar_offset
< 0)
1124 XplatUI
.ScrollWindow (Handle
, items_area
, old_offset
- hbar_offset
, 0, false);
1128 // Only returns visible points. The diference of with IndexFromPoint is that the rectangle
1129 // has screen coordinates
1130 private int IndexAtClientPoint (int x
, int y
)
1132 if (Items
.Count
== 0)
1137 else if (x
> ClientRectangle
.Right
)
1138 x
= ClientRectangle
.Right
;
1142 else if (y
> ClientRectangle
.Bottom
)
1143 y
= ClientRectangle
.Bottom
;
1145 for (int i
= top_index
; i
<= last_visible_index
; i
++)
1146 if (GetItemDisplayRectangle (i
, top_index
).Contains (x
, y
))
1152 private int LastVisibleItem ()
1154 Rectangle item_rect
;
1155 int top_y
= items_area
.Y
+ items_area
.Height
;
1158 if (top_index
>= Items
.Count
)
1161 for (i
= top_index
; i
< Items
.Count
; i
++) {
1163 item_rect
= GetItemDisplayRectangle (i
, top_index
);
1166 if (item_rect
.X
> items_area
.Width
)
1170 if (item_rect
.Y
+ item_rect
.Height
> top_y
) {
1178 private void UpdateTopItem ()
1181 int col
= top_index
/ RowCount
;
1183 if (col
> hscrollbar
.Maximum
)
1184 hscrollbar
.Value
= hscrollbar
.Maximum
;
1186 hscrollbar
.Value
= col
;
1188 int val
= vscrollbar
.Value
;
1189 if (top_index
> vscrollbar
.Maximum
)
1190 vscrollbar
.Value
= vscrollbar
.Maximum
;
1192 vscrollbar
.Value
= top_index
;
1193 Scroll (vscrollbar
, vscrollbar
.Value
- top_index
);
1194 XplatUI
.ScrollWindow (Handle
, items_area
, 0, ItemHeight
* (val
- vscrollbar
.Value
), false);
1198 // Navigates to the indicated item and returns the new item
1199 private int NavigateItemVisually (ItemNavigation navigation
)
1201 int page_size
, columns
, selected_index
= -1;
1204 columns
= items_area
.Width
/ ColumnWidthInternal
;
1205 page_size
= columns
* RowCount
;
1206 if (page_size
== 0) {
1207 page_size
= RowCount
;
1210 page_size
= items_area
.Height
/ ItemHeight
;
1213 switch (navigation
) {
1215 case ItemNavigation
.PreviousColumn
: {
1216 if (FocusedItem
- RowCount
< 0) {
1220 if (FocusedItem
- RowCount
< top_index
) {
1221 top_index
= FocusedItem
- RowCount
;
1225 selected_index
= FocusedItem
- RowCount
;
1229 case ItemNavigation
.NextColumn
: {
1230 if (FocusedItem
+ RowCount
>= Items
.Count
) {
1234 if (FocusedItem
+ RowCount
> last_visible_index
) {
1235 top_index
= FocusedItem
;
1239 selected_index
= FocusedItem
+ RowCount
;
1243 case ItemNavigation
.First
: {
1250 case ItemNavigation
.Last
: {
1252 int rows
= items_area
.Height
/ ItemHeight
;
1253 if (Items
.Count
< rows
) {
1255 selected_index
= Items
.Count
- 1;
1258 top_index
= Items
.Count
- rows
;
1259 selected_index
= Items
.Count
- 1;
1265 case ItemNavigation
.Next
: {
1266 if (FocusedItem
== Items
.Count
- 1)
1270 ArrayList heights
= new ArrayList ();
1271 if (draw_mode
== DrawMode
.OwnerDrawVariable
) {
1272 for (int i
= top_index
; i
<= FocusedItem
+ 1; i
++) {
1273 int h
= GetItemHeight (i
);
1278 bottom
= ((FocusedItem
+ 1) - top_index
+ 1) * ItemHeight
;
1281 if (bottom
>= items_area
.Height
) {
1282 int overhang
= bottom
- items_area
.Height
;
1285 if (draw_mode
== DrawMode
.OwnerDrawVariable
)
1286 while (overhang
> 0)
1287 overhang
-= (int) heights
[offset
];
1289 offset
= (int) Math
.Ceiling ((float)overhang
/ (float) ItemHeight
);
1290 top_index
+= offset
;
1293 selected_index
= FocusedItem
+ 1;
1297 case ItemNavigation
.Previous
: {
1298 if (FocusedItem
> 0) {
1299 if (FocusedItem
- 1 < top_index
) {
1303 selected_index
= FocusedItem
- 1;
1308 case ItemNavigation
.NextPage
: {
1309 if (Items
.Count
< page_size
) {
1310 NavigateItemVisually (ItemNavigation
.Last
);
1314 if (FocusedItem
+ page_size
- 1 >= Items
.Count
) {
1315 top_index
= Items
.Count
- page_size
;
1317 selected_index
= Items
.Count
- 1;
1320 if (FocusedItem
+ page_size
- 1 > last_visible_index
) {
1321 top_index
= FocusedItem
;
1325 selected_index
= FocusedItem
+ page_size
- 1;
1331 case ItemNavigation
.PreviousPage
: {
1333 int rows
= items_area
.Height
/ ItemHeight
;
1334 if (FocusedItem
- (rows
- 1) <= 0) {
1341 if (FocusedItem
- (rows
- 1) < top_index
) {
1342 top_index
= FocusedItem
- (rows
- 1);
1346 selected_index
= FocusedItem
- (rows
- 1);
1355 return selected_index
;
1359 private void OnGotFocus (object sender
, EventArgs e
)
1361 if (FocusedItem
!= -1)
1362 InvalidateItem (FocusedItem
);
1365 private void OnLostFocus (object sender
, EventArgs e
)
1367 if (FocusedItem
!= -1)
1368 InvalidateItem (FocusedItem
);
1371 private void OnKeyDownLB (object sender
, KeyEventArgs e
)
1375 if (Items
.Count
== 0)
1378 switch (e
.KeyCode
) {
1380 case Keys
.ControlKey
:
1381 ctrl_pressed
= true;
1385 shift_pressed
= true;
1389 new_item
= NavigateItemVisually (ItemNavigation
.First
);
1393 new_item
= NavigateItemVisually (ItemNavigation
.Last
);
1397 new_item
= NavigateItemVisually (ItemNavigation
.Previous
);
1401 new_item
= NavigateItemVisually (ItemNavigation
.Next
);
1405 new_item
= NavigateItemVisually (ItemNavigation
.PreviousPage
);
1409 new_item
= NavigateItemVisually (ItemNavigation
.NextPage
);
1413 if (multicolumn
== true) {
1414 new_item
= NavigateItemVisually (ItemNavigation
.NextColumn
);
1419 if (multicolumn
== true) {
1420 new_item
= NavigateItemVisually (ItemNavigation
.PreviousColumn
);
1425 if (selection_mode
== SelectionMode
.MultiSimple
) {
1426 SelectedItemFromNavigation (FocusedItem
);
1435 if (new_item
!= -1) {
1436 FocusedItem
= new_item
;
1437 if (selection_mode
!= SelectionMode
.MultiSimple
&& selection_mode
!= SelectionMode
.None
) {
1438 SelectedItemFromNavigation (new_item
);
1443 private void OnKeyUpLB (object sender
, KeyEventArgs e
)
1445 switch (e
.KeyCode
) {
1446 case Keys
.ControlKey
:
1447 ctrl_pressed
= false;
1450 shift_pressed
= false;
1457 internal void InvalidateItem (int index
)
1459 Rectangle bounds
= GetItemDisplayRectangle (index
, top_index
);
1460 if (ClientRectangle
.IntersectsWith (bounds
))
1461 Invalidate (bounds
);
1464 internal virtual void OnItemClick (int index
)
1466 OnSelectedIndexChanged (EventArgs
.Empty
);
1467 OnSelectedValueChanged (EventArgs
.Empty
);
1471 int[] prev_selection
;
1472 bool button_pressed
= false;
1474 private void SelectExtended (int index
)
1478 ArrayList new_selection
= new ArrayList ();
1479 int start
= anchor
< index
? anchor
: index
;
1480 int end
= anchor
> index
? anchor
: index
;
1481 for (int i
= start
; i
<= end
; i
++)
1482 new_selection
.Add (i
);
1485 foreach (int i
in prev_selection
)
1486 if (!selection
.Contains (i
))
1487 new_selection
.Add (i
);
1489 foreach (int i
in SelectedIndices
)
1490 if (!new_selection
.Contains (i
))
1491 UnSelectItem (i
, true);
1493 foreach (int i
in new_selection
)
1494 if (!SelectedIndices
.Contains (i
))
1499 private void OnMouseDownLB (object sender
, MouseEventArgs e
)
1501 int index
= IndexAtClientPoint (e
.X
, e
.Y
);
1506 switch (SelectionMode
) {
1507 case SelectionMode
.One
:
1508 if (SelectedIndex
!= index
) {
1509 UnSelectItem (SelectedIndex
, true);
1512 selected_index
= index
;
1515 case SelectionMode
.MultiSimple
:
1516 if (SelectedIndices
.Contains (index
))
1517 UnSelectItem (index
, true);
1522 case SelectionMode
.MultiExtended
:
1523 shift_pressed
= (XplatUI
.State
.ModifierKeys
& Keys
.Shift
) != 0;
1524 ctrl_pressed
= (XplatUI
.State
.ModifierKeys
& Keys
.Control
) != 0;
1527 prev_selection
= new int [selection
.Count
];
1528 SelectedIndices
.CopyTo (prev_selection
, 0);
1535 SelectExtended (index
);
1538 case SelectionMode
.None
:
1543 button_pressed
= true;
1544 FocusedItem
= index
;
1547 private void OnMouseMoveLB (object sender
, MouseEventArgs e
)
1549 if (!button_pressed
)
1552 int index
= IndexAtClientPoint (e
.X
, e
.Y
);
1554 switch (SelectionMode
) {
1555 case SelectionMode
.One
:
1556 if (index
== selected_index
)
1559 UnSelectItem (SelectedIndex
, true);
1561 selected_index
= index
;
1564 case SelectionMode
.MultiSimple
:
1567 case SelectionMode
.MultiExtended
:
1568 SelectExtended (index
);
1571 case SelectionMode
.None
:
1576 FocusedItem
= index
;
1579 private void OnMouseUpLB (object sender
, MouseEventArgs e
)
1582 OnDoubleClick (EventArgs
.Empty
);
1583 else if (e
.Clicks
== 1)
1584 OnClick (EventArgs
.Empty
);
1586 if (!button_pressed
)
1589 int index
= IndexAtClientPoint (e
.X
, e
.Y
);
1590 OnItemClick (index
);
1591 button_pressed
= ctrl_pressed
= shift_pressed
= false;
1594 private void Scroll (ScrollBar scrollbar
, int delta
)
1596 if (delta
== 0 || !scrollbar
.Visible
|| !scrollbar
.Enabled
)
1600 if (scrollbar
== hscrollbar
)
1601 max
= hscrollbar
.Maximum
- (items_area
.Width
/ ColumnWidthInternal
) + 1;
1603 max
= vscrollbar
.Maximum
- (items_area
.Height
/ ItemHeight
) + 1;
1605 int val
= scrollbar
.Value
+ delta
;
1608 else if (val
< scrollbar
.Minimum
)
1609 val
= scrollbar
.Minimum
;
1610 scrollbar
.Value
= val
;
1613 private void OnMouseWheelLB (object sender
, MouseEventArgs me
)
1615 if (Items
.Count
== 0)
1618 int lines
= me
.Delta
/ 120;
1621 Scroll (hscrollbar
, -SystemInformation
.MouseWheelScrollLines
* lines
);
1623 Scroll (vscrollbar
, -lines
);
1626 internal override void OnPaintInternal (PaintEventArgs pevent
)
1631 Draw (pevent
.ClipRectangle
, pevent
.Graphics
);
1634 internal void RepositionScrollBars ()
1636 if (vscrollbar
.is_visible
) {
1637 vscrollbar
.Size
= new Size (vscrollbar
.Width
, items_area
.Height
);
1638 vscrollbar
.Location
= new Point (items_area
.Width
, 0);
1641 if (hscrollbar
.is_visible
) {
1642 hscrollbar
.Size
= new Size (items_area
.Width
, hscrollbar
.Height
);
1643 hscrollbar
.Location
= new Point (0, items_area
.Height
);
1647 // Add an item in the Selection array and marks it visually as selected
1648 private void SelectItem (int index
)
1650 if (index
== -1 || SelectedIndices
.Contains (index
))
1653 selection
.Add (Items
[index
]);
1654 InvalidateItem (index
);
1657 // An item navigation operation (mouse or keyboard) has caused to select a new item
1658 internal void SelectedItemFromNavigation (int index
)
1660 switch (SelectionMode
) {
1661 case SelectionMode
.None
: // Do nothing
1663 case SelectionMode
.One
: {
1664 SelectedIndex
= index
;
1667 case SelectionMode
.MultiSimple
: {
1668 if (SelectedIndex
== -1) {
1669 SelectedIndex
= index
;
1672 if (SelectedIndices
.Contains (index
))
1673 UnSelectItem (index
, true);
1676 OnSelectedIndexChanged (new EventArgs ());
1677 OnSelectedValueChanged (new EventArgs ());
1683 case SelectionMode
.MultiExtended
: {
1684 if (SelectedIndex
== -1) {
1685 SelectedIndex
= index
;
1688 if (ctrl_pressed
== false && shift_pressed
== false) {
1692 if (shift_pressed
== true) {
1693 ShiftSelection (index
);
1694 } else { // ctrl_pressed or single item
1698 OnSelectedIndexChanged (new EventArgs ());
1699 OnSelectedValueChanged (new EventArgs ());
1709 private void ShiftSelection (int index
)
1711 int shorter_item
= -1, dist
= Items
.Count
+ 1, cur_dist
;
1713 foreach (int idx
in selected_indices
) {
1715 cur_dist
= idx
- index
;
1718 cur_dist
= index
- idx
;
1721 if (cur_dist
< dist
) {
1727 if (shorter_item
!= -1) {
1730 if (shorter_item
> index
) {
1734 start
= shorter_item
;
1739 for (int idx
= start
; idx
<= end
; idx
++) {
1745 internal int FocusedItem
{
1746 get { return focused_item; }
1748 if (focused_item
== value)
1751 int prev
= focused_item
;
1753 focused_item
= value;
1755 if (has_focus
== false)
1759 InvalidateItem (prev
);
1762 InvalidateItem (value);
1766 // Removes an item in the Selection array and marks it visually as unselected
1767 private void UnSelectItem (int index
, bool remove)
1773 selection
.Remove (Items
[index
]);
1775 InvalidateItem (index
);
1778 StringFormat string_format
;
1779 internal StringFormat StringFormat
{
1781 if (string_format
== null) {
1782 string_format
= new StringFormat ();
1783 if (RightToLeft
== RightToLeft
.Yes
)
1784 string_format
.Alignment
= StringAlignment
.Far
;
1786 string_format
.Alignment
= StringAlignment
.Near
;
1788 string_format
.SetTabStops (0, new float [] {(float)(Font.Height * 3.7)}
);
1790 return string_format
;
1795 internal virtual void CollectionChanged ()
1800 if (Items
.Count
== 0) {
1801 selected_index
= -1;
1806 if (!IsHandleCreated
|| suspend_layout
)
1814 private void UpdateListBoxBounds ()
1816 if (requested_height
== -1)
1819 SetBounds(0, 0, 0, requested_height
, BoundsSpecified
.Height
);
1822 private void UpdateScrollBars ()
1824 items_area
= ClientRectangle
;
1825 if (UpdateHorizontalScrollBar ()) {
1826 items_area
.Height
-= hscrollbar
.Height
;
1827 if (UpdateVerticalScrollBar ()) {
1828 items_area
.Width
-= vscrollbar
.Width
;
1829 UpdateHorizontalScrollBar ();
1831 } else if (UpdateVerticalScrollBar ()) {
1832 items_area
.Width
-= vscrollbar
.Width
;
1833 if (UpdateHorizontalScrollBar ()) {
1834 items_area
.Height
-= hscrollbar
.Height
;
1835 UpdateVerticalScrollBar ();
1839 RepositionScrollBars ();
1842 /* Determines if the horizontal scrollbar has to be displyed */
1843 private bool UpdateHorizontalScrollBar ()
1846 bool enabled
= true;
1849 if (canvas_size
.Width
> items_area
.Width
) {
1851 hscrollbar
.Maximum
= canvas_size
.Width
/ ColumnWidthInternal
- 1;
1852 } else if (ScrollAlwaysVisible
== true) {
1855 hscrollbar
.Maximum
= 0;
1857 } else if (canvas_size
.Width
> ClientRectangle
.Width
&& HorizontalScrollbar
) {
1859 hscrollbar
.Maximum
= canvas_size
.Width
;
1860 hscrollbar
.LargeChange
= items_area
.Width
;
1863 hbar_offset
= hscrollbar
.Value
;
1864 hscrollbar
.Enabled
= enabled
;
1865 hscrollbar
.Visible
= show
;
1870 /* Determines if the vertical scrollbar has to be displyed */
1871 private bool UpdateVerticalScrollBar ()
1873 if (MultiColumn
|| Items
.Count
== 0) {
1874 vscrollbar
.Visible
= false;
1879 bool enabled
= true;
1880 if (canvas_size
.Height
> items_area
.Height
) {
1882 vscrollbar
.Maximum
= Items
.Count
- 1;
1883 vscrollbar
.LargeChange
= items_area
.Height
/ ItemHeight
;
1884 } else if (ScrollAlwaysVisible
) {
1887 vscrollbar
.Maximum
= 0;
1890 vscrollbar
.Enabled
= enabled
;
1891 vscrollbar
.Visible
= show
;
1897 private void VerticalScrollEvent (object sender
, EventArgs e
)
1899 int top_item
= top_index
;
1901 top_index
= /*row_count + */ vscrollbar
.Value
;
1902 last_visible_index
= LastVisibleItem ();
1904 int diff
= top_item
- top_index
;
1906 XplatUI
.ScrollWindow (Handle
, items_area
, 0, ItemHeight
* diff
, false);
1909 #endregion Private Methods
1911 [ListBindable (false)]
1912 public class ObjectCollection
: IList
, ICollection
, IEnumerable
1914 internal class ListObjectComparer
: IComparer
1916 public int Compare (object a
, object b
)
1918 string str1
= a
.ToString ();
1919 string str2
= b
.ToString ();
1920 return str1
.CompareTo (str2
);
1924 private ListBox owner
;
1925 internal ArrayList object_items
= new ArrayList ();
1927 public ObjectCollection (ListBox owner
)
1932 public ObjectCollection (ListBox owner
, object[] obj
)
1938 public ObjectCollection (ListBox owner
, ObjectCollection obj
)
1944 #region Public Properties
1946 get { return object_items.Count; }
1949 public bool IsReadOnly
{
1950 get { return false; }
1954 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
1955 public virtual object this [int index
] {
1957 if (index
< 0 || index
>= Count
)
1958 throw new ArgumentOutOfRangeException ("Index of out range");
1960 return object_items
[index
];
1963 if (index
< 0 || index
>= Count
)
1964 throw new ArgumentOutOfRangeException ("Index of out range");
1966 throw new ArgumentNullException ("value");
1968 object_items
[index
] = value;
1969 owner
.CollectionChanged ();
1973 bool ICollection
.IsSynchronized
{
1974 get { return false; }
1977 object ICollection
.SyncRoot
{
1978 get { return this; }
1981 bool IList
.IsFixedSize
{
1982 get { return false; }
1985 #endregion Public Properties
1987 #region Public Methods
1988 public int Add (object item
)
1992 idx
= AddItem (item
);
1993 owner
.CollectionChanged ();
1997 public void AddRange (object[] items
)
1999 foreach (object mi
in items
)
2002 owner
.CollectionChanged ();
2005 public void AddRange (ObjectCollection col
)
2007 foreach (object mi
in col
)
2010 owner
.CollectionChanged ();
2013 internal void AddRange (IList list
)
2015 foreach (object mi
in list
)
2018 owner
.CollectionChanged ();
2021 public virtual void Clear ()
2023 owner
.selection
.Clear ();
2024 object_items
.Clear ();
2025 owner
.CollectionChanged ();
2027 public bool Contains (object obj
)
2029 return object_items
.Contains (obj
);
2032 public void CopyTo (object[] dest
, int arrayIndex
)
2034 object_items
.CopyTo (dest
, arrayIndex
);
2037 void ICollection
.CopyTo (Array dest
, int index
)
2039 object_items
.CopyTo (dest
, index
);
2042 public IEnumerator
GetEnumerator ()
2044 return object_items
.GetEnumerator ();
2047 int IList
.Add (object item
)
2052 public int IndexOf (object value)
2054 return object_items
.IndexOf (value);
2057 public void Insert (int index
, object item
)
2059 if (index
< 0 || index
> Count
)
2060 throw new ArgumentOutOfRangeException ("Index of out range");
2062 owner
.BeginUpdate ();
2063 object_items
.Insert (index
, item
);
2064 owner
.CollectionChanged ();
2068 public void Remove (object value)
2070 RemoveAt (IndexOf (value));
2073 public void RemoveAt (int index
)
2075 if (index
< 0 || index
>= Count
)
2076 throw new ArgumentOutOfRangeException ("Index of out range");
2078 owner
.selection
.Remove (object_items
[index
]);
2079 object_items
.RemoveAt (index
);
2080 owner
.CollectionChanged ();
2082 #endregion Public Methods
2084 #region Private Methods
2085 internal int AddItem (object item
)
2088 throw new ArgumentNullException ("item");
2090 int cnt
= object_items
.Count
;
2091 object_items
.Add (item
);
2095 internal void Sort ()
2097 object_items
.Sort (new ListObjectComparer ());
2100 #endregion Private Methods
2103 public class SelectedIndexCollection
: IList
, ICollection
, IEnumerable
2105 private ListBox owner
;
2107 public SelectedIndexCollection (ListBox owner
)
2112 #region Public Properties
2115 get { return owner.selection.Count; }
2118 public bool IsReadOnly
{
2119 get { return true; }
2122 public int this [int index
] {
2124 if (index
< 0 || index
>= Count
)
2125 throw new ArgumentOutOfRangeException ("Index of out range");
2127 return owner
.Items
.IndexOf (owner
.selection
[index
]);
2131 bool ICollection
.IsSynchronized
{
2132 get { return true; }
2135 bool IList
.IsFixedSize
{
2136 get { return true; }
2139 object ICollection
.SyncRoot
{
2140 get { return this; }
2143 #endregion Public Properties
2145 #region Public Methods
2146 public bool Contains (int selectedIndex
)
2148 foreach (object o
in owner
.selection
)
2149 if (owner
.Items
.IndexOf (o
) == selectedIndex
)
2154 public void CopyTo (Array dest
, int index
)
2156 foreach (object o
in owner
.selection
)
2157 dest
.SetValue(owner
.Items
.IndexOf (o
), index
++);
2160 public IEnumerator
GetEnumerator ()
2162 //FIXME: write an enumerator that uses owner.selection.GetEnumerator
2163 // so that invalidation is write on selection changes
2164 ArrayList indices
= new ArrayList ();
2165 foreach (object o
in owner
.selection
)
2166 indices
.Add (owner
.Items
.IndexOf (o
));
2167 return indices
.GetEnumerator ();
2170 int IList
.Add (object obj
)
2172 throw new NotSupportedException ();
2177 throw new NotSupportedException ();
2180 bool IList
.Contains (object selectedIndex
)
2182 return Contains ((int)selectedIndex
);
2185 int IList
.IndexOf (object selectedIndex
)
2187 return IndexOf ((int) selectedIndex
);
2190 void IList
.Insert (int index
, object value)
2192 throw new NotSupportedException ();
2195 void IList
.Remove (object value)
2197 throw new NotSupportedException ();
2200 void IList
.RemoveAt (int index
)
2202 throw new NotSupportedException ();
2205 object IList
.this[int index
]{
2206 get {return owner.Items.IndexOf (owner.selection [index]); }
2207 set {throw new NotImplementedException (); }
2210 public int IndexOf (int selectedIndex
)
2212 for (int i
= 0; i
< owner
.selection
.Count
; i
++)
2213 if (owner
.Items
.IndexOf (owner
.selection
[i
]) == selectedIndex
)
2217 #endregion Public Methods
2220 public class SelectedObjectCollection
: IList
, ICollection
, IEnumerable
2222 private ListBox owner
;
2224 public SelectedObjectCollection (ListBox owner
)
2229 #region Public Properties
2231 get { return owner.selection.Count; }
2234 public bool IsReadOnly
{
2235 get { return true; }
2239 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
2240 public object this [int index
] {
2242 if (index
< 0 || index
>= Count
)
2243 throw new ArgumentOutOfRangeException ("Index of out range");
2245 return owner
.selection
[index
];
2247 set {throw new NotSupportedException ();}
2250 bool ICollection
.IsSynchronized
{
2251 get { return true; }
2254 object ICollection
.SyncRoot
{
2255 get { return this; }
2258 bool IList
.IsFixedSize
{
2259 get { return true; }
2262 #endregion Public Properties
2264 #region Public Methods
2265 public bool Contains (object selectedObject
)
2267 return owner
.selection
.Contains (selectedObject
);
2270 public void CopyTo (Array dest
, int index
)
2272 owner
.selection
.CopyTo (dest
, index
);
2275 int IList
.Add (object value)
2277 throw new NotSupportedException ();
2282 throw new NotSupportedException ();
2285 void IList
.Insert (int index
, object value)
2287 throw new NotSupportedException ();
2290 void IList
.Remove (object value)
2292 throw new NotSupportedException ();
2295 void IList
.RemoveAt (int index
)
2297 throw new NotSupportedException ();
2300 public int IndexOf (object item
)
2302 return owner
.selection
.IndexOf (item
);
2305 public IEnumerator
GetEnumerator ()
2307 return owner
.selection
.GetEnumerator ();
2310 #endregion Public Methods