0

I have a WinForms project that uses data bindings to track realtime prices. The prices are bound like so:

var btcPriceInUsdBinding = new Binding("Text", Client, "BtcPriceInUsd", true, DataSourceUpdateMode.OnPropertyChanged);
btcPriceInUsdBinding.Format += (s, e) => { e.Value = string.Format("BTC/USD: ${0:#####0.00}", e.Value); };
btcUsdValueLabel.DataBindings.Add(btcPriceInUsdBinding);

The actual object storing the data inherits from an ObservableObject - that is, an abstract base class that implements INotifyPropertyChanged.

public abstract class ObservableObject : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    public void Notify([CallerMemberName]string property = null)
    {
        if (property != null)
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }

}

Then when a value is changed, it is fired like this

    public decimal BtcPriceInUsd
    {
        get { return _btcPriceInUSD; }
        set {
            _btcPriceInUSD = value;
            Notify();
        }
    }

Debugging, I can see that the PropertyChanged is correctly being called, and breaking inside of the Binding.Format event shows that e.Value is the correct value. However, despite all of this, the label does not update. Why is this happening?

w0f
  • 908
  • 9
  • 23
  • Is your PropertyChanged null, when you try to invoke it? As you are using conditionalaccess you won't see if it is not null when just stepping through. Had this kind of problem several times and most of the time nothing was bound to my PropertyChanged event – Tobias Theel Aug 28 '17 at 15:49
  • 1
    Pro Tip:Use `nameof(TextBox.Text)` and `nameof(MyClass.BtcPriceInUsd)`. Then you get compilation errors if you have a typo and refactoring will propagate to the bindings (not related to your question, though) – Dennis Kuypers Aug 28 '17 at 15:52
  • We don't have a code to reproduce the problem and I tested in a clean environment and every thing is working fine. Just make sure that the object instance that you are changing is the same instance that you bind your label to it. For example take a look at [this post](https://stackoverflow.com/a/39821755/3110834) to see a common mistake: [Data Binding doesn't work when I assign a new object instance to the bound variable](https://stackoverflow.com/a/39821755/3110834) – Reza Aghaei Aug 28 '17 at 16:05
  • @TobiasTheel Your suggestion seems to have at least figured out what is wrong. The derived object's PropertyChanged hjas a value, but the base class PropertyChanged is null. What I don't understand is that the Binding.Format event is still called with all the proper values when updated. Regardless, is this because the PropertyChanged handling is in a base/abstract class? – w0f Aug 28 '17 at 16:57
  • My best guess is, that your base class does not recognize, that you bound your property to something, so your event handler is null. Try the following implementation, this is how i also do it: https://stackoverflow.com/a/1316417/4992212 – Tobias Theel Aug 28 '17 at 17:05
  • I'd replace the `Format` event handler to not use a lambda expression just for testing purposes, and implement it just as a regular `Format` event handler. I'm thinking your `e.Value = string.Format("BTC/USD: ${0:#####0.00}", e.Value);` is throwing an exception, which is not getting caught anywhere, and silently being dropped. Having a "regular" event handler method will give you a chance to more easily step through it and see if it actually throws. – Luc Morin Nov 04 '17 at 20:47

0 Answers0