如何隐藏自定义ComboBox中的Items属性

我正在创建一个inheritance自ComboBox的自定义控件。 将项添加到ComboBox时,我需要执行自定义操作。 它是C#还是Vb.NET并不重要,但我不知道该怎么做。

看起来不值得努力修改所有内容来检测它,如下所示:
用于检测添加到ComboBox的项目的事件

所以也许可以创建我的自定义.Add(); 方法,但后来我需要隐藏Items属性,所以控件不允许两种不同的添加方法,只有一种工作方式。

我试过在这个post中使用的东西,但我没有设法让它工作。 例如,我尝试将重载属性设置为private ,但没有更改任何内容,如Vb.NET中的此示例所示:

 Private Overloads ReadOnly Property Items() As ObjectCollection '... 

可以吗?

是的,不是。

是的,您可以隐藏原始的Items集合,并用其他东西替换它。

但是,您的新“自定义”商品将无法使用; 它总是空的 – 至少那是我发现的。 也许有人可以详细介绍为什么……?

这就是为什么我用一些相当无用的东西替换它 – 一个赤裸的物体。

可以做的是:你可以在中间人类中公开原始项目,并在你的自定义ComboBox类中使用它。 您可以例如命名公开的类Items_并创建一个类来替换最终inheritance级别中的Items。 此类需要实现您希望自定义类的使用者拥有的所有方法和属性。

我已经命名为自定义项目’项目’,并实现了一个方法和一个属性。 (对于不区分大小写的VB,也许Itemz会更好;-)

这是最小的中间人:

 [ToolboxItem(false)] public class mimComboBox : ComboBox { public ObjectCollection items_; public mimComboBox() { items_ = Items; } } 

