Как я могу обработать изменение выбранного индекса ComboBox? - PullRequest
3 голосов
/ 23 апреля 2009

У меня есть ComboBox, в котором есть список производителей. Когда пользователь выбирает производителя, приведенная ниже сетка заполняется данными для выбранного производителя. Эти данные могут быть изменены. Пользователь должен нажать кнопку Сохранить после всех изменений.

Но пользователь может забыть нажать «Сохранить» и выбрать другого производителя в поле со списком, и сетка будет заполнена другими данными, поэтому предыдущие изменения будут потеряны.

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

Как я могу это сделать? Или, может быть, вы предлагаете другой способ решения моей задачи (глядя под другим углом)?

Ответы [ 10 ]

9 голосов
/ 26 апреля 2009

Вот как мы можем создать подкласс ComboBox для введения нового SelectedIndexChangingEvent с возможностью отменить изменение:

    public class ComboBoxEx : ComboBox
{
    public event CancelEventHandler SelectedIndexChanging;

    [Browsable(false)]
    public int LastAcceptedSelectedIndex { get; private set; }

    public ComboBoxEx()
    {
        LastAcceptedSelectedIndex = -1;
    }

    protected void OnSelectedIndexChanging(CancelEventArgs e)
    {
        var selectedIndexChanging = SelectedIndexChanging;
        if (selectedIndexChanging != null)
            selectedIndexChanging(this, e);
    }


    protected override void OnSelectedIndexChanged(EventArgs e)
    {
        if (LastAcceptedSelectedIndex != SelectedIndex)
        {
            var cancelEventArgs = new CancelEventArgs();
            OnSelectedIndexChanging(cancelEventArgs);

            if (!cancelEventArgs.Cancel)
            {
                LastAcceptedSelectedIndex = SelectedIndex;
                base.OnSelectedIndexChanged(e);
            }
            else
                SelectedIndex = LastAcceptedSelectedIndex;
        }
    }

}
4 голосов
/ 23 октября 2012

Создание 2 переменных уровня класса

private bool selectionCancelled=false;
private int lastSelectedIndex=-1;

