vb.net 取消 SelectedIndexChanged 并重新选择上一项

vb.net cancel SelectedIndexChanged and reselect previous item

I have a ComboBox and when a different item is selected some data need to be deleted.

为避免意外删除,我在 SelectedIndexChanged 活动中添加了一条确认消息。

这样数据确认后才取消

我的问题是:如何在未确认时也避免更改所选项目?

(我希望保留之前选择的索引)

我注意到我无法使用 e.cancele.handled

我也知道我可以将实际值存储在全局变量中并使用它来恢复以前的值,但我要求更好的解决方案(如果可能的话)。

编辑
当时,我将索引存储在表单级变量中,并使用布尔值来避免两次执行事件。下面你可以看到我的代码:

Private Sub CBox_AmType_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CBox_AmType.SelectedIndexChanged
    If DontRunSelChange Then
        DontRunSelChange = False
        Exit Sub
    End If
    '...some code 
    Dim OkCanc As DialogResult = MessageBox.Show("Are you sure?", "Changing confirmation",
                                 MessageBoxButtons.OKCancel, MessageBoxIcon.Question)
        If OkCanc = vbCancel Then
            DontRunSelChange = True 'This to avoid running twice
            CBox_AmType.SelectedIndex = AmType_Index
            Exit Sub
        End If
    '...some code 
End sub

编辑 2
以下是我使用 Plutonix 代码的尝试:

Private Sub ComboBoxEx1_SelectedIndexChanging(sender As Object, e As SelectedIndexChangingEventArgs) Handles ComboBoxEx1.SelectedIndexChanging
    Dim SN As DialogResult = MessageBox.Show("Are you sure?", "Changing confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
    If SN = DialogResult.No Then
        e.Cancel = True
        Exit Sub
    End If
    Me.Lbl_Text.Text = Me.ComboBoxEx1.SelectedItem.ToString
End Sub

但是事件被触发了两次,由行调用:

MyBase.SelectedIndex = MyBase.Items.IndexOf(selectedObject)

这应该可以满足您的大部分需求。它对 ComboBox 进行子类化以添加一个在 SelectedIndexChanged 事件之前触发的新事件。如果您取消,则该事件不会触发。

Public Class SelectedIndexChangingEventArgs
    Inherits EventArgs

    Public Property Cancel As Boolean = False
    Public Property NewIndex As Int32 = -1

    Friend Sub New(index As Int32)
        NewIndex = index
    End Sub
End Class


Public Class ComboBoxEx
    Inherits ComboBox

    Private selectedObject As Object = Nothing

    Public Event SelectedIndexChanging(sender As Object, 
                            e As SelectedIndexChangingEventArgs)

    Public Sub New()
        MyBase.New()
    End Sub

    Protected Overrides Sub OnSelectedIndexChanged(e As EventArgs)
        Dim evArgs As New SelectedIndexChangingEventArgs(MyBase.SelectedIndex)
        RaiseEvent SelectedIndexChanging(Me, evArgs)

        If evArgs.Cancel Then
            If selectedObject IsNot Nothing Then
                MyBase.SelectedIndex = MyBase.Items.IndexOf(selectedObject)
            Else
                MyBase.SelectedIndex = -1
            End If
            Return       ' do not fire Changed event
        End If

        MyBase.OnSelectedIndexChanged(e)
        selectedObject = MyBase.Items(MyBase.SelectedIndex)
    End Sub
End Class

它只是内化了您可能已经拥有的逻辑,但如果表单上有多个 "cancel-able" 控件,则您不必拥有多个索引跟踪变量。也许这样更简单。

用法:

Private Sub ComboBoxEx1_SelectedIndexChanging(sender As Object,
          e As SelectedIndexChangingEventArgs) Handles ComboBoxEx1.SelectedIndexChanging
    If ComboBoxEx1.Items(e.NewIndex).ToString.Contains("o") Then
        e.Cancel = True
    End If
End Sub

由于可以修改 Items 集合,因此一个简单的 LastIndex 变量可能不够用 - 它可能会在添加或删除某些内容后引用错误的项目。这会跟踪最后选择的对象并尝试在当前列表中找到它。

它也适用于 DataSource,但可能还有许多其他情况需要考虑。

您可以将当前选择的项目存储在全局变量中,例如

Dim selected As Object

然后在 ComboBox 的 DropDown 事件上,您可以将其设置为等于当前选中的项目。

selected = ComboBox.SelectedItem

然后在您不想更改 SelectedIndexChanged 事件时,您可以简单地将所选项目设置回来。

ComboBox.SelectedItem = selected

可能还有更简洁的方法,但这只是我的想法。

如果您不想存储整个对象而只存储索引,您可以使用 .SelectedIndex 并将变量声明为 Integer。

Now I'm trying to avoid that the event is run twice: when I cancel, the command MyBase.SelectedIndex = MyBase.Items.IndexOf(selectedObject) makes the confirmation is asked twice.

对于那些现在遇到这个问题的人,我添加了一段麻木的代码来阻止它第二次触发。我相信这对多个组合框会很好地工作,但它发生得太快了,如果没有,或者如果你只使用像我这样的组合框,它应该没问题。

Public Class SelectedIndexChangingEventArgs
    Inherits EventArgs

    Public Property Cancel As Boolean = False
    Public Property NewIndex As Int32 = -1

    Friend Sub New(index As Int32)
        NewIndex = index
    End Sub
End Class


Public Class ComboBoxEx

    Inherits ComboBox

    Private selectedObject As Object = Nothing

    Private Property Numb As Boolean = False

    Public Event SelectedIndexChanging(sender As Object,
                                e As SelectedIndexChangingEventArgs)

    Public Sub New()
        MyBase.New()
    End Sub

    Protected Overrides Sub OnSelectedIndexChanged(e As EventArgs)
        Dim evArgs As New SelectedIndexChangingEventArgs(MyBase.SelectedIndex)

        If Numb = False Then

            RaiseEvent SelectedIndexChanging(Me, evArgs)

        Else

            Numb = False

        End If

        If evArgs.Cancel Then
            If selectedObject IsNot Nothing Then

                Numb = True

                MyBase.SelectedIndex = MyBase.Items.IndexOf(selectedObject)
            Else
                MyBase.SelectedIndex = -1
            End If
            Return       ' do not fire Changed event
        End If

        MyBase.OnSelectedIndexChanged(e)
        selectedObject = MyBase.Items(MyBase.SelectedIndex)
    End Sub
End Class

以防对任何人有用:P