-1

I'm trying to detect when a numeric box value was changed by a user and handle it in my view model.

The numeric DoubleBox is defined in XAML like this:

<numeric:DoubleBox Value="{Binding LeadR}" Grid.Column="1" MinValue="0" MaxValue="1000" IsEnabled="{Binding IsNotMeasuring}" ValueChanged="{Binding DoubleBox_ValueChanged}"/>

In my ViewModel.cs:

private void DoubleBox_ValueChanged(object sender, ValueChangedEventArgs<double?> e)
{
    // Omitted Code: Insert code that does something whenever the text changes...
}

When I right click DoubleBox_ValueChanged in XAML and "Go to definition", it will navigate to the method in WM. But when I run the code, Visual Studio shows this error:

System.Windows.Markup.XamlParseException: ''Provide value on 'System.Windows.Data.Binding' threw an exception.' Line number '123' and line position '162'.'

enter image description here

Can anyone tell me how to solve this?

thatguy
  • 21,059
  • 6
  • 30
  • 40
  • Does [this question](https://stackoverflow.com/questions/25138695/how-to-handle-the-slider-valuechanged-event-in-a-view-model) resolve your issue? – Hayden Aug 19 '20 at 00:00
  • that's not the viewmodel, that's codebehind. In order to make a binding work, you need to set the xaml's DataContext property to a Viewmodel .cs file, that way the binding will work. and you also need a property named LeadR in the viewmodel. – Akos Aug 19 '20 at 06:00
  • Please post the whole exception, the screenshot shows an inner expception. – thatguy Aug 19 '20 at 06:57
  • You shouldn't have an event handler if you're using MVVM. Even if you're not calling it mvvm, you don't need an event handler. For a good answer, you need to provide more information. Like what the viewmodel looks like, whether it's set as the datacontext or not. The minimum code and markup necessary to reproduce your issue. Not your whole project ( most people won't or cannot download those ). – Andy Aug 19 '20 at 08:58

2 Answers2

0

You're using the code-behind and not the viewmodel; the error means that you have not associated a DataContext to the Window/UserControl/whatever the DoubleBox is contained in. You have to setup a ViewModel and bind it to the Container of the DoubleBox to make binding work. I'll give you a quick example.

public class ViewModel : INotifyPropertyChanged
    {

        private double _leadR;
        public double LeadR
        {
            get
            {
                return _leadR;
            }
            set
            {
                _leadR = value;
                OnPropertyChanged(nameof(LeadR));
                OnLeadRChanged();
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void OnLeadRChanged()
        {
            //Do whatever you want with the new value of LeadR
        }
    }

Then in your container you can set the DataContext even in the constructor like

public class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = new ViewModel();
            }
        }

Hope this helps with your question.

HiiiiD
  • 46
  • 1
  • 4
0

If you want to react on a value change on DoubleBox, simply do it in the setter of LeadR.

private double _leadr;
public double LeadR
{
   get => _leadr;
   set
   {
      if (Math.Abs(_leadr - value) > 10E-12)
      {
         _leadr = value;
         OnPropertyChanged();

         // The value changed, do something with it here
      }
   }
}

You do not need and should not handle the ValueChanged event in the view model. Other options are writing an attached property, a tigger action or a behavior, but that might be to complex for what you want to achieve.

The binding exception that you get seems to originate from using a wrong type, since the inner exception of the XamlParseException is an InvalidCastException.

thatguy
  • 21,059
  • 6
  • 30
  • 40