2010-06-02 4 views
70

C#, .NET 4.0, VS2010.ComboBox - SelectionChanged-Ereignis hat alten Wert, kein neuer Wert

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

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

Derzeit:

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

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

Hinweis, erhalte ich das gleiche Verhalten, wenn ich das Objekt die Nutzung im Falle args übergeben wird, z.B. e.OriginalQuelle.

+2

Ich bin gerade über das gleiche Problem gestolpert - danke! Ist das eigentlich ein Bug, und er sollte eigentlich "SelectionChanging" * heißen? – Jan

Antwort

83

Laut MSDN, e.AddedItems:

Ruft eine Liste, die die Elemente enthält, die ausgewählt wurden.

Sie könnten also verwenden:

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

Sie auch SelectedItem verwenden können, wenn Sie string Werte für die Items vom sender verwenden:

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 sowohl Content und SelectedItem sind Objekte, ein sicherer Ansatz .ToString() statt as string

+10

interessant ... es hat den neuen Wert. Und RemovedItems hat das Alte. Dieser Ereignisname ist ein bisschen falsch, zumindest IMHO. Wenn ich SelectionChanged sehe, erwarte ich, dass sich der Zustand des Objekts geändert hat. Ich kann sehen, dass dies uns etwas mehr Informationen gibt. – Matt

+0

Ja, ich denke es ist, weil die Änderung aufgetreten ist, aber nicht begangen wurde? Das ist nur eine Vermutung. Sie können möglicherweise den Text des ausgewählten Elements abrufen, siehe meine Bearbeitung. – SwDevMan81

+0

Beide arbeiten, danke !! – Matt

1

Die zweite Option wäre die Verwendung nicht für mich arbeiten, weil das .Text Element außerhalb des Gültigkeitsbereichs (C# 4.0 VS2008) war. Dies war meine Lösung ...

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

Das ist für mich gearbeitet:

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

irgendwie nur SelectedItem wird mit dem neuen Element, nicht SelectedValue aufgefüllt. – mauris

0

Ich brauchte dies in VB.NET zu lösen. Hier ist, was ich habe, das 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
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) 
{ 
    string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString(); 
} 
+3

Bitte geben Sie keine reinen Code-Antworten an. Bitte geben Sie eine Erklärung, warum Ihre Lösung die Antwort ist. –

40

Verwenden Sie das DropDownClosed Ereignis statt selection, wenn Sie den aktuellen Wert des Kombinationsfelds soll.

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

ist wirklich so einfach.

+0

Dank Kumpel, arbeitete wie ein Charme. –

+10

@jvelez Ich denke, es wird nicht schießen, wenn Sie eine Tastatur verwenden. – NoviceProgrammer

+0

das ist scheiße. AnfängerProgrammierer, der wusste ...! – hidden

-2

Dies sollte für Sie arbeiten ...

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

Können Sie erklären, wie dies die Frage beantwortet? –

0

Es ist seltsam, dass SelectedItem die frischen Daten hält, während SelectedValue nicht der Fall ist. Klingt für mich wie ein Käfer.Wenn Ihr Artikel in der Combobox sind andere Objekte als ComboBoxItems, Sie so etwas wie dieses benötigen: (mein ComboBox enthält KeyValuePair s)

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 null sein kann, während Visual Studio hält mich zu sagen, dass ein KeyValuePair kann nicht sei null. Deshalb habe ich das SelectedItem auf ein nullbares KeyValuePair<string, string>? gewirkt. Dann überprüfe ich, ob selectedItem einen anderen Wert als null hat. Dieser Ansatz sollte auf jeden Typ anwendbar sein, den Ihr ausgewählter Gegenstand tatsächlich ist.

-3

Ich löste dies durch das DropDownClosed Ereignis verwenden, da diese leicht ausgelöst, nachdem der Wert geändert wird.

0

Wenn Sie wirklich brauchen die SelectionChanged Ereignis, dann ist die beste Antwort SwDevMan81 Antwort ist. wenn Sie mit WPF jedoch beginnen, dann könnten Sie wollen lernen, wie die Dinge, die WPF Weise zu tun, die anders ist als die alte Windows-Tage Formulare, die auf Ereignissen wie SelectionChanged verlassen verwendet, mit WPF und Model-View-Viewmodel-Muster, Sie sollte Bindings verwenden. 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"); } 
    } 

} 
32

Der richtige Wert hier zu überprüfen, ist die SelectedItem Eigenschaft.

eine Combobox ist eine Verbundsteuerung mit zwei seiner Teile ist durch:

  1. Textteil: der Wert in der diesem Teil entspricht dem Text Eigenschaft des ComboBox.
  2. Der Selektor Teil (das heißt der "drop-down" part): Das ausgewählte Element in diesem Teil entspricht die SelectedItem Eigenschaft.

Expanded ComboBox Parts

Das obige Bild sofort aufgenommen wurde, nachdem die ComboBox expandiert wurde (das heißt, bevor ein neuer Wert der Auswahl). An diesem Punkt beide Text und SelectedItem sind „Info“, vorausgesetzt, die ComboBox Elemente Saiten waren. Wenn die ComboBox Elemente waren stattdessen alle Werte eines Enum genannt „LogLevel“, SelectedItem würde zur Zeit sein LogLevel.Info.

Wenn ein Element in der Dropdown-angeklickt wird, wird der Wert von SelectedItem geändert und die Selection Ereignis ausgelöst wird. Die Text Eigenschaft ist noch nicht aktualisiert, obwohl, wie der Text Teil erst aktualisiert wird, nachdem die Selection Handler beendet ist.Dies kann, indem man einen Haltepunkt in dem Handler und Blick auf die Steuerung zu beachten:

ComboBox at breakpoint in SelectionChanged handler

Da der Text Teil hat an dieser Stelle nicht aktualisiert worden ist, die Text Eigenschaft gibt die zuvor gewählte Wert.

+1

Complete Expanation und es half zu erkennen, dass meine Bindung auf der Text-Eigenschaft statt des richtigen SelectedItem war. – cmousset

4

Dieser arbeitete für mich:

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

Das ist sehr wichtig. Die akzeptierte Antwort zeigt nicht explizit, dass "Absender" das korrekte "SelectedItem" enthält. – Jess

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 der e.AddedItems[0] as kProject wo kProject eine Klasse, die die Daten für mich gearbeitet hält, wie es zu der RemovedItems wurde säumige [0], bevor ich gemacht habe diese ausdrückliche Unterscheidung. Danke SwDevMan81 für die ersten Informationen, die diese Frage für mich beantwortet haben.

1

Das folgende Ereignis wird für jede Änderung des Textes 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" /> 
Verwandte Themen