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>
30 using System.Collections;
31 using System.ComponentModel;
32 using System.Reflection;
33 using System.Runtime.InteropServices;
35 namespace System.Windows.Forms
38 [ClassInterface (ClassInterfaceType.AutoDispatch)]
41 public class CheckedListBox : ListBox
43 private CheckedIndexCollection checked_indices;
44 private CheckedItemCollection checked_items;
45 private Hashtable check_states = new Hashtable ();
46 private bool check_onclick = false;
47 private bool three_dcheckboxes = false;
49 public CheckedListBox ()
51 checked_indices = new CheckedIndexCollection (this);
52 checked_items = new CheckedItemCollection (this);
53 SetStyle (ControlStyles.ResizeRedraw, true);
57 static object ItemCheckEvent = new object ();
61 [EditorBrowsable (EditorBrowsableState.Always)]
64 [EditorBrowsable (EditorBrowsableState.Never)]
66 public new event EventHandler Click {
67 add { base.Click += value; }
68 remove { base.Click -= value; }
72 [EditorBrowsable (EditorBrowsableState.Never)]
73 public new event EventHandler DataSourceChanged {
74 add { base.DataSourceChanged += value; }
75 remove { base.DataSourceChanged -= value; }
79 [EditorBrowsable (EditorBrowsableState.Never)]
80 public new event EventHandler DisplayMemberChanged {
81 add { base.DisplayMemberChanged += value; }
82 remove { base.DisplayMemberChanged -= value; }
86 [EditorBrowsable (EditorBrowsableState.Never)]
87 public new event DrawItemEventHandler DrawItem {
88 add { base.DrawItem += value; }
89 remove { base.DrawItem -= value; }
93 [EditorBrowsable (EditorBrowsableState.Never)]
94 public new event MeasureItemEventHandler MeasureItem {
95 add { base.MeasureItem += value; }
96 remove { base.MeasureItem -= value; }
100 [EditorBrowsable (EditorBrowsableState.Never)]
101 public new event EventHandler ValueMemberChanged {
102 add { base.ValueMemberChanged += value; }
103 remove { base.ValueMemberChanged -= value; }
106 public event ItemCheckEventHandler ItemCheck {
107 add { Events.AddHandler (ItemCheckEvent, value); }
108 remove { Events.RemoveHandler (ItemCheckEvent, value); }
112 #region Public Properties
115 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
116 public CheckedListBox.CheckedIndexCollection CheckedIndices {
117 get {return checked_indices; }
121 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
122 public CheckedListBox.CheckedItemCollection CheckedItems {
123 get {return checked_items; }
126 [DefaultValue (false)]
127 public bool CheckOnClick {
128 get { return check_onclick; }
129 set { check_onclick = value; }
132 protected override CreateParams CreateParams {
133 get { return base.CreateParams;}
136 [EditorBrowsable (EditorBrowsableState.Never)]
138 public new object DataSource {
139 get { return base.DataSource; }
140 // FIXME: docs say you can't use a DataSource with this subclass
141 set { base.DataSource = value; }
144 [EditorBrowsable (EditorBrowsableState.Never)]
146 public new string DisplayMember {
147 get { return base.DisplayMember; }
148 set { base.DisplayMember = value; }
152 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
153 [EditorBrowsable (EditorBrowsableState.Never)]
154 public override DrawMode DrawMode {
155 get { return DrawMode.Normal; }
156 set { /* Not an exception, but has no effect. */ }
160 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
161 [EditorBrowsable (EditorBrowsableState.Never)]
162 public override int ItemHeight {
163 get { return base.ItemHeight; }
164 set { /* Not an exception, but has no effect. */ }
167 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
169 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
170 public new CheckedListBox.ObjectCollection Items {
171 get { return (CheckedListBox.ObjectCollection) base.Items; }
174 public override SelectionMode SelectionMode {
175 get { return base.SelectionMode; }
177 if (!Enum.IsDefined (typeof (SelectionMode), value))
178 throw new InvalidEnumArgumentException ("value", (int) value, typeof (SelectionMode));
180 if (value == SelectionMode.MultiSimple || value == SelectionMode.MultiExtended)
181 throw new ArgumentException ("Multi selection not supported on CheckedListBox");
183 base.SelectionMode = value;
187 [DefaultValue (false)]
188 public bool ThreeDCheckBoxes {
189 get { return three_dcheckboxes; }
191 if (three_dcheckboxes == value)
194 three_dcheckboxes = value;
200 [EditorBrowsable (EditorBrowsableState.Never)]
201 public new string ValueMember {
202 get { return base.ValueMember; }
203 set { base.ValueMember = value; }
206 #endregion Public Properties
208 #region Public Methods
210 protected override AccessibleObject CreateAccessibilityInstance ()
212 return base.CreateAccessibilityInstance ();
215 protected override ListBox.ObjectCollection CreateItemCollection ()
217 return new ObjectCollection (this);
220 public bool GetItemChecked (int index)
222 return check_states.Contains (Items [index]);
225 public CheckState GetItemCheckState (int index)
227 if (index < 0 || index >= Items.Count)
228 throw new ArgumentOutOfRangeException ("Index of out range");
230 object o = Items [index];
231 if (check_states.Contains (o))
232 return (CheckState) check_states [o];
234 return CheckState.Unchecked;
237 protected override void OnBackColorChanged (EventArgs e)
239 base.OnBackColorChanged (e);
242 protected override void OnClick (EventArgs e)
247 protected override void OnDrawItem (DrawItemEventArgs e)
249 if (check_states.Contains (Items [e.Index])) {
250 DrawItemState state = e.State | DrawItemState.Checked;
251 if (((CheckState) check_states [Items [e.Index]]) == CheckState.Indeterminate)
252 state |= DrawItemState.Inactive;
253 e = new DrawItemEventArgs (e.Graphics, e.Font, e.Bounds, e.Index, state, e.ForeColor, e.BackColor);
255 ThemeEngine.Current.DrawCheckedListBoxItem (this, e);
258 protected override void OnFontChanged (EventArgs e)
260 base.OnFontChanged (e);
263 protected override void OnHandleCreated (EventArgs e)
265 base.OnHandleCreated (e);
268 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
270 ItemCheckEventHandler eh = (ItemCheckEventHandler)(Events [ItemCheckEvent]);
275 protected override void OnKeyPress (KeyPressEventArgs e)
279 if (e.KeyChar == ' ' && FocusedItem != -1)
280 SetItemChecked (FocusedItem, !GetItemChecked (FocusedItem));
283 protected override void OnMeasureItem (MeasureItemEventArgs e)
285 base.OnMeasureItem (e);
288 protected override void OnSelectedIndexChanged (EventArgs e)
290 base.OnSelectedIndexChanged (e);
293 public void SetItemChecked (int index, bool value)
295 SetItemCheckState (index, value ? CheckState.Checked : CheckState.Unchecked);
298 public void SetItemCheckState (int index, CheckState value)
300 if (index < 0 || index >= Items.Count)
301 throw new ArgumentOutOfRangeException ("Index of out range");
303 if (!Enum.IsDefined (typeof (CheckState), value))
304 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for CheckState", value));
306 CheckState old_value = GetItemCheckState (index);
308 if (old_value == value)
311 OnItemCheck (new ItemCheckEventArgs (index, value, old_value));
314 case CheckState.Checked:
315 case CheckState.Indeterminate:
316 check_states [Items[index]] = value;
318 case CheckState.Unchecked:
319 check_states.Remove (Items[index]);
325 UpdateCollections ();
327 InvalidateCheckbox (index);
330 protected override void WmReflectCommand (ref Message m)
332 base.WmReflectCommand (ref m);
335 protected override void WndProc (ref Message m)
337 base.WndProc (ref m);
340 #endregion Public Methods
342 #region Private Methods
344 int last_clicked_index = -1;
346 internal override void OnItemClick (int index)
348 if (CheckOnClick || last_clicked_index == index) {
349 if (GetItemChecked (index))
350 SetItemCheckState (index, CheckState.Unchecked);
352 SetItemCheckState (index, CheckState.Checked);
355 last_clicked_index = index;
356 base.OnItemClick (index);
359 internal override void CollectionChanged ()
361 base.CollectionChanged ();
362 UpdateCollections ();
365 private void InvalidateCheckbox (int index)
367 Rectangle area = GetItemDisplayRectangle (index, TopIndex);
369 area.Y += (area.Height - 11) / 2;
375 private void UpdateCollections ()
377 CheckedItems.Refresh ();
378 CheckedIndices.Refresh ();
381 #endregion Private Methods
383 public new class ObjectCollection : ListBox.ObjectCollection
385 private CheckedListBox owner;
387 public ObjectCollection (CheckedListBox owner) : base (owner)
392 public int Add (object item, bool isChecked)
394 return Add (item, isChecked ? CheckState.Checked : CheckState.Unchecked);
397 public int Add (object item, CheckState check)
400 if (check != CheckState.Unchecked)
401 owner.check_states [item] = check;
402 if (check == CheckState.Checked)
403 owner.OnItemCheck (new ItemCheckEventArgs (Count-1, check, CheckState.Unchecked));
404 owner.UpdateCollections ();
409 public class CheckedIndexCollection : IList, ICollection, IEnumerable
411 private CheckedListBox owner;
412 private ArrayList indices = new ArrayList ();
414 internal CheckedIndexCollection (CheckedListBox owner)
419 #region Public Properties
421 get { return indices.Count; }
424 public bool IsReadOnly {
428 bool ICollection.IsSynchronized {
429 get { return false; }
432 bool IList.IsFixedSize{
436 object ICollection.SyncRoot {
441 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
442 public int this[int index] {
444 if (index < 0 || index >= Count)
445 throw new ArgumentOutOfRangeException ("Index of out range");
447 return (int) indices[index];
450 #endregion Public Properties
452 public bool Contains (int index)
454 return indices.Contains (index);
458 public void CopyTo (Array dest, int index)
460 indices.CopyTo (dest, index);
463 public IEnumerator GetEnumerator ()
465 return indices.GetEnumerator ();
468 int IList.Add (object value)
470 throw new NotSupportedException ();
475 throw new NotSupportedException ();
478 bool IList.Contains (object index)
480 return Contains ((int)index);
483 int IList.IndexOf (object index)
485 return IndexOf ((int) index);
488 void IList.Insert (int index, object value)
490 throw new NotSupportedException ();
493 void IList.Remove (object value)
495 throw new NotSupportedException ();
498 void IList.RemoveAt (int index)
500 throw new NotSupportedException ();
503 object IList.this[int index]{
504 get {return indices[index]; }
505 set {throw new NotImplementedException (); }
508 public int IndexOf (int index)
510 return indices.IndexOf (index);
513 #region Private Methods
514 internal void Refresh ()
517 for (int i = 0; i < owner.Items.Count; i++)
518 if (owner.check_states.Contains (owner.Items [i]))
521 #endregion Private Methods
525 public class CheckedItemCollection : IList, ICollection, IEnumerable
527 private CheckedListBox owner;
528 private ArrayList list = new ArrayList ();
530 internal CheckedItemCollection (CheckedListBox owner)
535 #region Public Properties
537 get { return list.Count; }
540 public bool IsReadOnly {
545 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
546 public object this [int index] {
548 if (index < 0 || index >= Count)
549 throw new ArgumentOutOfRangeException ("Index of out range");
553 set {throw new NotSupportedException ();}
556 bool ICollection.IsSynchronized {
560 object ICollection.SyncRoot {
564 bool IList.IsFixedSize {
568 #endregion Public Properties
570 #region Public Methods
571 public bool Contains (object selectedObject)
573 return list.Contains (selectedObject);
576 public void CopyTo (Array dest, int index)
578 list.CopyTo (dest, index);
581 int IList.Add (object value)
583 throw new NotSupportedException ();
588 throw new NotSupportedException ();
591 void IList.Insert (int index, object value)
593 throw new NotSupportedException ();
596 void IList.Remove (object value)
598 throw new NotSupportedException ();
601 void IList.RemoveAt (int index)
603 throw new NotSupportedException ();
606 public int IndexOf (object item)
608 return list.IndexOf (item);
611 public IEnumerator GetEnumerator ()
613 return list.GetEnumerator ();
616 #endregion Public Methods
618 #region Private Methods
619 internal void Refresh ()
622 for (int i = 0; i < owner.Items.Count; i++)
623 if (owner.check_states.Contains (owner.Items [i]))
624 list.Add (owner.Items[i]);
626 #endregion Private Methods
629 [DefaultValue (false)]
630 public bool UseCompatibleTextRendering {
631 get { return use_compatible_text_rendering; }
632 set { use_compatible_text_rendering = value; }