vb.net отменить SelectedIndexChanged и повторно выбрать предыдущий элемент

У меня есть ComboBox и когда выбран другой элемент, некоторые данные должны быть удалены.

Чтобы избежать случайного удаления, я добавил подтверждающее сообщение на SelectedIndexChanged событие.

Таким образом, данные отменяются только после подтверждения.

Моя проблема: Как я могу также избежать изменения выбранного элемента, если он не подтвержден?

(Я хочу сохранить предыдущий выбранный индекс)

Я заметил, что я не могу использовать e.cancel или же e.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)

2 ответа

Решение

Это должно делать большую часть того, что вы хотите. Это подклассы 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

Он просто усваивает логику, которую вы, вероятно, уже используете, но если в форме имеется более одного "отменяемого" элемента управления, вам не нужно иметь несколько переменных отслеживания индекса. Может быть, это проще.

Использование:

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

Затем в событии DropDown ComboBox вы можете установить его равным тому, что в данный момент делает выбранный элемент.

selected = ComboBox.SelectedItem

Затем на вашем событии SelectedIndexChanged, когда вы не хотите, чтобы он изменился, вы можете просто вернуть выбранный элемент обратно.

ComboBox.SelectedItem = selected

Есть, вероятно, более чистые способы, но это было просто из головы.

Если вы не хотите хранить весь объект и только индекс, вы можете использовать.SelectedIndex и объявить переменную как Integer.

Теперь я пытаюсь избежать того, чтобы событие запускалось дважды: когда я отменяю, команда MyBase.SelectedIndex = MyBase.Items.IndexOf(selectedObject) запрашивает подтверждение дважды.

Для тех, кто сталкивается с этим сейчас, я добавил ошеломляющий фрагмент кода, который не дает ему сработать во второй раз. Я считаю, что это будет нормально работать с несколькими комбинированными списками, но это происходит так быстро, что все должно быть хорошо, если это не так, или если вы используете только один, как я.

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

Другие вопросы по тегам