ComboBox – SelectionChanged事件具有旧值,而不是新值

C#,.NET 4.0,VS2010。

新来WPF。 我的MainWindow上有一个ComboBox。 我迷上了所述combobox的SelectionChanged事件。 但是,如果我检查事件处理程序中的combobox的值,它具有旧的值。 这听起来更像是一个“SelectionChanging”事件,而不是一个SelectionChanged事件。

在select实际发生之后,如何获得combobox的新值?

目前:

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

请注意,如果使用事件args,egeOriginalSource中传递的对象,我会得到相同的行为。

根据MSDN, e.AddedItems

获取包含所选项目的列表。

所以你可以使用:

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

如果您使用来自senderItems string值,也可以使用SelectedItem

 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; } 

由于ContentSelectedItem都是对象,所以更安全的方法是使用.ToString()而不是as string

如果您需要combobox的当前值,请使用DropDownClosed事件而不是selectionChanged。

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

真的很简单

这里检查的正确值是SelectedItem属性。

ComboBox是一个复合控件,它的两个部分是:

  1. 文本部分 :这部分的值对应于ComboBox的Text属性。
  2. select器部分 (即“下拉”部分):这部分中的选定项目对应于SelectedItem属性。

扩展的组合框部件

上面的图像是在ComboBox展开后(即在select新值之前)立即获取的。 此时TextSelectedItem都是“Info”,假设ComboBox项目是string。 如果combobox项目是所有名为“LogLevel”的Enum的值,则SelectedItem将当前为LogLevel.Info

当单击下拉菜单中的某个项目时, SelectedItem的值将被更改,并引发SelectionChanged事件。 但是Text属性还没有更新,因为文本部分SelectionChanged处理程序完成之后才会更新。 这可以通过在处理程序中放置断点并查看控件来观察:

ComboBox在SelectionChanged处理程序的断点处

由于此时文本部分尚未更新,所以Text属性返回之前选定的值。

这对我工作:

 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; } 

第二个选项对我不起作用,因为.Text元素超出了范围(C#4.0 VS2008)。 这是我的解决scheme…

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

以下事件被触发,用于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(); } 

我需要在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以外的对象,则需要如下所示:(我的ComboBox包含KeyValuePair

 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转换为可空的KeyValuePair<string, string>? 。 然后我检查selectedItem是否有一个非null 。 这种方法应该适用于你select的物品的实际types。

如果你真的需要SelectionChanged事件,那么最好的答案是SwDevMan81的答案。 但是,如果你是从WPF开始,那么你可能想学习如何做WPF的方式,这是不同于旧的Windows窗体天,过去依赖像SelectionChanged ,WPF和模型视图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为我回答这个问题的初始信息。

这应该适合你…

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

我通过使用DropDownClosed事件解决了这个问题,因为在值更改后会稍微触发。