C#, .NET 4.0, VS2010.
New to WPF. I have a ComboBox on my MainWindow. I hooked the SelectionChanged event of said combo box. However, if I examine the value of the combo box in the event handler, it has the old value. This sounds more like a "SelectionChanging" event, than a SelectionChanged event.
How do I get the new value of the ComboBox after the selection has actually happend?
Currently:
this.MyComboBox.SelectionChanged += new SelectionChangedEventHandler(OnMyComboBoxChanged);
...
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
string text = this.MyComboBox.Text;
}
Note, I get the same behaviour if I use the object being passed in the event args, e.g. e.OriginalSource.
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 correct value to check here is the SelectedItem property.
A ComboBox is a composite control with two of its parts being:
- The Text Part: the value in the this part corresponds to the Text property of the ComboBox.
- The Selector Part (i.e. the "drop-down" part): The selected item in this part corresponds to the SelectedItem property.
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:
Since the Text Part hasn't been updated at this point, the Text property returns the previously selected value.
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 worked for me:
private void AppName_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBoxItem cbi = (ComboBoxItem)AppName.SelectedItem;
string selectedText = cbi.Content.ToString();
}
This worked for me:
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
var text = ((sender as ComboBox).SelectedItem as ComboBoxItem).Content as string;
}
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" />
private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
string newItem = ((DataRowView) e.AddedItems[0]).Row.ItemArray[0].ToString();
}
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;
}
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
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 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
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.
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"); }
}
}
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.
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.
This should work for you ...
int myInt= ((data)(((object[])(e.AddedItems))[0])).kid;
I solved this by using the DropDownClosed event because this fires slightly after the value is changed.
来源:https://stackoverflow.com/questions/2961118/combobox-selectionchanged-event-has-old-value-not-new-value