2012-11-15 80 views
3

我的自定義組合框源代碼如下:自定義組合框拋出ArgumentOutOfRangeException

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using System.Windows.Forms; 

namespace IHWinUtility 
{ 
    public class IHComboBox : ComboBox 
    { 
     private IHComboBoxItems _ihComboBoxItems; 

     public IHComboBox() 
     { 
      this.DropDownStyle = ComboBoxStyle.DropDownList; 
      _ihComboBoxItems = new IHComboBoxItems(this); 
     } 

     new public IHComboBoxItems Items 
     { 
      get { return _ihComboBoxItems; } 
      set { _ihComboBoxItems = (IHComboBoxItems)value; } 
     } 

     new public string SelectedValue 
     { 
      get { return this.SelectedItem == null ? "" : ((IHComboBoxItem)this.SelectedItem).Value.ToString(); } 
     } 
    } 


    public class IHComboBoxItems : ComboBox.ObjectCollection 
    { 
     public IHComboBox _ihComboBox; 

     public IHComboBoxItems(IHComboBox owner) : base(owner) 
     { 
      _ihComboBox = owner; 
     } 

     public int Add(string Text, object Value) 
     { 
      int _retValue = 0; 

      IHComboBoxItem _item = new IHComboBoxItem(); 
      _item.Text = Text; 
      _item.Value = Value; 
      _ihComboBox.Items.Add(_item); 

      _retValue = _ihComboBox.Items.Count; 

      return _retValue; 
     } 

     new public void Insert(int index, object item) 
     { 

     } 
    } 


    public class IHComboBoxItem 
    { 
     public string Text { get; set; } 
     public object Value { get; set; } 

     public override string ToString() 
     { 
      return Text; 
     } 
    } 
} 

,我增加了一些數據添加到組合框,如下:

private void Form1_Load(object sender, EventArgs e) 
    { 
     this.ihComboBox1.Items.Add("Text1", "Value1"); 
    } 

它工作得很好。 我可以看到Text1綁定到我的Combobox。 但問題是,當我通過點擊組合框的箭頭更改selectedItem屬性,它拋出我下面的錯誤:

System.ArgumentOutOfRangeException was unhandled Message="InvalidArgument=Value of '0' is not valid for 'index'. 
Parameter name: index 
    at: System.ArgumentOutOfRangeException System.Windows.Forms.ComboBox.ObjectCollection.get_Item(Int32 index) 
    at: System.Windows.Forms.ComboBox.get_SelectedItem() 
    at: System.Windows.Forms.ComboBox.get_Text() 
    at: System.Windows.Forms.ComboBox.WmReflectCommand(Message& m) 
    at: System.Windows.Forms.ComboBox.WndProc(Message& m) 
    at: System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at: System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at: System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

誰能幫我這個錯誤?

回答

0

在選定的值中,您試圖強制一個值。但是這個價值不在收藏。

0

當您的代碼調用IHComboBoxItems :: Add方法時,新對象將添加到IHComboBox._ihComboBoxItems集合中,與原始ComboBox.Items集合不同。原始ComboBox.Items將爲空。

ComboBox.get_Text使用ComboBox.Items屬性通過當前SelectedIndex獲取SelectedItem。

下拉列表使用反射枚舉Items集合,與映射到新的IHComboBoxItems.Items屬性(在調用Add後將不會爲空),並允許用戶選擇非零SelectedIndex,但原始ComboBoxItems.Items將保持爲空。當內部ComboBox代碼嘗試加載文本時,它會調用原始ComboBox.Items(保持爲空),並使用非零SelectedIndex並導致Exception。

嘗試在ObjectCollection上創建和使用包裝,而不是創建新的ObjectCollection實例。 但是在包裝器代碼中,每次在使用它之前都必須檢查到ObjectCollection實例的鏈接(或者您將得到ArgumentOutOfRangeException),因爲ComboBox代碼可以重新創建它並且不允許重寫創建ObjectCollection實例構造。

代碼示例:

public abstract class TypedComboBox<T> : ComboBox 
{ 
    public TypedComboBox() 
    { 
     _objectCollectionProxy = new TypedObjectCollectionProxy<T>(this); 
    } 

    private TypedObjectCollectionProxy<T> _objectCollectionProxy; 

    public ObjectCollection ObjectCollectionCollection 
    { 
     get { return base.Items; } 
    } 

    public class TypedObjectCollectionProxy<ItemType> : IList, IList<ItemType>, ICollection, ICollection<ItemType>, IEnumerable, IEnumerable<ItemType> 
    { 
     public ObjectCollection _objectCollection; 
     private TypedComboBox<T> _owner; 

