WPF ComboBox SelectionChangedEvent
When programming with the Combobox and handling its SelectionChangedEvent, you need to be a bit careful. The general expectation will be that when this event fires, the various properties like SelectionBoxItem or Text will give the new value, but that isn't the case.
The SelectedIndex does points to the newly selected item index, but the values of properties like SelectionBoxItem or Text still point to the old values and the new one selection hasn't really been updated. It is only after the event handler code that you write has completed execution that these properties update.
Take a simple sample XAML as below
<Window x:Class="TestWPFApp.ComboTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestWPFApp"
Title="ComboTest" Height="300" Width="300">
<Window.Resources>
<ObjectDataProvider x:Key="colorCol" ObjectType="{x:Type local:MyColorCollection}"/>
<local:MyColorCollection x:Key="colors" />
</Window.Resources>
<Grid>
<ComboBox Name="cmbBox" SelectionChanged="cmbBox_SelectionChanged" Height="27" VerticalAlignment="Top" Margin="43,17,45,0">
<ComboBoxItem>One</ComboBoxItem>
<ComboBoxItem>Two</ComboBoxItem>
<ComboBoxItem>Three</ComboBoxItem>
</ComboBox>
<Button Content="Click" Name="myBtn" Margin="93,101,91,130" />
</Grid>
</Window>
We intend to disable the button when the value selected in ComboBox is "One" and keep it enabled otherwise. If you were to write code like the following, you will be in for a surprise since as i mentioned earlier, the value of SelectionBoxItem still points to earlier value while the SelectionChangedEvent is being processed.
private void cmbBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (string.Equals(cmbBox.SelectionBoxItem.ToString(), "One"))
myBtn.IsEnabled = false;
else
myBtn.IsEnabled = true;
}
This is easily addressed by using the properties like SelectedIndex directly. So in our case, since we know the value of "One" is at index 0, we can use that directly as below
private void cmbBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (cmbBox.SelectedIndex == 0)
myBtn.IsEnabled = false;
else
myBtn.IsEnabled = true;
}
However the if you want really work with the right values and not rely on prior knowledge of indices, you would want to work with the details available in the SelectionChangedEventArgs parameter that is available for this event. This object has additional properties like AddedItems and RemovedItems that will give the details of the item that is about to be selected and the item that is about to be deselected. These can contain multiple values since the same object is used in cases like multiselect ListBoxes or ListView controls. So a code like the following is what you can actually write to get the same effect and without relying on hardcoded index values.
private void cmbBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
myBtn.IsEnabled = true;
foreach (ComboBoxItem item in e.AddedItems)
{
if (string.Equals(item.Content, "One"))
{
myBtn.IsEnabled = false;
break;
}
}
}
Finally, just to prove the point, I ran the application and put a debug breakpoint in the SelectionChangedEvent handler code. The figure below shows that while the debugger has hit the code, the ComboBox drop down hasn't still collapsed. The dropdown can still be seen over the VS window while i am debugging the event handler. It is only after I exit the handler, will this drop down disappear and the new selection appear in the ComboBox's display area (and the values of SelectionBoxItem and Text property get updated).

Feel free to try this yourself and verify.



Comments
You can also use this:
((ContentControl(cmbBox.Items[cmbBox.SelectedIndex])).Content.ToString();
to get the "SelectedText" we have on windows forms.
Posted by: Mario Calderon | September 25, 2008 5:40 PM
Mario, you are right and this works since as I mentioned earlier, the SelectedIndex property can be used directly. However, please note that if ComboBox allows multiple selection, then this won't work and you will have to revert to using the AddedItems collection.
Posted by: Atul Gupta | September 29, 2008 8:08 AM
This is an excellent post...
Thanks Atul ...!!!
Posted by: KJ | February 5, 2009 10:21 AM