Friday, October 10, 2008

MSDN Question on WPF: Keeping ComboBox selection unchanged

I came across this interesting question on MSDN WPF forums where a user had a combo box whose XAML can be like shown.


<ComboBox SelectionChanged="ComboBox_SelectionChanged" Name="myFoo" Width="100" Height="20" >
<ComboBoxItem>Item1</ComboBoxItem>
<ComboBoxItem>Item2</ComboBoxItem>
<ComboBoxItem>Browse</ComboBoxItem>
</ComboBox>

The requirement is that when the user selects "Browse", a dialog should pop up and based on the answer from the user (Yes/No) you should either show browser in combo box as selected or just keep the previously selected item in the selection. That is, if Item1 is selected and then Browse is selected, and the user clicks No, then Item1 should still remain selected. So, how do we suppress the selection for such cases?

The idea is to keep track of previously selected item. If current selection is "Browse" then we ask for user input for yes or no using a message box(or any dialog for that matter). If the answer is no, then we should not show Browse => we set back the SelectedValue property back to the "previous". If current selection is not Browse, then it becomes the "previous". The code that does this is shown below.



/// &lt;summary&gt;
/// Keeps track of the last selected combobox item by the user.
/// &lt;/summary&gt;
private ComboBoxItem prev;
/// &lt;summary&gt;
/// fromEventHandler if set to true indicates that the event handler has been fired because of a change made to the selected item
/// of the combobox from a event handler and not from code.
/// You set this to true if the selection is browse. And then set it back to false later.
/// &lt;/summary&gt;
private bool fromEventHandler = false;
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (fromEventHandler) return;

//If browse is selected from the combobox
if ((myFoo.SelectedValue as ComboBoxItem).Content.ToString() == "Browse")
{
//An example of a dialog. If dialog result is No, then you do not show Browse in the item and instead show the previously selected option
if (MessageBox.Show("Set or No Set", "Yes to see Browse, No to revert to previous item", MessageBoxButton.YesNo) == MessageBoxResult.No)
{
fromEventHandler = true;
myFoo.SelectedValue = prev;
fromEventHandler = false;
//e.Handled = true; //not required, still works without this.
}
}
else //if any other item is selected, we store it as previously selected item
{
prev = myFoo.SelectedValue as ComboBoxItem;
}
}



So why do we need "fromEventHandler" variable? The reason is that if when you "SelectedValue" to "prev", then the SelectionChanged Event would fire again and the dialog box would be shown once more. So, to suppress this, we need a way to keep track of selection changes made from the event handler.

I hope this was little helpful.

No comments: