ListBox.SelectedObjectCollection.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Collections;
  5. using System.ComponentModel;
  6. namespace System.Windows.Forms
  7. {
  8. public partial class ListBox
  9. {
  10. // Should be "ObjectCollection", except we already have one of those.
  11. public class SelectedObjectCollection : IList
  12. {
  13. // This is the bitmask used within ItemArray to identify selected objects.
  14. internal static int SelectedObjectMask = ItemArray.CreateMask();
  15. private readonly ListBox _owner;
  16. private bool stateDirty;
  17. private int lastVersion;
  18. private int count;
  19. public SelectedObjectCollection(ListBox owner)
  20. {
  21. _owner = owner ?? throw new ArgumentNullException(nameof(owner));
  22. stateDirty = true;
  23. lastVersion = -1;
  24. }
  25. /// <summary>
  26. /// Number of current selected items.
  27. /// </summary>
  28. public int Count
  29. {
  30. get
  31. {
  32. // If the handle hasn't been created, we must do this the hard way.
  33. // Getting the count when using a mask is expensive, so cache it.
  34. //
  35. if (lastVersion != InnerArray.Version)
  36. {
  37. lastVersion = InnerArray.Version;
  38. count = InnerArray.GetCount(SelectedObjectMask);
  39. }
  40. return count;
  41. }
  42. }
  43. object ICollection.SyncRoot
  44. {
  45. get
  46. {
  47. return this;
  48. }
  49. }
  50. bool ICollection.IsSynchronized
  51. {
  52. get
  53. {
  54. return false;
  55. }
  56. }
  57. bool IList.IsFixedSize
  58. {
  59. get
  60. {
  61. return true;
  62. }
  63. }
  64. /// <summary>
  65. /// Called by the list box to dirty the selected item state.
  66. /// </summary>
  67. internal void Dirty()
  68. {
  69. stateDirty = true;
  70. }
  71. /// <summary>
  72. /// This is the item array that stores our data. We share this backing store
  73. /// with the main object collection.
  74. /// </summary>
  75. private ItemArray InnerArray
  76. {
  77. get
  78. {
  79. EnsureUpToDate();
  80. return ((ObjectCollection)_owner.Items).InnerArray;
  81. }
  82. }
  83. /// <summary>
  84. /// This is the function that Ensures that the selections are uptodate with
  85. /// current listbox handle selections.
  86. /// </summary>
  87. internal void EnsureUpToDate()
  88. {
  89. if (stateDirty)
  90. {
  91. stateDirty = false;
  92. }
  93. }
  94. public bool IsReadOnly
  95. {
  96. get
  97. {
  98. return true;
  99. }
  100. }
  101. public bool Contains(object selectedObject)
  102. {
  103. return IndexOf(selectedObject) != -1;
  104. }
  105. public int IndexOf(object selectedObject)
  106. {
  107. return InnerArray.IndexOf(selectedObject, SelectedObjectMask);
  108. }
  109. int IList.Add(object value)
  110. {
  111. throw new NotSupportedException();
  112. }
  113. void IList.Clear()
  114. {
  115. throw new NotSupportedException();
  116. }
  117. void IList.Insert(int index, object value)
  118. {
  119. throw new NotSupportedException();
  120. }
  121. void IList.Remove(object value)
  122. {
  123. throw new NotSupportedException();
  124. }
  125. void IList.RemoveAt(int index)
  126. {
  127. throw new NotSupportedException();
  128. }
  129. // A new internal method used in SelectedIndex getter...
  130. // For a Multi select ListBox there can be two items with the same name ...
  131. // and hence a object comparison is required...
  132. // This method returns the "object" at the passed index rather than the "item" ...
  133. // this "object" is then compared in the IndexOf( ) method of the itemsCollection.
  134. //
  135. internal object GetObjectAt(int index)
  136. {
  137. return InnerArray.GetEntryObject(index, SelectedObjectCollection.SelectedObjectMask);
  138. }
  139. /// <summary>
  140. /// Retrieves the specified selected item.
  141. /// </summary>
  142. [Browsable(false)]
  143. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  144. public object this[int index]
  145. {
  146. get
  147. {
  148. return InnerArray.GetItem(index, SelectedObjectMask);
  149. }
  150. set
  151. {
  152. throw new NotSupportedException();
  153. }
  154. }
  155. public void CopyTo(Array destination, int index)
  156. {
  157. int cnt = InnerArray.GetCount(SelectedObjectMask);
  158. for (int i = 0; i < cnt; i++)
  159. {
  160. destination.SetValue(InnerArray.GetItem(i, SelectedObjectMask), i + index);
  161. }
  162. }
  163. public IEnumerator GetEnumerator()
  164. {
  165. return InnerArray.GetEnumerator(SelectedObjectMask);
  166. }
  167. /// <summary>
  168. /// This method returns if the actual item index is selected. The index is the index to the MAIN
  169. /// collection, not this one.
  170. /// </summary>
  171. internal bool GetSelected(int index)
  172. {
  173. return InnerArray.GetState(index, SelectedObjectMask);
  174. }
  175. /// <summary>
  176. /// Same thing for GetSelected.
  177. /// </summary>
  178. internal void SetSelected(int index, bool value)
  179. {
  180. InnerArray.SetState(index, SelectedObjectMask, value);
  181. }
  182. public void Clear()
  183. {
  184. if (_owner != null)
  185. {
  186. _owner.ClearSelected();
  187. }
  188. }
  189. public void Add(object value)
  190. {
  191. if (_owner != null)
  192. {
  193. ObjectCollection items = _owner.Items;
  194. if (items != null && value != null)
  195. {
  196. int index = items.IndexOf(value);
  197. if (index != -1 && !GetSelected(index))
  198. {
  199. _owner.SelectedIndex = index;
  200. }
  201. }
  202. }
  203. }
  204. public void Remove(object value)
  205. {
  206. if (_owner != null)
  207. {
  208. ObjectCollection items = _owner.Items;
  209. if (items != null & value != null)
  210. {
  211. int index = items.IndexOf(value);
  212. if (index != -1 && GetSelected(index))
  213. {
  214. _owner.SetSelected(index, false);
  215. }
  216. }
  217. }
  218. }
  219. }
  220. }
  221. }