ComboBox-SelectionChanged событие имеет старое значение, а не новое значение
C#, .NET 4.0, VS2010.
новый для WPF. У меня есть ComboBox на моем главном окне. Я подключил событие SelectionChanged указанного поля со списком. Однако, если я проверю значение поля со списком в обработчике событий, оно имеет старое значение. Это больше похоже на событие "SelectionChanging", чем на событие SelectionChanged.
Как я могу получить новое значение ComboBox после того, как выбор действительно произошел?
:this.MyComboBox.SelectionChanged += new SelectionChangedEventHandler(OnMyComboBoxChanged);
...
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
string text = this.MyComboBox.Text;
}
Примечание., Я получаю такое же поведение, если я использую объект, передаваемый в событии args, например E. OriginalSource.
14 ответов:
согласно MSDN,
e.AddedItems
:возвращает список, содержащий элементы, которые были выбраны.
так что вы могли бы использовать:
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) { string text = (e.AddedItems[0] as ComboBoxItem).Content as string; }
вы также можете использовать
SelectedItem
если вы используетеstring
значенияItems
Сsender
:private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) { string text = (sender as ComboBox).SelectedItem as string; }
или
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) { string text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string; }
так как
Content
иSelectedItem
являются объектами, более безопасным подходом было бы использовать.ToString()
вместоas string
используйте событие DropDownClosed вместо selectionChanged, если требуется текущее значение поля со списком.
private void comboBox_DropDownClosed(object sender, EventArgs e) { MessageBox.Show(comboBox.Text) }
- Это действительно так просто.
правильное значение для проверки здесь SelectedItem собственность.
компонент ComboBox представляет собой составной элемент управления с двумя своими частями:
- Текстовая Часть: значение в этой части соответствует текст свойства компонента ComboBox.
- Часть Селектора (т. е." выпадающая " часть): выбранный элемент в этой части соответствует SelectedItem свойство.
изображение выше было сделано сразу после того, как ComboBox был расширен (т. е. перед выбором нового значения). В этот момент оба текст и SelectedItem являются "информация", предполагая, что элементы ComboBox были строками. Если элементы ComboBox были вместо этого все значения перечисления под названием "LogLevel", SelectedItem в настоящее время будет LogLevel.Info.
когда элемент в раскрывающемся списке будет нажат, значение SelectedItem и SelectionChanged события. Элемент текст свойство еще не обновлено, хотя, как Текстовая Часть не обновляется до тех пор, пока после SelectionChanged обработчик завершения. Это можно наблюдать, поместив точку останова в обработчик и посмотрев на управление:
с Текстовая Часть не был обновлен на данный момент,текст свойство возвращает ранее выбранное значение.
это сработало для меня:
private void AppName_SelectionChanged(object sender, SelectionChangedEventArgs e) { ComboBoxItem cbi = (ComboBoxItem)AppName.SelectedItem; string selectedText = cbi.Content.ToString(); }
это сработало для меня:
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) { var text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string; }
следующее событие запускается для любого изменения текста в поле со списком (при изменении выбранного индекса и при изменении текста путем редактирования тоже).
<ComboBox IsEditable="True" TextBoxBase.TextChanged="cbx_TextChanged" />
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e) { string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString(); }
второй вариант не работает для меня, потому что .Текстовый элемент был вне области действия (C# 4.0 VS2008). Это было мое решение...
string test = null; foreach (ComboBoxItem item in e.AddedItems) { test = item.Content.ToString(); break; }
Мне нужно было решить это в VB.NET вот что у меня есть, что, кажется, работает:
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
странно, что для selecteditem содержит свежие данные, в то время как SelectedValue не. Звучит как ошибка для меня. Если ваши элементы в Combobox являются объектами, отличными от ComboBoxItems, вам понадобится что-то вроде этого: (my
ComboBox
содержит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, в то время как Visual Studio продолжает говорить мне, что aKeyValuePair
не может быть null. Вот почему я бросилSelectedItem
к нам!--6-->. Тогда я проверю, еслиselectedItem
имеет значениеnull
. Этот подход должен быть применим к любому типу выбранного элемента на самом деле.
Если вам действительно нужен
SelectionChanged
событие, тогда лучший ответ-это ответ SwDevMan81. Однако, если вы начинаете с WPF, то вы можете узнать, как делать вещи способом WPF, который отличается от старых дней Windows Forms, которые раньше полагались на такие события, какSelectionChanged
, с шаблоном WPF и Model View ViewModel, вы должны использовать привязки. Вот пример кода:// 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"); } } }
private void indBoxProject_SelectionChanged(object sender, SelectionChangedEventArgs e) { int NewProjID = (e.AddedItems[0] as kProject).ProjectID; this.MyProject = new kProject(NewProjID); LoadWorkPhase(); }
использование
e.AddedItems[0] as kProject
где kProject-это класс, который содержит данные, которые работали для меня, поскольку он был по умолчанию для RemovedItems[0], прежде чем я сделал это явное различие. Спасибо SwDevMan81 за первоначальную информацию, которая ответила на этот вопрос для меня.