ValueChanging event and data binding

Editors for WPF Forum

Posted 13 years ago by Michael Davis
Version: 11.1.0543
Platform: .NET 4.0
Environment: Windows 7 (64-bit)
Avatar
I have a situation where I have an Int32EditBox bound to a property on my view model and, under some circumstances, I need to display a confirmation prompt whenever the user changes the value.

I started to do this by handling the ValueChanging event to display a message box and setting the eventArgs.Cancel property to true if the user chose not to confirm the change. As expected, the value in the UI returns to the old value. However, the binding source property is always updated to the new value regardless of the cancellation.

I've come up with a workaround that seems to be working in my case (specifically, I'm listening for the SourceUpdated event instead and reverting the change from there if necessary), but I think this behavior is, if not wrong, then at least very unintuitive. Am I missing anything here about how this is supposed to work?

Here is some sample code that demonstrates the problem. If you enter an odd number in the Int32EditBox, the event handler will cancel the change, but it still propagates to the model and updates the TextBox below.

using System.ComponentModel;
using System.Windows;
using ActiproSoftware.Windows;

namespace WpfApplication1
{
    /// <summary>
    ///     Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Int32EditBox_ValueChanging(object sender, PropertyChangingRoutedEventArgs<int?> e)
        {
            e.Cancel = (e.NewValue % 2) == 1; // Cancel change if the new value is an odd number
        }
    }
    public class Model : INotifyPropertyChanged
    {
        private int _value = 42;

        public int Value
        {
            get { return _value; }
            set
            {
                _value = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Value"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };
    }
}

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:WpfApplication1="clr-namespace:WpfApplication1"
        xmlns:editors="http://schemas.actiprosoftware.com/winfx/xaml/editors"
        Title="MainWindow"
        Height="350"
        Width="525">
    <Window.DataContext>
        <WpfApplication1:Model />
    </Window.DataContext>
    <StackPanel>
        <editors:Int32EditBox Name="_editor"
                              Value="{Binding Value, Mode=TwoWay}"
                              ValueChanging="Int32EditBox_ValueChanging" />
        <TextBox Name="_textBox"
                 Text="{Binding Value, Mode=TwoWay}" />
    </StackPanel>
</Window>

Comments (1)

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Michael,

The ValueChanging event is raised when WPF calls our coercion callback, which is part of the dependency property registration. When you cancel the change, we return the old value from the callback, which effectively resets the Value property to it's old value.

Unfortunately, there is a quirk (not sure if it's considered a bug) in WPF where it will push back the un-coerced value through a two-way binding. We've added a workaround for the next maintenance release, but in the meantime you'd have to use something like the following:
private bool changing = false;
private void Int32EditBox_ValueChanging(object sender, PropertyChangingRoutedEventArgs<int?> e) {
    if (this.changing)
        return;

    this.changing = true;
    try {
        e.Cancel = (e.NewValue % 2) == 1; // Cancel change if the new value is an odd number
        if (e.Cancel)
            ((Int32EditBox)sender).Value = e.OldValue;
    }
    finally {
        this.changing = false;
    }
}


Actipro Software Support

The latest build of this product (v24.1.1) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.