web-dev-qa-db-fra.com

Comment empêcher/annuler un changement de valeur de liste déroulante dans c #?

J'ai une liste déroulante en haut d'un formulaire qui charge des données modifiables dans les champs ci-dessous. Si l'utilisateur a apporté des modifications, mais qu'il n'a pas été enregistré, et qu'il tente de sélectionner une option différente dans la liste déroulante, je souhaite les avertir et leur donner la possibilité d'annuler ou de sauvegarder.

J'ai besoin d'un événement "BeforeValueChange" avec un argument d'événement annulable.

Un conseil sur la façon d'accomplir?

22
rg01

Enregistrez le SelectedIndex de la ComboBox quand box si vous l'avez entré pour la première fois, puis restaurez sa valeur lorsque vous devez annuler la modification.

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;
    }
}
16
Denis Biondic

Voici le correctif le plus simple: -

        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;
        }
4
Kushal Waikar

Enregistrez la valeur actuelle sur l'événement Enter. Implémentez la logique BeforeValueChange dans l'événement ValueChanged, avant la logique ValueChanged réelle. Si l'utilisateur annule, définissez la valeur stockée et ne continuez pas dans la méthode (return).

Si vous comptez beaucoup utiliser ce système, je vous conseillerais d'hériter ComboBox et d'y implémenter votre événement BeforeValuechange.

3

L'événement de validation peut être utilisé pour ce scénario
http://msdn.Microsoft.com/en-us/library/system.windows.forms.control.validating.aspx

2
Aleris

Vous n'obtenez pas un événement approprié par défaut. Vous pouvez mettre en cache la valeur précédente et la redéfinir sur cette valeur si l'utilisateur souhaite annuler.

1
Daniel M

Qu'en est-il des événements Validation/Validé?
Cela fonctionne bien si l’événement qui se produit sur LostFocus au lieu de Change vous convient.

Sinon, que diriez-vous

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

    // perform rest of onChange code
}
1
configurator

Vous pouvez utiliser un message filter pour intercepter les clics et les appuis sur les touches, ce qui vous permettrait d’empêcher le comportement normal de la zone de liste déroulante. Mais je pense que vous feriez mieux de désactiver la zone de liste déroulante lorsque l'utilisateur apporte une modification et de lui demander de sauvegarder ou d'annuler ses modifications.

0
Simon

Vous ne pouvez pas vraiment l'empêcher, mais vous pouvez revenir à l'ancienne valeur si certaines conditions ne sont pas remplies:

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;
  }
}
0
Tates