vb.netcomboboxselectedindexchanged

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.

To avoid accidentally deleting, I've added a confirm message on SelectedIndexChanged event.

This way, data are cancelled only after confirmation.

My problem is: How can I also avoid changing of selected item when not confirmed?

(I wish to mantain the previous selected index)

I noticed that I can't use e.cancel or e.handled

I also know that I could store actual value in a global variable and use it to restore previous value but I'm asking for a better solution (if it's possible).

EDIT
At the time, I'm storing the Index in a form level variable and I'm using a boolean to avoid executing the event twice. Below you can see my code:

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

EDIT 2
The following is my attempt using Plutonix code:

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

But the event is fired twice, called by the row:

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

Solution

  • This should do most of what you want. It subclasses ComboBox to add a new event which fires before the SelectedIndexChanged event. If you cancel, then that event does not fire.

    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
    

    It just internalizes the logic you probably already have, but if there are more than one "cancel-able" controls on the form, you wont have to have multiple index tracking variables. Maybe that is simpler.

    Usage:

    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
    

    Since the Items collection can be modified, a simple LastIndex variable may not be enough - it could refer to the wrong item after something is added or removed. This tracks the last object selected and tries to find it in the current list.

    It also works with a DataSource, but there are probably a number of other situations to be accounted for.