Das ComboBox-SelectionChanged-Ereignis hat einen alten Wert, keinen neuen Wert


89

C #, .NET 4.0, VS2010.

Neu bei WPF. Ich habe eine ComboBox in meinem MainWindow. Ich habe das SelectionChanged-Ereignis dieses Kombinationsfelds verknüpft. Wenn ich jedoch den Wert des Kombinationsfelds im Ereignishandler untersuche, hat es den alten Wert. Dies klingt eher nach einem "SelectionChanging" -Ereignis als nach einem SelectionChanged-Ereignis.

Wie erhalte ich den neuen Wert der ComboBox, nachdem die Auswahl tatsächlich erfolgt ist?

Zur Zeit:

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

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

Beachten Sie, dass ich das gleiche Verhalten erhalte, wenn ich das Objekt verwende, das in den Ereignisargumenten egeOriginalSource übergeben wird.


2
Ich bin gerade über das gleiche Problem gestolpert - danke! Ist das eigentlich ein Fehler, und er hätte eigentlich benannt werden sollen SelectionChanging?
Jan

Antworten:


109

Laut MSDN e.AddedItems:

Ruft eine Liste ab, die die ausgewählten Elemente enthält.

Sie könnten also verwenden:

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

Sie können auch verwenden , SelectedItemwenn Sie verwenden stringWerte für die Itemsvon der sender:

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

oder

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

Da beide Contentund SelectedItemsind Objekte, wäre ein sicherer Ansatz zu verwenden , .ToString()stattas string


11
interessant ... es hat den neuen Wert. Und RemovedItems hat das alte. Dieser Ereignisname ist ein bisschen falsch, zumindest meiner Meinung nach. Wenn ich SelectionChanged sehe, erwarte ich, dass sich der Status des Objekts geändert hat. Ich kann sehen, wie dies uns etwas mehr Informationen gibt.
Matt

1
Ja, ich denke, es liegt daran, dass die Änderung stattgefunden hat, aber nicht begangen wurde? Das ist nur eine Vermutung. Möglicherweise können Sie den Text des ausgewählten Elements abrufen, siehe meine Bearbeitung.
SwDevMan81

3
ComboBox.SelectedItemhat keine Eigenschaft namens Text, aber Sie können tun ComboBox.SelectedItem as string(obwohl dies möglicherweise nur funktioniert, wenn Sie stringfür die Items- nichts anderes getestet)
musefan

Nur Zeichenfolge text = (Zeichenfolge) e.AddedItems [0];
Igor Semin

Komplizieren Sie die Dinge nicht ohne Grund. Mit der SelectedValue-Eigenschaft können Sie auf einfache Weise einen ausgewählten ComboBox-Wert wie folgt abrufen: YourComboBoxName.SelectedValue.ToString (). Hinter den Kulissen ist die SelectedValue-Eigenschaft wie folgt definiert: SelectedValue {get; set;} Dies bedeutet, dass Sie damit den Wert einer ComboBox abrufen oder festlegen können. Die Verwendung von SelectedItem ist kein effizienter Weg, um einen ComboBox-Wert zu erhalten, da viele Konsequenzen erforderlich sind.
Sam Tomashi

59

Der richtige Wert, der hier überprüft werden muss, ist die SelectedItem- Eigenschaft.

Eine ComboBox ist ein zusammengesetztes Steuerelement, dessen zwei Teile sind:

  1. Der Textteil : Der Wert in diesem Teil entspricht der Text- Eigenschaft der ComboBox.
  2. Der Auswahlteil (dh der "Dropdown" -Teil): Das ausgewählte Element in diesem Teil entspricht der SelectedItem- Eigenschaft.

Erweiterte ComboBox-Teile

Das obige Bild wurde unmittelbar nach dem Erweitern der ComboBox (dh vor der Auswahl eines neuen Werts) aufgenommen. Zu diesem Zeitpunkt sind sowohl Text als auch SelectedItem "Info", vorausgesetzt, die ComboBox-Elemente waren Zeichenfolgen. Wenn die ComboBox-Elemente stattdessen alle Werte einer Aufzählung mit dem Namen "LogLevel" wären , wäre SelectedItem derzeit LogLevel.Info .

Wenn Sie auf ein Element in der Dropdown-Liste klicken, wird der Wert von SelectedItem geändert und das SelectionChanged- Ereignis ausgelöst. Der Text Eigenschaft ist noch nicht aktualisiert, obwohl, wie der Text Teil aktualisiert wird erst nach dem Selectionhandler beendet ist. Dies kann beobachtet werden, indem ein Haltepunkt in den Handler gesetzt und die Steuerung betrachtet wird:

ComboBox am Haltepunkt im SelectionChanged-Handler

Da der Text Teil nicht an dieser Stelle aktualisiert hat, der Text gibt Eigenschaft den zuvor ausgewählten Wert.


