Как прервать процесс изменения значения поля со списком? - PullRequest
1 голос
/ 22 июня 2011

Я пишу на C # с визуальным интерфейсом. Часть логики состоит из набора значений, изменяющихся в зависимости от того, какое из них (наборов) выбрано в поле со списком.

Изменения в наборах значений могут быть сохранены или нет. Необходимо предоставить пользователю возможность сохранять несохраненные изменения или отклонять их, когда он выбирает другой элемент (набор) в поле со списком. Крайне важно, чтобы при отображении поля сообщения с да / нет в поле со списком все еще отображалось старое значение, и только после этого, в зависимости от выбора пользователя, отображалось новое или старое.

Последовательность должна быть:

пользователь использует ключи или раскрывающийся список для выбора нового элемента -> событие запускается и форма останавливает всю его обработку -> мой код отменяет изменение или позволяет ему пройти -> (если не отменено) поле со списком перерисовывается новое значение.

N.B. Следующие события были опробованы и оказались неадекватными:

  • SelectedIndexChanged
  • SelectedValueChanged
  • SelectionChangeCommitted
  • Пользователи
  • DropDownClosed

Ответы [ 2 ]

1 голос
/ 23 июня 2011

Я нашел несколько приемлемое решение, хотя и не соответствующее непосредственно дословному вопросу задаваемого вопроса.

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

В конце я остановился на «косметическом» решении, идея которого заключалась в замене отображаемого текста в поле со списком на время принятия пользователем решения на предмет того, является ли или нетне отменять изменения.

Итак, в событие SelectedIndexChanged я поместил следующий код:

try
{
    if (MyDataSets.Current.HasChanges() && !MyDataSets.Current.Name.Equals(cbChosenDataSet.Value))
    {
        cbChosenDataSet.DropDownStyle = ComboBoxStyle.DropDown;
        cbChosenDataSet.Text = MyDataSets.Current.Name + ' ';
        Application.DoEvents();
    }
    else return;
    /*
     * UserChoseToCancel is set according to user's choice
     */
    if (UserChoseToCancel)
        cbChosenDataSet.Value = MyDataSets.Current.Name;
    else
        MyDataSets.SetCurrent(cbChosenDataSet.Value);
    /*
     * other things
     */
}
catch(Exception e) {/* handling */}
finally
{
    cbChosenDataSet.DropDownStyle = ComboBoxStyle.DropDownList;
}

Суть идеи такова: в стиле DropDown текст ComboBox 'может бытьизменилось по мере необходимости.Однако при установке одного из элементов в списке произойдет изменение выбора.Чтобы избежать этого без необходимости, к временному тексту добавляется пробел.

Если отмена не происходит, восстановление стиля в DropDownList заставляет текст изменить на фактическое выбранное значение (которое осталось прежним).

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

1 голос
/ 22 июня 2011

Я думаю, что это то, что вам нужно - каждый раз, когда значение изменяется, пользователю предлагается ОК / Отмена.Единственное ограничение - это то, что в выпадающем списке отображается новое значение, пока отображается окно сообщения и пока пользователь не нажмет кнопку ОтменаМожет быть, перехватив сообщения рисования, вы можете предотвратить это.

class MyCombo : ComboBox
    {
        // Keep track of the previous value
        int previousIndex = 0;

        // Determines whether the OnSelectedIndexChanged is ignored
        bool ignoreChangedEvent = false;

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ComboBox.SelectedIndexChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnSelectedIndexChanged(EventArgs e)
        {
            if (!ignoreChangedEvent)
            {
                // Prompt the user to see if they really want to change.
                if (MessageBox.Show("Change value?", Application.ProductName, MessageBoxButtons.OKCancel) == DialogResult.Cancel)
                {
                    ignoreChangedEvent = true;
                    base.SelectedIndex = previousIndex;
                }
                else
                {
                    previousIndex = base.SelectedIndex;
                }
            }
            else
            {
                ignoreChangedEvent = false;
            }

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