【问题标题】:Event to detect item added to ComboBox检测添加到 ComboBox 的项目的事件
【发布时间】:2014-07-15 15:01:12
【问题描述】:

我正在创建一个继承自 ComboBox 的自定义控件。我需要检测何时将 Item 添加到 ComboBox 以执行我自己的检查。是 C# 还是 Vb.NET 没关系,但我不知道该怎么做。

我尝试了我在互联网上找到的所有东西,包括this thread,但答案中的链接处于离线状态,我不知道该怎么办。

例如vb.net中的这段代码:

Public Sub SomeFunc() Handles Items.CollectionChanged
    '....
End Sub

它说Items 属性未定义WithEvents

控件未使用 BindingSource。添加项目时,我需要控件来执行自定义操作。项目直接添加到 .Items 属性中:

customComboBox.Items.Add("item");

可以吗?

【问题讨论】:

  • 这是 WPF 还是 WinForms?你能显示一些代码吗?项目是如何添加到 ComboBox 中的?
  • @Savanna Winforms,已编辑
  • 在您提供的链接中,建议订阅 ComboBox 的 Items 集合上的 CollectionChanged 事件。你试过这个吗?请发布您的代码,以便我们了解您遇到的问题。
  • how can I do that 困难重重。我开始继承 LV Items 集合并放弃了。请记住,尤其是对于 CBO 和 LB,它们不仅仅是字符串,还可以是集合中的类对象,因此您需要承担很多工作。
  • 我正在寻找解决方案。使用反射我能够更改 ComboBox 的内部项目集合(私有字段 itemCollection),但 ComobBox.ObjectCollection 不允许您覆盖 Add 方法(尽管 this[index] 是虚拟的)。我想我已经准备好放弃了,但以防万一有人想走得更远然后this might be of interest。使用类似的方法,有人可能会覆盖集合的 Add 方法。

标签: c# .net vb.net winforms combobox


【解决方案1】:

我认为最好的方法是听原生 ComboBox messages:

不要被STRING这个词所迷惑,每当你添加、插入或删除一个项目时,它们都会被触发。所以当列表被清除时。

Public Class UIComboBox
    Inherits ComboBox

    Private Sub NotifyAdded(index As Integer)
    End Sub

    Private Sub NotifyCleared()
    End Sub

    Private Sub NotifyInserted(index As Integer)
    End Sub

    Private Sub NotifyRemoved(index As Integer)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        Select Case m.Msg
            Case CB_ADDSTRING
                MyBase.WndProc(m)
                Dim index As Integer = (Me.Items.Count - 1)
                Me.NotifyAdded(index)
                Exit Select
            Case CB_DELETESTRING
                MyBase.WndProc(m)
                Dim index As Integer = m.WParam.ToInt32()
                Me.NotifyRemoved(index)
                Exit Select
            Case CB_INSERTSTRING
                MyBase.WndProc(m)
                Dim index As Integer = m.WParam.ToInt32()
                Me.NotifyAdded(If((index > -1), index, (Me.Items.Count - 1)))
                Exit Select
            Case CB_RESETCONTENT
                MyBase.WndProc(m)
                Me.NotifyCleared()
                Exit Select
            Case Else
                MyBase.WndProc(m)
                Exit Select
        End Select
    End Sub

    Private Const CB_ADDSTRING As Integer = &H143
    Private Const CB_DELETESTRING As Integer = &H144
    Private Const CB_INSERTSTRING As Integer = 330
    Private Const CB_RESETCONTENT As Integer = &H14B

End Class

【讨论】:

  • 工作就像一个魅力,谢谢。我只是修改了删除Exit Select的方法,将MyBase.WndProc(m)放在开头和一些其他的小改动。
【解决方案2】:

如果您的ComboBoxBindingSource 支持,那么您可以侦听AddingItem 事件并进行相应处理。

【讨论】:

  • 遗憾的是,它没有使用 BindingSource。添加项目时,我需要控件来执行自定义操作。项目直接添加到control.Items 属性中。
【解决方案3】:

您可以控制何时将项目添加到 ComboBox。 因此,发生这种情况时不会触发任何事件。

您是向 ComboBox 添加项目的人。执行此操作的不是外部可执行文件,而是您的代码。因此,您可以确保所有添加都是通过函数 AddItem(item As Object) {...} 完成的,您应该处理在其中添加项目时需要执行的逻辑。所以,不需要事件。

【讨论】:

  • 没有投反对票,但你能解释一下You are in control of吗?
  • 抱歉简短的回答。我的意思是您是向 ComboBox 添加项目的人。执行此操作的不是外部可执行文件,而是您的代码。因此,您可以确保所有添加都是通过函数 AddItem(item As Object) {...} 完成的,您应该处理在其中添加项目时需要执行的逻辑。所以,不需要事件。
  • 我需要该事件,因为控件必须在添加项目时执行自定义操作。这必须在不期望最终程序员添加它的情况下完成,而是直接使用控件。
  • 两种解决方案: - 创建您自己的控件 API 以添加项目 CustomAdd,在此函数中,您应该调用普通的 ComboBox Add 函数 + 您想要事件的逻辑。 - 覆盖 ComboBox Add 方法。
  • 第二个选项的问题是你真的必须重写 Items.Add 方法,正如 SysDragon 在上面的 cmets 中提到的那样...... ComboBox 没有 Add 方法,它是 Combobox。项目。添加。
【解决方案4】:

我最近在同一个问题上苦苦挣扎,发现缺少文档和其他网络帖子。 Windows Forms ComboBox 的核心是两个控件合二为一。一个紧凑的 ListBox 和一个 TextBox。我想检测用户何时在 TextBox 中键入了未包含在 Items 集合中的新条目,以便可以处理新项目并可能将其添加到要选择的项目列表中。

控件没有定义直接覆盖这种情况的事件,并且 TextChanged 事件过于细化。

我在 Leave 事件处理程序中发现了以下逻辑,用于检测不在列表中的潜在新项目。

void cb_Leave(object sender, EventArgs e) {
    if (cb.SelectedIndex < 0 && string.IsNullOrEmpty(cb.Text)) {
        // The Text represents the potential new item provided by the user
        // Insert validation, value generation, etc. here
        // If the proposed text becomes a new item, add it to the list
        ListItemType newItem = new ListItemType(cb.Text);
        cb.Items.Add(newItem);

        // And don't forget to select the new item so that the
        // SelectedIndex and SelectedItem are updated to reflect the addition
        cb.SelectedItem = newItem;
    }

}

如果您只是使用字符串值作为列表项,那么上面的 newItem 就是 cb.Text。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-08
    • 2011-10-06
    • 1970-01-01
    相关资源
    最近更新 更多