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 являются "Info", предполагая, что элементы ComboBox были строками. Если элементы ComboBox были вместо этого все значения перечисления под названием "LogLevel",SelectedItem в настоящее время будет LogLevel.Info.
когда элемент в раскрывающемся списке нажимается, значение SelectedItem и SelectionChanged события. The текст свойство еще не обновлено, хотя, как Текстовая Часть не обновляется до после 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 (при изменении выбранного индекса и при изменении текста путем редактирования).
<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 продолжает говорить мне, что KeyValuePair
не может быть null. Вот почему я бросил SelectedItem
к nullable KeyValuePair<string, string>?
. Затем я проверяю, если selectedItem
имеет значение null
. Этот подход должен быть применим к любому типу выбранного вами элемента.
Если вам действительно нужен SelectionChanged
событие, тогда лучшим ответом является ответ SwDevMan81. Однако, если вы начинаете с WPF, вы можете узнать, как делать вещи способом WPF, который отличается от старых дней Windows Forms, которые привыкли полагаться на такие события, как SelectionChanged
, с WPF и Model View ViewModel pattern, вы должны использовать привязки. Вот пример кода:
// 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 за первоначальную информацию, которая ответила на этот вопрос для меня.
Я решил это, используя событие DropDownClosed, потому что это срабатывает немного после изменения значения.