     public TypedObjectCollectionProxy(TypedComboBox<T> owner) 
     { 
      this._owner = owner; 
      this._objectCollection = owner.ObjectCollectionCollection; 
     } 

     /// <summary>Gets the number of items in the collection</summary> 
     public int Count { get { return _objectCollection.Count; } } 
     /// <summary>Gets a value indicating whether this collection can be modified</summary> 
     public bool IsReadOnly { get { return _objectCollection.IsReadOnly; } } 

     /// <summary>Retrieves the item at the specified index within the collection</summary> 
     /// <param name="index">The index of the item in the collection to retrieve</param> 
     /// <returns>An object representing the item located at the specified index within the collection</returns> 
     /// <exception cref="System.ArgumentOutOfRangeException">The index was less than zero.-or- The index was greater than the count of 
     ///               items in the collection.</exception> 
     [Browsable(false)] 
     [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
     public virtual ItemType this[int index] 
     { 
      get 
      { 
       CheckItems(); 
       return (ItemType)_objectCollection[index]; 
      } 
      set 
      { 
       CheckItems(); 
       _objectCollection[index] = value; 
      } 
     } 

     public void CheckItems() 
     { 
      if (this._objectCollection != _owner.ObjectCollectionCollection) 
       this._objectCollection = _owner.ObjectCollectionCollection; 
     } 

     /// <summary>Adds an item to the list of items for a System.Windows.Forms.ComboBox</summary> 
     /// <param name="item">An object representing the item to add to the collection</param> 
     /// <returns>The zero-based index of the item in the collection</returns> 
     /// <exception cref="System.ArgumentNullException">The item parameter was null</exception> 
     public int Add(ItemType item) 
     { 
      CheckItems(); 
      return _objectCollection.Add(item); 
     } 

     /// <summary>Adds an array of items to the list of items for a System.Windows.Forms.ComboBox</summary> 
     /// <param name="items">An array of objects to add to the list</param> 
     /// <exception cref="System.ArgumentNullException">An item in the items parameter was null</exception> 
     public void AddRange(IEnumerable<ItemType> items) 
     { 
      CheckItems(); 
      _objectCollection.AddRange(items.Cast<object>().ToArray()); 
     } 

     /// <summary>Removes all items from the System.Windows.Forms.ComboBox</summary> 
     public void Clear() 
     { 
      CheckItems(); 
      _objectCollection.Clear(); 
     } 

     /// <summary>Determines if the specified item is located within the collection</summary> 
     /// <param name="value">An object representing the item to locate in the collection</param> 
     /// <returns>true if the item is located within the collection; otherwise, false</returns> 
     public bool Contains(ItemType value) 
     { 
      CheckItems(); 
      return _objectCollection.Contains(value); 
     } 

     /// <summary>Copies the entire collection into an existing array of objects at a specified location within the array</summary> 
     /// <param name="destination">The object array to copy the collection to</param> 
     /// <param name="arrayIndex">The location in the destination array to copy the collection to</param> 
     public void CopyTo(object[] destination, int arrayIndex) 
     { 
      CheckItems(); 
      _objectCollection.CopyTo(destination, arrayIndex); 
     } 

     /// <summary>Returns an enumerator that can be used to iterate through the item collection</summary> 
     /// <returns>An System.Collections.IEnumerator that represents the item collection</returns> 
     public IEnumerator GetEnumerator() 
     { 
      CheckItems(); 
      return _objectCollection.GetEnumerator(); 
     } 

     /// <summary>Retrieves the index within the collection of the specified item</summary> 
     /// <param name="value">An object representing the item to locate in the collection</param> 
     /// <returns>The zero-based index where the item is located within the collection; otherwise, -1</returns> 
     /// <exception cref="System.ArgumentNullException">The value parameter was null</exception> 
     public int IndexOf(ItemType value) 
     { 
      CheckItems(); 
      return _objectCollection.IndexOf(value); 
     } 

     /// <summary>Inserts an item into the collection at the specified index</summary> 
     /// <param name="index">The zero-based index location where the item is inserted</param> 
     /// <param name="item">An object representing the item to insert</param> 
     /// <exception cref="System.ArgumentNullException">The item was null</exception> 
     /// <exception cref="System.ArgumentOutOfRangeException">The index was less than zero.-or- The index was greater than the count of items in the collection</exception> 
     public void Insert(int index, ItemType item) 
     { 
      CheckItems(); 
      _objectCollection.Insert(index, item); 
     } 

     /// <summary>Removes the specified item from the System.Windows.Forms.ComboBox</summary> 
     /// <param name="value">The System.Object to remove from the list</param> 
     public bool Remove(ItemType value) 
     { 
      int kIndex = IndexOf(value); 
      if (kIndex >= 0) 
      { 
       CheckItems(); 
       _objectCollection.RemoveAt(kIndex); 
       return true; 
      } 
      return false; 
     } 

     /// <summary>Removes an item from the System.Windows.Forms.ComboBox at the specified index</summary> 
     /// <param name="index">The index of the item to remove</param> 
     /// <exception cref="System.ArgumentOutOfRangeException">The value parameter was less than zero.-or- The value parameter was greater than or equal to the count of items in the collection</exception> 
     public void RemoveAt(int index) 
     { 
      CheckItems(); 
      _objectCollection.RemoveAt(index); 
     } 

     #region IList Members 

     int IList.Add(object value) 
     { 
      return this.Add((ItemType)value); 
     } 

     void IList.Clear() 
     { 
      this.Clear(); 
     } 

     bool IList.Contains(object value) 
     { 
      return this.Contains((ItemType)value); 
     } 

     int IList.IndexOf(object value) 
     { 
      return this.IndexOf((ItemType)value); 
     } 

     void IList.Insert(int index, object value) 
     { 
      this.Insert(index, (ItemType)value); 
     } 

     bool IList.IsFixedSize 
     { 
      get 
      { 
       CheckItems(); 
       return (_objectCollection as IList).IsFixedSize; 
      } 
     } 

     bool IList.IsReadOnly 
     { 
      get { return this.IsReadOnly; } 
     } 

     void IList.Remove(object value) 
     { 
      this.Remove((ItemType)value); 
     } 

     void IList.RemoveAt(int index) 
     { 
      this.RemoveAt(index); 
     } 

     object IList.this[int index] 
     { 
      get 
      { 
       return this[index]; 
      } 
      set 
      { 
       this[index] = (ItemType)value; 
      } 
     } 

     #endregion 

     #region ICollection Members 

     void ICollection.CopyTo(Array array, int index) 
     { 
      this.CopyTo((object[])array, index); 
     } 

     int ICollection.Count 
     { 
      get { return this.Count; } 
     } 

     bool ICollection.IsSynchronized 
     { 
      get 
      { 
       CheckItems(); 
       return (_objectCollection as ICollection).IsSynchronized; 
      } 
     } 

     object ICollection.SyncRoot 
     { 
      get 
      { 
       CheckItems(); 
       return (_objectCollection as ICollection).SyncRoot; 
      } 
     } 

     #endregion 

     #region IEnumerable<ItemType> Members 

     IEnumerator<ItemType> IEnumerable<ItemType>.GetEnumerator() 
     { 
      CheckItems(); 
      return _objectCollection.Cast<ItemType>().GetEnumerator(); 
     } 

     #endregion 

     #region ICollection<ItemType> Members 

     void ICollection<ItemType>.Add(ItemType item) 
     { 
      this.Add(item); 
     } 

     void ICollection<ItemType>.Clear() 
     { 
      this.Clear(); 
     } 

     bool ICollection<ItemType>.Contains(ItemType item) 
     { 
      return this.Contains(item); 
     } 

     void ICollection<ItemType>.CopyTo(ItemType[] array, int arrayIndex) 
     { 
      throw new NotImplementedException(); 
     } 

     int ICollection<ItemType>.Count 
     { 
      get { return this.Count; } 
     } 

     bool ICollection<ItemType>.IsReadOnly 
     { 
      get { return this.IsReadOnly; } 
     } 

     bool ICollection<ItemType>.Remove(ItemType item) 
     { 
      return this.Remove(item); 
     } 

     #endregion 

     #region IEnumerable Members 

     IEnumerator IEnumerable.GetEnumerator() 
     { 
      return this.GetEnumerator(); 
     } 

     #endregion 
    } 

    /// <summary>Gets an object representing the collection of the items contained in this System.Windows.Forms.ComboBox</summary> 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
    [Browsable(false)] 
    [Bindable(true)] 
    public new TypedObjectCollectionProxy<T> Items 
    { 
     get { return _objectCollectionProxy; } 
    } 

    /// <summary>Gets or sets currently selected item in the System.Windows.Forms.ComboBox</summary> 
    [Bindable(true)] 
    [Browsable(false)] 
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
    public new T SelectedItem 
    { 
     get { return (T)base.SelectedItem; } 
     set { base.SelectedItem = value; } 
    } 
} 

這是我自己的抽象通用組合框。