Как предотвратить/отменить изменение значения поля со списком в С#?

У меня есть поле со списком в верхней части формы, которое загружает редактируемые данные в поля ниже. Если пользователь внес изменения, но не сохранил их, и пытается выбрать другой вариант из списка, я хочу предупредить их и дать им возможность отменить или сохранить изменения.

Мне нужно событие «BeforeValueChange» с отменяемым аргументом события.

Любые советы о том, как выполнить?


person Community    schedule 24.11.2008    source источник


Ответы (8)


Сохраните SelectedIndex ComboBox, когда в поле, если он был введен впервые, а затем восстановите его значение, когда вам нужно отменить изменение.

cbx_Example.Enter += cbx_Example_Enter;
cbx_Example.SelectionChangeCommitted += cbx_Example_SelectionChangeCommitted;

...

private int prevExampleIndex = 0;
private void cbx_Example_Enter(object sender, EventArgs e)
{
    prevExampleIndex = cbx_Example.SelectedIndex;
}

private void cbx_Example_SelectionChangeCommitted(object sender, EventArgs e)
{
    // some custom flag to determine Edit mode
    if (mode == FormModes.EDIT) 
    {
        cbx_Example.SelectedIndex = prevExampleIndex;
    }
}
person Denis Biondic    schedule 02.09.2009
comment
Это идеальное решение вместо события SelectionChanging. Спасибо!! -- Мэтью - person Matthew M.; 03.12.2010
comment
Использование события Enter для сохранения последнего выбора не требуется. Просто сохраните значение lastSelectedIndex как переменную private перед выходом из обработчика событий SelectionChangeCommitted. После этого последующие записи в этот обработчик событий могут использовать lastSelectedIndex для установки ComboBox.SelectedIndex в предыдущую позицию. - person Jim Fell; 05.07.2016

Вот самое простое исправление: -

        bool isSelectionHandled = true;

        void CmbBx_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (isSelectionHandled)
            {
                MessageBoxResult result = MessageBox.Show("Do you wish to continue selection change?", this.Title, MessageBoxButton.YesNo, MessageBoxImage.Question);
                if (result == MessageBoxResult.No)
                {
                    ComboBox combo = (ComboBox)sender;
                    isSelectionHandled = false;
                    if (e.RemovedItems.Count > 0)
                        combo.SelectedItem = e.RemovedItems[0];
                    return;
                }
            }
            isSelectionHandled = true;
        }
person Kushal Waikar    schedule 20.04.2011
comment
Что это за событие SelectionChanged? Это из WinForm ComboBox. - person i486; 21.11.2017
comment
@ i486 Да, это так. - person raulmd13; 14.01.2021

Сохраните текущее значение события Enter. Реализуйте логику BeforeValueChange в событии ValueChanged до фактической логики ValueChanged. Если пользователь отменяет, установите сохраненное значение и не продолжайте в методе (return).

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

person Vincent Van Den Berghe    schedule 24.11.2008

В этом сценарии можно использовать событие Validating
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

person Aleris    schedule 24.11.2008
comment
Это происходит после того, как вы потеряете фокус, так что не получится. Мне нужно событие, которое происходит до того, как пользователь попытается изменить значение. - person ; 25.11.2008
comment
@RG - не могли бы вы просто вернуть фокус на поле со списком, или происходит какая-то обработка, когда он теряет фокус? - person Lucas Jones; 12.04.2009

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

person Daniel M    schedule 24.11.2008

Как насчет использования событий Validating/Validated?
Это хорошо работает, если вас устраивает событие, происходящее на LostFocus вместо Change.

В противном случае, как насчет

public void Combobox_ValueChanged(object sender, EventArgs e) {
    if (!AskUserIfHeIsSureHeWantsToChangeTheValue())
    {
        // Set previous value
        return;
    }

    // perform rest of onChange code
}
person configurator    schedule 24.11.2008

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

person Simon    schedule 24.11.2008

Вы не можете предотвратить это, но вы можете вернуть старое значение, если определенные требования не выполняются:

private SomeObject = selectedSomeObject=null;

private void cbxTemplates_SelectionChangeCommitted(object sender, EventArgs e)
{
  if (!(sender is ComboBox cb)) return;
  if (!(cb.SelectedItem is SomeObject tem)) return;
  if (MessageBox.Show("You sure?", "??.",
        MessageBoxButtons.OKCancel) != DialogResult.OK)
    cb.SelectedItem = selectedSomeObject;
  else
  {
    selectedSomeObject = tem;
  }
}
person Tates    schedule 16.07.2018