2
Vollständige Erweiterung und es half zu erkennen, dass sich meine Bindung in der Text-Eigenschaft anstelle des korrekten SelectedItem befand.
cmousset

1
@ DaveKidder Tolles Beispiel! +1
Ryan Wilson

46

Verwenden Sie das DropDownClosed-Ereignis anstelle von selectionChanged, wenn Sie den aktuellen Wert des Kombinationsfelds anzeigen möchten.

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

Ist wirklich so einfach.


10
@jvelez Ich denke, es wird nicht ausgelöst, wenn eine Tastatur verwendet wird.
NoviceProgrammer

das ist Scheiße. NoviceProgrammer, der wusste ...!
versteckt

10

Das hat bei mir funktioniert:

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

Irgendwie wird nur SelectedItem mit dem neuen Element gefüllt, nicht SelectedValue.
Mauris

7

Das hat bei mir funktioniert:

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

Dies ist sehr wichtig. Die akzeptierte Antwort zeigt nicht explizit, dass sie senderdie richtige enthält SelectedItem.
Jess

3

Das folgende Ereignis wird für jede Änderung des Texts in der ComboBox ausgelöst (wenn der ausgewählte Index geändert wird und wenn der Text auch durch Bearbeiten geändert wird).

<ComboBox IsEditable="True" TextBoxBase.TextChanged="cbx_TextChanged" />

1
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
}

4
Bitte geben Sie keine Nur-Code-Antworten an. Bitte erläutern Sie, warum Ihre Lösung die Antwort ist.
Lee Taylor

1

Die zweite Option hat bei mir nicht funktioniert, da das .Text-Element außerhalb des Gültigkeitsbereichs lag (C # 4.0 VS2008). Das war meine Lösung ...

string test = null;
foreach (ComboBoxItem item in e.AddedItems)
{
   test = item.Content.ToString();
   break;
}

0

Ich musste dies in VB.NET lösen. Folgendes scheint zu funktionieren:

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

Es ist seltsam, dass SelectedItem die frischen Daten enthält, SelectedValue jedoch nicht. Klingt für mich nach einem Fehler. Wenn Ihre Elemente in der Combobox andere Objekte als ComboBoxItems sind, benötigen Sie Folgendes: (my ComboBoxenthält 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.SelectedItemkann null sein, während Visual Studio mir immer wieder sagt, dass a KeyValuePairnicht null sein kann. Deshalb habe ich das SelectedItemauf nullable gesetzt KeyValuePair<string, string>?. Dann überprüfe ich, ob selectedItemes einen anderen Wert als hat null. Dieser Ansatz sollte auf jeden Typ Ihres ausgewählten Elements anwendbar sein.


0

Wenn Sie das SelectionChangedEreignis wirklich brauchen , ist die beste Antwort die Antwort von SwDevMan81. Wenn Sie jedoch mit WPF beginnen, möchten Sie möglicherweise lernen, wie Sie Dinge auf WPF-Weise tun. Dies unterscheidet sich von den alten Windows Forms-Tagen, in denen Ereignisse wie SelectionChangedWPF und Model View ViewModel verwendet wurden Verwenden Sie Bindungen. Hier ist ein Codebeispiel:

// 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
private void indBoxProject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    int NewProjID = (e.AddedItems[0] as kProject).ProjectID;
    this.MyProject = new kProject(NewProjID);
    LoadWorkPhase();
}

Die Verwendung von e.AddedItems[0] as kProjectwhere kProject ist eine Klasse, die die für mich bearbeiteten Daten enthält, da standardmäßig RemovedItems [0] verwendet wurde, bevor ich diese explizite Unterscheidung getroffen habe. Vielen Dank an SwDevMan81 für die ersten Informationen, die diese Frage für mich beantwortet haben.


0

Komplizieren Sie die Dinge nicht ohne Grund. Mit der SelectedValue-Eigenschaft können Sie auf einfache Weise einen ausgewählten ComboBox-Wert wie folgt abrufen: YourComboBoxName.SelectedValue.ToString ().

Hinter den Kulissen ist die SelectedValue-Eigenschaft wie folgt definiert: SelectedValue {get; set;} Dies bedeutet, dass Sie damit den Wert einer ComboBox abrufen oder festlegen können.

Die Verwendung von SelectedItem ist kein effizienter Weg, um einen ComboBox-Wert zu erhalten, da viele Konsequenzen erforderlich sind.


0

Sie können die SelectedIndex- oder SelectedValue- oder SelectedItem-Eigenschaft im SelectionChanged-Ereignis des Combobox-Steuerelements überprüfen.


-2

Das sollte für Sie funktionieren ...

int myInt= ((data)(((object[])(e.AddedItems))[0])).kid;

2
Können Sie erklären, wie dies die Frage beantwortet?
Nathan Tuggy

-3

Ich habe dieses Problem mithilfe des DropDownClosed-Ereignisses gelöst, da es nach dem Ändern des Werts leicht ausgelöst wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.