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

C # ,. NET 4.0,VS2010.

WPF 新手。我的主窗口上有一个组合框。我钩住了该组合框的 SelectionChanged 事件。但是,如果我检查事件处理程序中组合框的值,它就具有原来的值。这听起来更像是“ SelectionChanged”事件,而不是 SelectionChanged 事件。

在选择实际发生之后,如何获得组合框的新值?

目前:

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


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

注意,如果我使用在事件参数中传递的对象,我会得到相同的行为,例如,e.OriginalSource。

224865 次浏览

According to MSDN, e.AddedItems:

Gets a list that contains the items that were selected.

So you could use:

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

You could also use SelectedItem if you use string values for the Items from the sender:

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

or

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

Since both Content and SelectedItem are objects, a safer approach would be to use .ToString() instead of as string

The second option didn't work for me because the .Text element was out of scope (C# 4.0 VS2008). This was my solution...

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

This worked for me:

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

I needed to solve this in VB.NET. Here's what I've got that seems to work:

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
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
}

Use the DropDownClosed event instead of selectionChanged if you want the current value of the combo box.

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

Is really that simple.

This should work for you ...

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

It's weird that SelectedItem holds the fresh data, whereas SelectedValue doesn't. Sounds like a bug to me. If your items in the Combobox are objects other than ComboBoxItems, you will need something like this: (my ComboBox contains KeyValuePairs)

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 can be null, whereas Visual Studio keeps telling me that a KeyValuePair can't be null. That's why I cast the SelectedItem to a nullable KeyValuePair<string, string>?. Then I check if selectedItem has a value other than null. This approach should be applicable to whatever type your selected item actually is.

I solved this by using the DropDownClosed event because this fires slightly after the value is changed.

If you really need the SelectionChanged event, then the best answer is SwDevMan81's answer. However, if you are starting with WPF, then you might want to learn how to do things the WPF way, which is different than the old Windows Forms days that used to rely on events like SelectionChanged, with WPF and Model View ViewModel pattern, you should use bindings. Here is a code example:

// 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"); }
}


}

The correct value to check here is the SelectedItem property.

A ComboBox is a composite control with two of its parts being:

  1. The Text Part: the value in the this part corresponds to the Text property of the ComboBox.
  2. The Selector Part (i.e. the "drop-down" part): The selected item in this part corresponds to the SelectedItem property.

Expanded ComboBox Parts

The image above was taken immediately after the ComboBox was expanded (i.e. before selecting a new value). At this point both Text and SelectedItem are "Info", assuming the ComboBox items were strings. If the ComboBox items were instead all the values of an Enum called "LogLevel", SelectedItem would currently be LogLevel.Info.

When an item in the drop-down is clicked on, the value of SelectedItem is changed and the SelectionChanged event is raised. The Text property isn't updated yet, though, as the Text Part isn't updated until after the SelectionChanged handler is finished. This can be observed by putting a breakpoint in the handler and looking at the control:

ComboBox at breakpoint in SelectionChanged handler

Since the Text Part hasn't been updated at this point, the Text property returns the previously selected value.

This worked for me:

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
var text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string;
}
private void indBoxProject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int NewProjID = (e.AddedItems[0] as kProject).ProjectID;
this.MyProject = new kProject(NewProjID);
LoadWorkPhase();
}

The use of the e.AddedItems[0] as kProject where kProject is a class that holds the data worked for me as it was defaulting to the RemovedItems[0] before I have made this explicit distinction. Thanks SwDevMan81 for the initial information that answered this question for me.

Following event is fired for any change of the text in the ComboBox (when the selected index is changed and when the text is changed by editing too).

<ComboBox IsEditable="True" TextBoxBase.TextChanged="cbx_TextChanged" />

Don't complicate things for no reason. Using SelectedValue property you can easily get a selected ComboBox value like this: YourComboBoxName.SelectedValue.ToString().

Behind the scene the SelectedValue property is defined as: SelectedValue{get; set;} this means you can use it to get or set the value of a ComboBox.

Using SelectedItem is not an efficient way to get a ComboBox value since it requires a lot of ramifications.

You can check SelectedIndex or SelectedValue or SelectedItem property in the SelectionChanged event of the Combobox control.

From SelectionChanged event of a combobox you can get the selected item text as follow:

        private void myComboBox_SelectionChanged (object sender, SelectionChangedEventArgs e)
{
ComboBoxItem comboBoxItem = (ComboBoxItem) e.AddedItems[0];
string selectedItemText = comboBoxItem.Content.ToString();
}