Infosys Microsoft Alliance and Solutions blog

« The “framework” conundrum in ERP/CRM | Main | WPF - Bound property updates before Target property »

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).

ComboBox.jpg

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.

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.

This is an excellent post...
Thanks Atul ...!!!

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Please key in the two words you see in the box to validate your identity as an authentic user and reduce spam.

Subscribe to this blog's feed

Follow us on

Blogger Profiles

Infosys on Twitter