WPF ComboBox SelectedItem - change to previous value WPF ComboBox SelectedItem - change to previous value wpf wpf

WPF ComboBox SelectedItem - change to previous value


When the user says "no", WPF is unaware that the value has changed. As far as WPF is concerned, the value is whatever the user selected.

You might try raising a property changed notification:

public object SelItem{    get { ... }    set    {        if (!CancelChange())        {            this.selItem = value;        }        OnPropertyChanged("SelItem");    }}

The problem is, the change notification happens within the same context of the selection event. Thus, WPF ignores it because it already knows the property has changed - to the item the user selected!

What you need to do is raise the notification event in a separate message:

public object SelItem{    get { ... }    set    {        if (CancelChange())        {            Dispatcher.BeginInvoke((ThreadStart)delegate            {                OnPropertyChanged("SelItem");            });            return;        }        this.selItem = value;        OnPropertyChanged("SelItem");    }}

WPF will then process this message after it's done processing the selection changed event and will therefore revert the value in the view back to what it should be.

Your VM will obviously need access to the current Dispatcher. See my blog post on a base VM class if you need some pointers on how to do this.


Thanks for this question and answers. The Dispatcher.BeginInvoke helped me and was part of my final solution, but the above solution didn't quite work in my WPF 4 app.

I put together a small sample to figure out why. I had to add code that actually changed the underlying member variable's value temporarily so that when WPF re-queried the getter, it would see that the value chaned. Otherwise, the UI didn't properly reflect the cancellation and the BeginInvoke() call did not do anything.

Here's a my blog post with my sample showing a non-working and a working implementation.

My setter ended up looking like this:

    private Person _CurrentPersonCancellable;    public Person CurrentPersonCancellable    {        get        {            Debug.WriteLine("Getting CurrentPersonCancellable.");            return _CurrentPersonCancellable;        }        set        {            // Store the current value so that we can             // change it back if needed.            var origValue = _CurrentPersonCancellable;            // If the value hasn't changed, don't do anything.            if (value == _CurrentPersonCancellable)                return;            // Note that we actually change the value for now.            // This is necessary because WPF seems to query the             //  value after the change. The combo box            // likes to know that the value did change.            _CurrentPersonCancellable = value;            if (                MessageBox.Show(                    "Allow change of selected item?",                     "Continue",                     MessageBoxButton.YesNo                ) != MessageBoxResult.Yes            )            {                Debug.WriteLine("Selection Cancelled.");                // change the value back, but do so after the                 // UI has finished it's current context operation.                Application.Current.Dispatcher.BeginInvoke(                        new Action(() =>                        {                            Debug.WriteLine(                                "Dispatcher BeginInvoke " +                                 "Setting CurrentPersonCancellable."                            );                            // Do this against the underlying value so                             //  that we don't invoke the cancellation question again.                            _CurrentPersonCancellable = origValue;                            OnPropertyChanged("CurrentPersonCancellable");                        }),                        DispatcherPriority.ContextIdle,                        null                    );                // Exit early.                 return;            }            // Normal path. Selection applied.             // Raise PropertyChanged on the field.            Debug.WriteLine("Selection applied.");            OnPropertyChanged("CurrentPersonCancellable");        }    }


Another way to do it (make sure you also read the comments):

http://amazedsaint.blogspot.com/2008/06/wpf-combo-box-cancelling-selection.html

From the link:Another solution for issue of recursive calling of event handler without global variable is to cancel handler assignment before programmatic selection change, and reassign it after that.

Ex:

cmb.SelectionChanged -= ComboBox_SelectionChanged;cmb.SelectedValue = oldSel.Key;cmb.SelectionChanged += ComboBox_SelectionChanged;