这是一个自定义的ComboBox:

 public class myComboBox : mimComboBox { public myComboBox() { Items = new object(); // (1) items = new myItems(this); } new public object Items { get; set; } // this hides the real Items (2) public myItems items { get; set; } // this is the custom property public class myItems // the custom Items class with all necessary methods etc.. { public myItems( myComboBox parent ) { parentCB = parent; // reference to the outer class } private mimComboBox parentCB; // the man-in-the-middle // all your methods.. new public int Add(object o) // one example of a custom method { // add your item-added event here return parentCB.items_.Add(o); } // one of many many properties to provide.. public int Count { get { return parentCB.items_.Count; } } } } 

这是一个如何使用ComboBox的示例:

 private void button1_Click(object sender, EventArgs e) { myComboBox1.items.Add("uiuiuiiui"); // myComboBox1.Items.Add("sadsds"); // <== this doesn't compile! (3) button1.Text = myComboBox1.items.Count.ToString(); } 

这听起来像一些工作!

(也许中产阶级没有必要......?我想了解那个......!)

编辑:我根据Plutonix评论中的链接更改了一些细节。

笔记:

  • 如上所述,通过收听ComboBox系统消息可以更好地解决原始问题

  • 我仍然想知道为什么会这样:

当我替换(1)和(2)时

 Items = new myItems(this); new public myItems Items { get; set; } 

然后(3)编译就好了。 但是在运行时它会抛出一个空对象引用错误。

这是缺少的Overridable属性的迟来效果吗? @Jon Skeet来救援! 😉

MyComboBox充当普通的combobox(通过覆盖Item属性)和扩展事件(ItemAdded,ItemRemoved)

样品用法:

  MyComboBox1.Items.Add("0") MyComboBox1.Items.AddRange(New String() {"1", "2", "3", "55"}) MyComboBox1.Items.Remove("55") MyComboBox1.Items.RemoveAt(0) Debug.WriteLine(MyComboBox1.Items.IndexOf("2")) '2 Debug.WriteLine(MyComboBox1.Items.IndexOf("55")) '-1 MyComboBox1.Items.Clear() 

VB.NET代码:

 Public Class MyComboBox Inherits ComboBox Public Event ItemAdded As EventHandler 'Public Event ItemsAdded As EventHandler Public Event ItemRemoved As EventHandler 'Public Event ItemInserted(sender As Object, insertedIndex As Integer, e As EventArgs) Private ItemContainer_ As ItemContainer Sub New() ItemContainer_ = New ItemContainer(Me) AddHandler ItemContainer_.ItemAdded, AddressOf ItemContainer_ItemAdded 'AddHandler ItemContainer_.ItemsAdded, AddressOf ItemContainer_ItemsAdded AddHandler ItemContainer_.ItemRemoved, AddressOf ItemContainer_ItemRemoved 'AddHandler ItemContainer_.ItemInserted, AddressOf ItemContainer_ItemInserted End Sub Private Sub ItemContainer_ItemAdded(sender As Object, e As EventArgs) RaiseEvent ItemAdded(Me, e) End Sub 'Private Sub ItemContainer_ItemsAdded(sender As Object, e As EventArgs) ' RaiseEvent ItemsAdded(Me, e) 'End Sub Private Sub ItemContainer_ItemRemoved(sender As Object, e As EventArgs) RaiseEvent ItemRemoved(Me, e) End Sub 'Private Sub ItemContainer_ItemInserted(sender As Object, insertedIndex As Integer, e As EventArgs) ' RaiseEvent ItemInserted(Me, insertedIndex, e) 'End Sub Public Shadows ReadOnly Property Items As ItemContainer Get Return ItemContainer_ End Get End Property Public Shadows ReadOnly Property Items(index As Integer) As Object Get Return ItemContainer_.Item(index) End Get End Property Public Class ItemContainer Inherits System.Windows.Forms.ComboBox.ObjectCollection Public Event ItemAdded As EventHandler 'Public Event ItemsAdded As EventHandler Public Event ItemRemoved As EventHandler 'Public Event ItemInserted(sender As Object, insertedIndex As Integer, e As EventArgs) Private owner_ As ComboBox Sub New(owner As ComboBox) MyBase.New(owner) owner_ = owner End Sub Public Overloads Sub Add(item As Object) owner_.Items.Add(item) RaiseEvent ItemAdded(Me, New EventArgs) End Sub Public Overloads Sub AddRange(item() As Object) owner_.Items.AddRange(item) 'RaiseEvent ItemsAdded(Me, New EventArgs) RaiseEvent ItemAdded(Me, New EventArgs) End Sub Public Overloads Sub Insert(index As Integer, item As Object) owner_.Items.Insert(index, item) 'RaiseEvent ItemInserted(Me, index, New EventArgs) RaiseEvent ItemAdded(Me, New EventArgs) End Sub Public Overloads Sub Remove(item As Object) owner_.Items.Remove(item) RaiseEvent ItemRemoved(Me, New EventArgs) End Sub Public Overloads Sub RemoveAt(index As Integer) owner_.Items.RemoveAt(index) RaiseEvent ItemRemoved(Me, New EventArgs) End Sub Public Overloads Sub Clear() owner_.Items.Clear() RaiseEvent ItemRemoved(Me, New EventArgs) End Sub Public Overloads Function IndexOf(value As Object) As Integer Return owner_.Items.IndexOf(value) End Function Public Overloads Function Contains(value As Object) As Boolean Return owner_.Items.Contains(value) End Function Public Overloads Function GetHashCode() As Integer Return owner_.Items.GetHashCode End Function Public Overloads Function ToString() As String Return owner_.Items.ToString End Function Public Overloads Function GetEnumerator() As System.Collections.IEnumerator Return owner_.Items.GetEnumerator End Function Public Overloads Function Equals(obj As Object) As Boolean Return owner_.Items.Equals(obj) End Function Public Overloads Function Equals(objA As Object, objB As Object) As Boolean Return Object.Equals(objA, objB) End Function Public Overloads Sub CopyTo(Destination() As Object, arrayIndex As Integer) owner_.Items.CopyTo(Destination, arrayIndex) End Sub Public Overloads ReadOnly Property Count As Integer Get Return owner_.Items.Count End Get End Property Public Overloads ReadOnly Property IsReadOnly As Boolean Get Return owner_.Items.IsReadOnly End Get End Property Public Overloads ReadOnly Property Item(index As Integer) As Object Get Return owner_.Items.Item(index) End Get End Property End Class 

结束类

C#代码:

  using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; public class MyComboBox : System.Windows.Forms.ComboBox { public event EventHandler ItemAdded; //public event EventHandler ItemsAdded; public event EventHandler ItemRemoved; public event ItemInsertedEventHandler ItemInserted; public delegate void ItemInsertedEventHandler(object sender, int insertedIndex, EventArgs e); private ItemContainer ItemContainer_; public MyComboBox() { ItemContainer_ = new ItemContainer(this); ItemContainer_.ItemAdded += ItemContainer_ItemAdded; //ItemContainer_.ItemsAdded += ItemContainer_ItemsAdded; ItemContainer_.ItemRemoved += ItemContainer_ItemRemoved; ItemContainer_.ItemInserted += ItemContainer_ItemInserted; } private void ItemContainer_ItemAdded(object sender, EventArgs e) { if (ItemAdded != null) { ItemAdded(this, e); } } /*private void ItemContainer_ItemsAdded(object sender, EventArgs e) { if (ItemsAdded != null) { ItemsAdded(this, e); } }*/ private void ItemContainer_ItemRemoved(object sender, EventArgs e) { if (ItemRemoved != null) { ItemRemoved(this, e); } } private void ItemContainer_ItemInserted(object sender, int insertedIndex, EventArgs e) { if (ItemInserted != null) { ItemInserted(this, insertedIndex, e); } } public new ItemContainer Items { get { return ItemContainer_; } } public class ItemContainer : System.Windows.Forms.ComboBox.ObjectCollection { public event EventHandler ItemAdded; //public event EventHandler ItemsAdded; public event EventHandler ItemRemoved; public event ItemInsertedEventHandler ItemInserted; public delegate void ItemInsertedEventHandler(object sender, int insertedIndex, EventArgs e); private System.Windows.Forms.ComboBox owner_; public ItemContainer(System.Windows.Forms.ComboBox owner) : base(owner) { owner_ = owner; } public new void Add(object item) { owner_.Items.Add(item); if (ItemAdded != null) { ItemAdded(this, new EventArgs()); } } public new void AddRange(object[] item) { owner_.Items.AddRange(item); /*if (ItemsAdded != null) { ItemsAdded(this, new EventArgs()); }*/ if (ItemAdded != null) { ItemAdded(this, new EventArgs()); } } public new void Insert(int index, object item) { owner_.Items.Insert(index, item); if (ItemInserted != null) { ItemInserted(this, index, new EventArgs()); } } public new void Remove(object item) { owner_.Items.Remove(item); if (ItemRemoved != null) { ItemRemoved(this, new EventArgs()); } } public new void RemoveAt(int index) { owner_.Items.RemoveAt(index); if (ItemRemoved != null) { ItemRemoved(this, new EventArgs()); } } public new void Clear() { owner_.Items.Clear(); if (ItemRemoved != null) { ItemRemoved(this, new EventArgs()); } } public new int IndexOf(object value) { return owner_.Items.IndexOf(value); } public new bool Contains(object value) { return owner_.Items.Contains(value); } public new int GetHashCode() { return owner_.Items.GetHashCode(); } public new string ToString() { return owner_.Items.ToString(); } public new System.Collections.IEnumerator GetEnumerator() { return owner_.Items.GetEnumerator(); } public new bool Equals(object obj) { return owner_.Items.Equals(obj); } public new bool Equals(object objA, object objB) { return object.Equals(objA, objB); } public new void CopyTo(object[] Destination, int arrayIndex) { owner_.Items.CopyTo(Destination, arrayIndex); } public new int Count { get { return owner_.Items.Count; } } public new object this[int index] { get { return owner_.Items[index]; } } public new bool IsReadOnly { get { return owner_.Items.IsReadOnly; } } } }