ComboBox - Zdarzenie SelectionChanged ma starą wartość, a nie nową wartość

C#,. NET 4.0, VS2010.

Nowość w WPF. Mam ComboBox na moim głównym oknie. Podłączyłem Zdarzenie SelectionChanged wspomnianego combo box. Jednakże, jeśli zbadam wartość pola kombi w programie obsługi zdarzeń, ma ono starą wartość. To bardziej przypomina Zdarzenie "SelectionChanging", niż Zdarzenie SelectionChanged.

Jak uzyskać nową wartość ComboBox po dokonaniu wyboru?

Aktualnie:

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

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

Uwaga, mam takie samo zachowanie, jeśli użyj obiektu przekazywanego w args zdarzenia, np. OriginalSource.

Author: Kay Lee, 2010-06-02

14 answers

Według MSDN, e.AddedItems:

Pobiera listę zawierającą wybrane elementy.

Więc możesz użyć:

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

Możesz również użyć SelectedItem jeśli użyjesz string wartości dla Items z sender:

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

Lub

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

Ponieważ zarówno Content, jak i SelectedItem są obiektami, bezpieczniejszym podejściem byłoby użycie .ToString() zamiast as string

 90
Author: SwDevMan81,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-21 14:42:22

Użyj zdarzenia DropDownClosed zamiast selectionChanged, jeśli chcesz mieć bieżącą wartość pola kombi.

private void comboBox_DropDownClosed(object sender, EventArgs e)
{
   MessageBox.Show(comboBox.Text) 
}
To naprawdę takie proste.
 41
Author: hidden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-18 11:52:02

Poprawną wartością do sprawdzenia jest właściwość SelectedItem .

ComboBox to sterowanie złożone z dwóch jego części:

  1. część tekstowa : wartość w tej części odpowiada właściwości Text ComboBox.
  2. część selektora (tzn. część" rozwijana"): zaznaczona pozycja w tej części odpowiada właściwości SelectedItem .

Rozszerzone Części ComboBox

Obrazek powyższe zostało zrobione natychmiast po rozszerzeniu Comboboxu (tzn. przed wyborem nowej wartości). W tym momencie zarówno Text jak i SelectedItem są "Info", zakładając, że elementy ComboBox były ciągami znaków. Jeśli elementy ComboBox zamiast wszystkich wartości Enum o nazwie "LogLevel", SelectedItem będzie obecnie LogLevel.Info .

Gdy element z listy rozwijanej zostanie kliknięty, wartość SelectedItem zostanie zmieniona, a SelectionChanged wydarzenie zostało podniesione. Właściwość Text nie jest jeszcze aktualizowana, ponieważ część tekstowa jest aktualizowana dopiero po SelectionChanged handler jest skończony. Można to zaobserwować, umieszczając punkt przerwania w module obsługi i patrząc na kontrolkę:

ComboBox w punkcie przerwania w selectionchanged handler

Ponieważ część tekstowa nie została w tym momencie zaktualizowana, Właściwość Text zwraca wcześniej wybraną wartość.

 38
Author: Dave Kidder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-19 17:37:00

To mi pomogło:

private void AppName_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
   ComboBoxItem cbi = (ComboBoxItem)AppName.SelectedItem;
   string selectedText = cbi.Content.ToString();
}
 10
Author: Ramon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-18 11:52:18

To mi pomogło:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    var text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string;            
}
 4
Author: Бранко Пејић,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-21 14:43:24

Następne zdarzenie zostanie wywołane dla każdej zmiany tekstu w Comboboxie(przy zmianie wybranego indeksu i przy zmianie tekstu również przez edycję).

<ComboBox IsEditable="True" TextBoxBase.TextChanged="cbx_TextChanged" />
 2
Author: Petr Voborník,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-27 09:02:01
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
}
 1
Author: Buratino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-17 13:11:04

Druga opcja nie działa dla mnie, ponieważ .Element tekstowy był poza zakresem (C # 4.0 VS2008). To było moje rozwiązanie...

string test = null;
foreach (ComboBoxItem item in e.AddedItems)
{
   test = item.Content.ToString();
   break;
}
 1
Author: Josh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-18 11:52:36

I need to solve this in VB.NET. oto co mam to chyba działa:

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
Author: zzMzz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-18 11:53:07

To dziwne, że SelectedItem przechowuje świeże dane, podczas gdy SelectedValue nie. dla mnie brzmi to jak błąd. Jeśli twoje przedmioty w Comboboxie są obiektami innymi niż ComboBoxItems, będziesz potrzebował czegoś takiego: (my ComboBox zawiera 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 może być null, podczas gdy Visual Studio ciągle mi mówi, że KeyValuePair nie może być null. Dlatego rzuciłem SelectedItem na nullable KeyValuePair<string, string>?. Następnie sprawdzam czy selectedItem ma wartość inną niż null. Podejście to powinno mieć zastosowanie do każdego wpisz wybrany element faktycznie jest.

 0
Author: sorrymissjackson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-01 14:20:04

Jeśli naprawdę potrzebujesz zdarzenia SelectionChanged, najlepszą odpowiedzią jest odpowiedź SwDevMan81. Jeśli jednak zaczynasz od WPF, możesz chcieć dowiedzieć się, jak robić rzeczy w sposób WPF, który jest inny niż stare dni Windows Forms, które kiedyś polegały na zdarzeniach takich jak SelectionChanged, z WPF i modelem View ViewModel pattern, powinieneś używać wiązań. Oto przykład kodu:

// 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
Author: Lazaro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-06 15:13:21
private void indBoxProject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    int NewProjID = (e.AddedItems[0] as kProject).ProjectID;
    this.MyProject = new kProject(NewProjID);
    LoadWorkPhase();
}

Użycie e.AddedItems[0] as kProject gdzie kProject jest klasą, która przechowuje dane, działało dla mnie jako domyślne dla RemovedItems[0] zanim dokonałem tego wyraźnego rozróżnienia. Dzięki SwDevMan81 za wstępne informacje, które odpowiedziały na to pytanie dla mnie.

 0
Author: kyjote,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-22 12:43:43

To powinno zadziałać ...

int myInt= ((data)(((object[])(e.AddedItems))[0])).kid;
 -2
Author: soulexit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-29 19:15:11

Rozwiązałem to za pomocą zdarzenia DropDownClosed, ponieważ to zostanie wywołane nieco po zmianie wartości.

 -3
Author: user5028920,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-19 15:45:14