// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections; using System.ComponentModel; namespace System.Windows.Forms { public partial class ListBox { public class SelectedIndexCollection : IList { private readonly ListBox _owner; public SelectedIndexCollection(ListBox owner) { _owner = owner ?? throw new ArgumentNullException(nameof(owner)); } /// /// Number of current selected items. /// [Browsable(false)] public int Count { get { return _owner.SelectedItems.Count; } } object ICollection.SyncRoot { get { return this; } } bool ICollection.IsSynchronized { get { return true; } } bool IList.IsFixedSize { get { return true; } } public bool IsReadOnly { get { return true; } } public bool Contains(int selectedIndex) { return IndexOf(selectedIndex) != -1; } bool IList.Contains(object selectedIndex) { if (selectedIndex is int) { return Contains((int)selectedIndex); } else { return false; } } public int IndexOf(int selectedIndex) { // Just what does this do? The selectedIndex parameter above is the index into the // main object collection. We look at the state of that item, and if the state indicates // that it is selected, we get back the virtualized index into this collection. Indexes on // this collection match those on the SelectedObjectCollection. if (selectedIndex >= 0 && selectedIndex < InnerArray.GetCount(0) && InnerArray.GetState(selectedIndex, SelectedObjectCollection.SelectedObjectMask)) { return InnerArray.IndexOf(InnerArray.GetItem(selectedIndex, 0), SelectedObjectCollection.SelectedObjectMask); } return -1; } int IList.IndexOf(object selectedIndex) { if (selectedIndex is int) { return IndexOf((int)selectedIndex); } else { return -1; } } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } /// /// Retrieves the specified selected item. /// public int this[int index] { get { object identifier = InnerArray.GetEntryObject(index, SelectedObjectCollection.SelectedObjectMask); return InnerArray.IndexOfIdentifier(identifier, 0); } } object IList.this[int index] { get { return this[index]; } set { throw new NotSupportedException(); } } /// /// This is the item array that stores our data. We share this backing store /// with the main object collection. /// private ItemArray InnerArray { get { _owner.SelectedItems.EnsureUpToDate(); return ((ObjectCollection)_owner.Items).InnerArray; } } public void CopyTo(Array destination, int index) { int cnt = Count; for (int i = 0; i < cnt; i++) { destination.SetValue(this[i], i + index); } } public void Clear() { if (_owner != null) { _owner.ClearSelected(); } } public void Add(int index) { if (_owner != null) { ObjectCollection items = _owner.Items; if (items != null) { if (index != -1 && !Contains(index)) { _owner.SetSelected(index, true); } } } } public void Remove(int index) { if (_owner != null) { ObjectCollection items = _owner.Items; if (items != null) { if (index != -1 && Contains(index)) { _owner.SetSelected(index, false); } } } } public IEnumerator GetEnumerator() { return new SelectedIndexEnumerator(this); } /// /// EntryEnumerator is an enumerator that will enumerate over /// a given state mask. /// private class SelectedIndexEnumerator : IEnumerator { private readonly SelectedIndexCollection items; private int current; /// /// Creates a new enumerator that will enumerate over the given state. /// public SelectedIndexEnumerator(SelectedIndexCollection items) { this.items = items; current = -1; } /// /// Moves to the next element, or returns false if at the end. /// bool IEnumerator.MoveNext() { if (current < items.Count - 1) { current++; return true; } else { current = items.Count; return false; } } /// /// Resets the enumeration back to the beginning. /// void IEnumerator.Reset() { current = -1; } /// /// Retrieves the current value in the enumerator. /// object IEnumerator.Current { get { if (current == -1 || current == items.Count) { throw new InvalidOperationException(); } return items[current]; } } } } } }