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
37 [ClassInterface (ClassInterfaceType.AutoDispatch)]
39 [LookupBindingPropertiesAttribute ()]
40 public class CheckedListBox : ListBox
42 private CheckedIndexCollection checked_indices;
43 private CheckedItemCollection checked_items;
44 private Hashtable check_states = new Hashtable ();
45 private bool check_onclick = false;
46 private bool three_dcheckboxes = false;
48 public CheckedListBox ()
50 checked_indices = new CheckedIndexCollection (this);
51 checked_items = new CheckedItemCollection (this);
52 SetStyle (ControlStyles.ResizeRedraw, true);
56 static object ItemCheckEvent = new object ();
59 [EditorBrowsable (EditorBrowsableState.Always)]
60 public new event EventHandler Click {
61 add { base.Click += value; }
62 remove { base.Click -= value; }
66 [EditorBrowsable (EditorBrowsableState.Never)]
67 public new event EventHandler DataSourceChanged {
68 add { base.DataSourceChanged += value; }
69 remove { base.DataSourceChanged -= value; }
73 [EditorBrowsable (EditorBrowsableState.Never)]
74 public new event EventHandler DisplayMemberChanged {
75 add { base.DisplayMemberChanged += value; }
76 remove { base.DisplayMemberChanged -= value; }
80 [EditorBrowsable (EditorBrowsableState.Never)]
81 public new event DrawItemEventHandler DrawItem {
82 add { base.DrawItem += value; }
83 remove { base.DrawItem -= value; }
87 [EditorBrowsable (EditorBrowsableState.Never)]
88 public new event MeasureItemEventHandler MeasureItem {
89 add { base.MeasureItem += value; }
90 remove { base.MeasureItem -= value; }
94 [EditorBrowsable (EditorBrowsableState.Never)]
95 public new event EventHandler ValueMemberChanged {
96 add { base.ValueMemberChanged += value; }
97 remove { base.ValueMemberChanged -= value; }
100 public event ItemCheckEventHandler ItemCheck {
101 add { Events.AddHandler (ItemCheckEvent, value); }
102 remove { Events.RemoveHandler (ItemCheckEvent, value); }
106 [EditorBrowsable (EditorBrowsableState.Always)]
107 public new event MouseEventHandler MouseClick {
108 add { base.MouseClick += value; }
109 remove { base.MouseClick -= value; }
113 #region Public Properties
116 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
117 public CheckedListBox.CheckedIndexCollection CheckedIndices {
118 get {return checked_indices; }
122 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
123 public CheckedListBox.CheckedItemCollection CheckedItems {
124 get {return checked_items; }
127 [DefaultValue (false)]
128 public bool CheckOnClick {
129 get { return check_onclick; }
130 set { check_onclick = value; }
133 protected override CreateParams CreateParams {
134 get { return base.CreateParams;}
137 [EditorBrowsable (EditorBrowsableState.Never)]
139 public new object DataSource {
140 get { return base.DataSource; }
141 // FIXME: docs say you can't use a DataSource with this subclass
142 set { base.DataSource = value; }
145 [EditorBrowsable (EditorBrowsableState.Never)]
147 public new string DisplayMember {
148 get { return base.DisplayMember; }
149 set { base.DisplayMember = value; }
153 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
154 [EditorBrowsable (EditorBrowsableState.Never)]
155 public override DrawMode DrawMode {
156 get { return DrawMode.Normal; }
157 set { /* Not an exception, but has no effect. */ }
161 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
162 [EditorBrowsable (EditorBrowsableState.Never)]
163 public override int ItemHeight {
164 get { return base.ItemHeight; }
165 set { /* Not an exception, but has no effect. */ }
168 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
170 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
171 public new CheckedListBox.ObjectCollection Items {
172 get { return (CheckedListBox.ObjectCollection) base.Items; }
175 public override SelectionMode SelectionMode {
176 get { return base.SelectionMode; }
178 if (!Enum.IsDefined (typeof (SelectionMode), value))
179 throw new InvalidEnumArgumentException ("value", (int) value, typeof (SelectionMode));
181 if (value == SelectionMode.MultiSimple || value == SelectionMode.MultiExtended)
182 throw new ArgumentException ("Multi selection not supported on CheckedListBox");
184 base.SelectionMode = value;
188 [DefaultValue (false)]
189 public bool ThreeDCheckBoxes {
190 get { return three_dcheckboxes; }
192 if (three_dcheckboxes == value)
195 three_dcheckboxes = value;
201 [EditorBrowsable (EditorBrowsableState.Never)]
202 public new string ValueMember {
203 get { return base.ValueMember; }
204 set { base.ValueMember = value; }
208 [EditorBrowsable (EditorBrowsableState.Never)]
209 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
210 public new Padding Padding {
211 get { return base.Padding; }
212 set { base.Padding = value; }
214 #endregion Public Properties
216 #region Public Methods
218 protected override AccessibleObject CreateAccessibilityInstance ()
220 return base.CreateAccessibilityInstance ();
223 protected override ListBox.ObjectCollection CreateItemCollection ()
225 return new ObjectCollection (this);
228 public bool GetItemChecked (int index)
230 return check_states.Contains (Items [index]);
233 public CheckState GetItemCheckState (int index)
235 if (index < 0 || index >= Items.Count)
236 throw new ArgumentOutOfRangeException ("Index of out range");
238 object o = Items [index];
239 if (check_states.Contains (o))
240 return (CheckState) check_states [o];
242 return CheckState.Unchecked;
245 protected override void OnBackColorChanged (EventArgs e)
247 base.OnBackColorChanged (e);
250 protected override void OnClick (EventArgs e)
255 protected override void OnDrawItem (DrawItemEventArgs e)
257 if (check_states.Contains (Items [e.Index])) {
258 DrawItemState state = e.State | DrawItemState.Checked;
259 if (((CheckState) check_states [Items [e.Index]]) == CheckState.Indeterminate)
260 state |= DrawItemState.Inactive;
261 e = new DrawItemEventArgs (e.Graphics, e.Font, e.Bounds, e.Index, state, e.ForeColor, e.BackColor);
263 ThemeEngine.Current.DrawCheckedListBoxItem (this, e);
266 protected override void OnFontChanged (EventArgs e)
268 base.OnFontChanged (e);
271 protected override void OnHandleCreated (EventArgs e)
273 base.OnHandleCreated (e);
276 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
278 ItemCheckEventHandler eh = (ItemCheckEventHandler)(Events [ItemCheckEvent]);
283 protected override void OnKeyPress (KeyPressEventArgs e)
287 if (e.KeyChar == ' ' && FocusedItem != -1)
288 SetItemChecked (FocusedItem, !GetItemChecked (FocusedItem));
291 protected override void OnMeasureItem (MeasureItemEventArgs e)
293 base.OnMeasureItem (e);
296 protected override void OnSelectedIndexChanged (EventArgs e)
298 base.OnSelectedIndexChanged (e);
301 protected override void RefreshItems ()
303 base.RefreshItems ();
306 public void SetItemChecked (int index, bool value)
308 SetItemCheckState (index, value ? CheckState.Checked : CheckState.Unchecked);
311 public void SetItemCheckState (int index, CheckState value)
313 if (index < 0 || index >= Items.Count)
314 throw new ArgumentOutOfRangeException ("Index of out range");
316 if (!Enum.IsDefined (typeof (CheckState), value))
317 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for CheckState", value));
319 CheckState old_value = GetItemCheckState (index);
321 if (old_value == value)
324 ItemCheckEventArgs icea = new ItemCheckEventArgs (index, value, old_value);
327 switch (icea.NewValue) {
328 case CheckState.Checked:
329 case CheckState.Indeterminate:
330 check_states[Items[index]] = icea.NewValue;
332 case CheckState.Unchecked:
333 check_states.Remove (Items[index]);
339 UpdateCollections ();
341 InvalidateCheckbox (index);
344 protected override void WmReflectCommand (ref Message m)
346 base.WmReflectCommand (ref m);
349 protected override void WndProc (ref Message m)
351 base.WndProc (ref m);
354 #endregion Public Methods
356 #region Private Methods
358 int last_clicked_index = -1;
360 internal override void OnItemClick (int index)
362 if ((CheckOnClick || last_clicked_index == index) && index > -1) {
363 if (GetItemChecked (index))
364 SetItemCheckState (index, CheckState.Unchecked);
366 SetItemCheckState (index, CheckState.Checked);
369 last_clicked_index = index;
370 base.OnItemClick (index);
373 internal override void CollectionChanged ()
375 base.CollectionChanged ();
376 UpdateCollections ();
379 private void InvalidateCheckbox (int index)
381 Rectangle area = GetItemDisplayRectangle (index, TopIndex);
383 area.Y += (area.Height - 11) / 2;
389 private void UpdateCollections ()
391 CheckedItems.Refresh ();
392 CheckedIndices.Refresh ();
395 #endregion Private Methods
397 public new class ObjectCollection : ListBox.ObjectCollection
399 private CheckedListBox owner;
401 public ObjectCollection (CheckedListBox owner) : base (owner)
406 public int Add (object item, bool isChecked)
408 return Add (item, isChecked ? CheckState.Checked : CheckState.Unchecked);
411 public int Add (object item, CheckState check)
413 int idx = Add (item);
415 ItemCheckEventArgs icea = new ItemCheckEventArgs (idx, check, CheckState.Unchecked);
417 if (check == CheckState.Checked)
418 owner.OnItemCheck (icea);
420 if (icea.NewValue != CheckState.Unchecked)
421 owner.check_states[item] = icea.NewValue;
423 owner.UpdateCollections ();
428 public class CheckedIndexCollection : IList, ICollection, IEnumerable
430 private CheckedListBox owner;
431 private ArrayList indices = new ArrayList ();
433 internal CheckedIndexCollection (CheckedListBox owner)
438 #region Public Properties
440 get { return indices.Count; }
443 public bool IsReadOnly {
447 bool ICollection.IsSynchronized {
448 get { return false; }
451 bool IList.IsFixedSize{
455 object ICollection.SyncRoot {
460 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
461 public int this[int index] {
463 if (index < 0 || index >= Count)
464 throw new ArgumentOutOfRangeException ("Index of out range");
466 return (int) indices[index];
469 #endregion Public Properties
471 public bool Contains (int index)
473 return indices.Contains (index);
477 public void CopyTo (Array dest, int index)
479 indices.CopyTo (dest, index);
482 public IEnumerator GetEnumerator ()
484 return indices.GetEnumerator ();
487 int IList.Add (object value)
489 throw new NotSupportedException ();
494 throw new NotSupportedException ();
497 bool IList.Contains (object index)
499 return Contains ((int)index);
502 int IList.IndexOf (object index)
504 return IndexOf ((int) index);
507 void IList.Insert (int index, object value)
509 throw new NotSupportedException ();
512 void IList.Remove (object value)
514 throw new NotSupportedException ();
517 void IList.RemoveAt (int index)
519 throw new NotSupportedException ();
522 object IList.this[int index]{
523 get {return indices[index]; }
524 set {throw new NotImplementedException (); }
527 public int IndexOf (int index)
529 return indices.IndexOf (index);
532 #region Private Methods
533 internal void Refresh ()
536 for (int i = 0; i < owner.Items.Count; i++)
537 if (owner.check_states.Contains (owner.Items [i]))
540 #endregion Private Methods
544 public class CheckedItemCollection : IList, ICollection, IEnumerable
546 private CheckedListBox owner;
547 private ArrayList list = new ArrayList ();
549 internal CheckedItemCollection (CheckedListBox owner)
554 #region Public Properties
556 get { return list.Count; }
559 public bool IsReadOnly {
564 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
565 public object this [int index] {
567 if (index < 0 || index >= Count)
568 throw new ArgumentOutOfRangeException ("Index of out range");
572 set {throw new NotSupportedException ();}
575 bool ICollection.IsSynchronized {
579 object ICollection.SyncRoot {
583 bool IList.IsFixedSize {
587 #endregion Public Properties
589 #region Public Methods
590 public bool Contains (object item)
592 return list.Contains (item);
595 public void CopyTo (Array dest, int index)
597 list.CopyTo (dest, index);
600 int IList.Add (object value)
602 throw new NotSupportedException ();
607 throw new NotSupportedException ();
610 void IList.Insert (int index, object value)
612 throw new NotSupportedException ();
615 void IList.Remove (object value)
617 throw new NotSupportedException ();
620 void IList.RemoveAt (int index)
622 throw new NotSupportedException ();
625 public int IndexOf (object item)
627 return list.IndexOf (item);
630 public IEnumerator GetEnumerator ()
632 return list.GetEnumerator ();
635 #endregion Public Methods
637 #region Private Methods
638 internal void Refresh ()
641 for (int i = 0; i < owner.Items.Count; i++)
642 if (owner.check_states.Contains (owner.Items [i]))
643 list.Add (owner.Items[i]);
645 #endregion Private Methods
647 [DefaultValue (false)]
648 public bool UseCompatibleTextRendering {
649 get { return use_compatible_text_rendering; }
650 set { use_compatible_text_rendering = value; }