web-dev-qa-db-fra.com

L'événement ComboBox- SelectionChanged a l'ancienne valeur, pas la nouvelle

C #, .NET 4.0, VS2010.

Nouveau sur WPF. J'ai une ComboBox sur ma MainWindow. J'ai accroché l'événement SelectionChanged de la liste déroulante. Cependant, si j'examine la valeur de la liste déroulante dans le gestionnaire d'événements, celle-ci a l'ancienne valeur. Cela ressemble plus à un événement "SelectionChanging" qu'à un événement SelectionChanged. 

Comment puis-je obtenir la nouvelle valeur de la ComboBox une fois la sélection effectuée?

Actuellement:

this.MyComboBox.SelectionChanged += new SelectionChangedEventHandler(OnMyComboBoxChanged);

...
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string text = this.MyComboBox.Text;
}

Notez que j'obtiens le même comportement si j'utilise l'objet passé dans les arguments d'événement, par exemple. e.OriginalSource.

77
Matt

Selon MSDN, e.AddedItems :

Obtient une liste contenant les éléments sélectionnés.

Pour que vous puissiez utiliser:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string text = (e.AddedItems[0] as ComboBoxItem).Content as string;
}

Vous pouvez également utiliser SelectedItem si vous utilisez string pour Items à partir de sender:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string text = (sender as ComboBox).SelectedItem as string;
}

ou

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string;
}

Content et SelectedItem étant des objets, une approche plus sûre consisterait à utiliser .ToString() au lieu de as string

94
SwDevMan81

Utilisez l'événement DropDownClosed au lieu de selectionChanged si vous voulez la valeur actuelle de la liste déroulante.

private void comboBox_DropDownClosed(object sender, EventArgs e)
{
   MessageBox.Show(comboBox.Text) 
}

Est-ce vraiment si simple?.

44
hidden

La valeur correcte à vérifier ici est la propriété SelectedItem

Une ComboBox est un contrôle composite composé de deux parties:

  1. La partie texte: la valeur dans cette partie correspond à la propriété Texte de la ComboBox.
  2. La partie sélecteur (c'est-à-dire la partie "déroulante"): l'élément sélectionné dans cette partie correspond à la propriété SelectedItem.

 Expanded ComboBox Parts

L’image ci-dessus a été prise immédiatement après l’extension de la ComboBox (c’est-à-dire avant la sélection d’une nouvelle valeur). À ce stade, Text _ et SelectedItem_ sont «Info», en supposant que les éléments ComboBox étaient des chaînes. Si les éléments ComboBox étaient à la place toutes les valeurs d'un Enum appelé "LogLevel", SelectedItem serait actuellement LogLevel.Info.

Lorsque l'utilisateur clique sur un élément du menu déroulant, la valeur de SelectedItem est modifiée et l'événement SelectionChanged est déclenché. La propriété Texte n'est pas encore mise à jour, car la Partie de texte n'est mise à jour qu'après la fin du gestionnaire SelectionChanged. Ceci peut être observé en mettant un point d'arrêt dans le gestionnaire et en regardant le contrôle:

 ComboBox at breakpoint in SelectionChanged handler

La partie de texte n'ayant pas encore été mise à jour, la propriété texte renvoie la valeur précédemment sélectionnée.

44
Dave Kidder

Cela a fonctionné pour moi:

private void AppName_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
   ComboBoxItem cbi = (ComboBoxItem)AppName.SelectedItem;
   string selectedText = cbi.Content.ToString();
}
10
Ramon

Cela a fonctionné pour moi:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    var text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string;            
}

L'événement suivant est déclenché pour toute modification du texte dans la zone de liste déroulante (lorsque l'index sélectionné est modifié et lorsque le texte est également modifié).

<ComboBox IsEditable="True" TextBoxBase.TextChanged="cbx_TextChanged" />
2
Petr Voborník

La deuxième option ne fonctionnait pas pour moi car l'élément .Text était hors de portée (C # 4.0 VS2008). C'était ma solution ...

string test = null;
foreach (ComboBoxItem item in e.AddedItems)
{
   test = item.Content.ToString();
   break;
}
1
Josh
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
}
1
Buratino