Затем в событии SelectedIndex вы можете написать код следующим образом

        if (!selectionCancelled)
        {
            if (MessageBox.Show("Are you sure you want to change the selection ?", this.Text, MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
            {
                selectionCancelled = true;
                comboBox.SelectedIndex = lastSelectedIndex;
                return;
            }

            lastSelectedIndex = comboBox.SelectedIndex;
            // Normal code of the event handler

        }
        else
        {

            selectionCancelled = false;
        }
3 голосов
/ 23 апреля 2009

Вы должны обработать событие ComboBox.SelectedIndexChanged. Что-то вроде:

this.ComboBox1.SelectedIndexChanged += new system.EventHandler(ComboBox1_SelectedIndexChanged);

Тогда ComboBox1_SelectedIndexChanged() будет вызываться при каждом изменении, и вы можете обновить информацию о производителе в этой функции. Сохраните старую информацию перед заполнением новой информации. Или попросите пользователя, если он действительно хочет изменить его, перед сохранением.

1 голос
/ 23 октября 2014

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

Решение представляет собой комбинацию сообщений @ AftabAhmedKalhoro и @ jeffamaphone, но вместо этого используется свойство Tag.

Я не хотел создавать подкласс ComboBox или иметь какие-либо дополнительные закрытые переменные, плавающие в форме. Но некоторым может не понравиться свойство Tag, потому что оно отчасти скрыто, если вы не используете его (что-то вроде остатка от VB6).

Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    ComboBox1.Items.Add("Item1")
    ComboBox1.Items.Add("Item2")
    ComboBox1.Items.Add("Item3")
    ComboBox1.Items.Add("Item4")
    ' Load Value from database or whatever and set the value or index.
    ComboBox1.SelectedIndex = 0
    ComboBox1.Tag = ComboBox1.SelectedIndex

    ' I add the handler at the end because I don't want it to fire during loading the form.
    AddHandler ComboBox1.SelectedIndexChanged, New EventHandler(AddressOf ComboBox1_SelectedIndexChanged)
End Sub

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    If (ComboBox1.Tag <> ComboBox1.SelectedIndex) Then
        If MessageBox.Show("Warning! You are changing the index." & vbCrLf & _
                           "Do you wish to continue?", _
                           "Changing Index", _
                           MessageBoxButtons.YesNo, _
                           MessageBoxIcon.Warning) = Windows.Forms.DialogResult.Yes Then
            ComboBox1.Tag = ComboBox1.SelectedIndex
            ' Do Something.
        Else
            ComboBox1.SelectedIndex = ComboBox1.Tag
        End If
    End If
End Sub

Обратите внимание, что сброс SelectedIndex приведет к повторному запуску события в этой строке:

ComboBox1.SelectedIndex = ComboBox1.Tag
1 голос
/ 16 января 2014

Простой способ отслеживать несохраненные изменения.

После загрузки любых исходных значений отключите кнопку «Сохранить».

Когда пользователь пытается выйти, проверьте, включена ли кнопка «Сохранить».

Включите или отключите кнопку «Сохранить», как требуется.

1 голос
/ 27 ноября 2011

Решение Night Coder элегантно и лаконично. Я упаковал его в DLL.
(Я называю это CustomControls.) Для этого создайте новую библиотеку классов и добавьте первые несколько операторов в решение Night Coder (скопировано здесь для удобства).

После того, как вы скомпилировали код, вы можете добавить его в качестве справочного материала. Я фактически загрузил DLL в мою панель инструментов Visual Studio. Таким образом, я могу перетащить элемент управления на мою форму во время разработки. Удобно, что новое событие отображается в списке свойств.

use System.ComponentModel;

use System.Windows.Forms; //this will need to be added as a reference

//your namespace will name your dll call it what you will

namespace CustomControls

Решение Night Coder следующее:

public class ComboBoxEx : ComboBox
{
        public event CancelEventHandler SelectedIndexChanging;


    [Browsable(false)]
    public int LastAcceptedSelectedIndex { get; private set; }

    public ComboBoxEx()
    {
            LastAcceptedSelectedIndex = -1;
    }

    protected void OnSelectedIndexChanging(CancelEventArgs e)
    {
            var selectedIndexChanging = SelectedIndexChanging;
            if (selectedIndexChanging != null)
                    selectedIndexChanging(this, e);
    }


    protected override void OnSelectedIndexChanged(EventArgs e)
    {
            if (LastAcceptedSelectedIndex != SelectedIndex)
            {
                    var cancelEventArgs = new CancelEventArgs();
                    OnSelectedIndexChanging(cancelEventArgs);

                    if (!cancelEventArgs.Cancel)
                    {
                            LastAcceptedSelectedIndex = SelectedIndex;
                            base.OnSelectedIndexChanged(e);
                    }
                    else
                            SelectedIndex = LastAcceptedSelectedIndex;
            }
    }
}
0 голосов
/ 02 июня 2009

Отличная работа ночного кодера. Ваш код работает отлично.

Спасибо!

Для разработчиков, которые пишут в VB.NET здесь у вас есть перевод:

Imports System.ComponentModel

Public Class ComboBoxEx
  Inherits ComboBox

  Private pLastAcceptedSelectedIndex As Integer

  Public Event SelectedIndexChanging As CancelEventHandler

  Public Property LastAcceptedSelectedIndex() As Integer
    Get
      Return pLastAcceptedSelectedIndex
    End Get
    Set(ByVal value As Integer)
      pLastAcceptedSelectedIndex = value
    End Set
  End Property

  Public Sub New()
    LastAcceptedSelectedIndex = -1
  End Sub

  Protected Sub OnSelectedIndexChanging(ByVal e As CancelEventArgs)
    RaiseEvent SelectedIndexChanging(Me, e)
  End Sub

  Protected Overrides Sub OnSelectedIndexChanged(ByVal e As System.EventArgs)
    If LastAcceptedSelectedIndex <> SelectedIndex Then
      Dim cancelEventArgs As CancelEventArgs

      cancelEventArgs = New CancelEventArgs()
      OnSelectedIndexChanging(cancelEventArgs)

      If Not cancelEventArgs.Cancel Then
        LastAcceptedSelectedIndex = SelectedIndex
        MyBase.OnSelectedIndexChanged(e)
      Else
        SelectedIndex = LastAcceptedSelectedIndex
      End If
    End If
  End Sub
End Class
0 голосов
/ 23 апреля 2009

Лучше всего здесь сравнить данные, введенные в ComboBox (аналогично другим полям), с уже сохраненными (в любом месте - DataSet, объектом списка и т. Д.) И проверить на наличие различий. Таким образом, если пользователь выбирает другой элемент в ComboBox, но затем меняет его обратно на исходный, программа распознает, что данные все еще не были изменены. (Например, обработка события SelectionChangeCommited и установка логического значения на true не позволят это обнаружить, и, кроме того, будет немного сложнее реализовать.) В этой ситуации кажется, что самый простой и элегантный подход обеспечивает наилучшую функциональность.

0 голосов
/ 23 апреля 2009

Если вам интересно, как вы можете получать уведомления при изменении выбора, вы можете подписаться на событие ComboBox.SelectedIndexChanged.

Если вы хотите предложить пользователю возможность сохранения, только если что-то изменилось и она забыла, поэтому сохраните свои изменения, вам нужно отслеживать, когда эти другие поля изменяются. Этого можно достичь, поддерживая логическое значение, которое устанавливается равным true, когда пользователь редактирует какие-либо поля. Когда упомянутое событие происходит, проверьте это значение, прежде чем решать, предлагать ли вариант сохранения.

0 голосов
/ 23 апреля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...