Si vous avez vraiment besoin de l'événement SelectionChanged, la meilleure réponse est la réponse de SwDevMan81. Toutefois, si vous débutez avec WPF, vous voudrez peut-être apprendre à faire les choses de la même manière que WPF, qui diffère des anciens jours Windows Forms qui reposaient sur des événements tels que SelectionChanged, avec WPF et le modèle View View Model View. devrait utiliser des liaisons. Voici un exemple de code:

// In the Views folder: /Views/MyWindow.xaml:
// ...
<ComboBox ItemsSource="{Binding MyViewModel.MyProperties, RelativeSource={RelativeSource AncestorType=Window}}"
         SelectedItem="{Binding MyViewModel.MyProperty  , RelativeSource={RelativeSource AncestorType=Window}}" />
// ...



// In the Views folder: /Views/MyWindow.xaml.cs:
public partial class MyWindow : Window
{
    public  MyViewModelClass MyViewModel {
        get { return _viewModel; }
        private set { _viewModel = value;}
    }

    public MyWindow()
    {
        MyViewModel.PropertyChanged += MyViewModel_PropertyChanged;

    }

    void MyViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "MyProperty")
        {
            // Do Work
            // Put your logic here!
        }
    }
}

using System.ComponentModel;

// In your ViewModel folder: /ViewModels/MyViewModelClass.cs:
public class MyViewModelClass : INotifyPropertyChanged
{
    // INotifyPropertyChanged implementation:
    private void NotifyPropertyChanged(string propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
    public event PropertyChangedEventHandler PropertyChanged;

    // Selected option:
    private string _myProperty;
    public  string  MyProperty {
        get { return _myProperty; }
        set { _myProperty = value; NotifyPropertyChanged("MyProperty"); }
    }

    // Available options:
    private List<string> _myProperties;
    public  List<string>  MyProperties {
        get { return _myProperties; }
        set { _myProperties = value; NotifyPropertyChanged("MyProperties"); }
    }

}
0
Lazaro

Il est étrange que SelectedItem contienne les données fraîches, alors que SelectedValue ne le fait pas. Cela ressemble à un bug pour moi. Si vos éléments de la liste déroulante sont des objets autres que ComboBoxItems, vous aurez besoin de quelque chose comme ceci: (ma ComboBox contient KeyValuePairs)

var selectedItem = (KeyValuePair<string, string>?)(sender as ComboBox).SelectedItem;
if (!selectedItem.HasValue)
    return;

string selectedValue = selectedItem.Value.Value;  // first .Value gets ref to KVPair

ComboBox.SelectedItem peut être null, alors que Visual Studio n'arrête pas de me dire qu'une KeyValuePair ne peut pas être nulle. C'est pourquoi j'ai converti la SelectedItem en un KeyValuePair<string, string>? nullable. Ensuite, je vérifie si selectedItem a une valeur autre que null. Cette approche devrait être applicable à tout type d’élément choisi.

0
sorrymissjackson
private void indBoxProject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    int NewProjID = (e.AddedItems[0] as kProject).ProjectID;
    this.MyProject = new kProject(NewProjID);
    LoadWorkPhase();
}

L'utilisation de e.AddedItems[0] as kProject, où kProject est une classe qui contient les données, a fonctionné pour moi car elle correspondait par défaut à RemovedItems [0] avant que je fasse cette distinction explicite. Merci SwDevMan81 pour les informations initiales qui ont répondu à cette question pour moi.

0
kyjote

J'avais besoin de résoudre cela en VB.NET. Voici ce que j'ai qui semble fonctionner:

Private Sub ComboBox1_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles ComboBox_AllSites.SelectionChanged
   Dim cr As System.Windows.Controls.ComboBoxItem = ComboBox1.SelectedValue
   Dim currentText = cr.Content
   MessageBox.Show(currentText)
End Sub
0
zzMzz

Ne compliquez pas les choses sans raison. En utilisant la propriété SelectedValue, vous pouvez facilement obtenir une valeur ComboBox sélectionnée, telle que: YourComboBoxName.SelectedValue.ToString ().

Derrière la scène, la propriété SelectedValue est définie comme suit: SelectedValue {get; set;} cela signifie que vous pouvez l'utiliser pour obtenir ou définir la valeur d'un ComboBox.

Utiliser SelectedItem n'est pas un moyen efficace d'obtenir une valeur ComboBox car cela nécessite beaucoup de ramifications.

0
Sam Tomashi