0

I have a databinding that uses the MethodToValueConverter in this answer. This works great, however I am having difficulty forcing the view to update after the result of the method has changed. It's a little hard to explain, so hopefully some code snippits will help.

The class object

[DataContract]
public class RetentionBankItem : INotifyPropertyChanged
{
    #region Private Properties
    public event PropertyChangedEventHandler PropertyChanged;
    private float _rbRevisedRateLoad;
    private float _rbCurrentRateLoad;
    #endregion

    [DataMember]
    public float rbRevisedRateLoad
    {
        get
        {
            return _rbRevisedRateLoad;
        }
        set
        {
            PropertyChanged.ChangeAndNotify(ref _rbRevisedRateLoad, value, () => rbRevisedRateLoad);
            OnPropertyChanged("RateLoadDifference");
        }
    }

    [DataMember]
    public float rbCurrentRateLoad
    {
        get
        {
            return _rbCurrentRateLoad;
        }
        set
        {
            PropertyChanged.ChangeAndNotify(ref _rbCurrentRateLoad, value, () => rbCurrentRateLoad);
            OnPropertyChanged("RateLoadDifference");
        }
    }

    public float RateLoadDifference()
    {
        if (rbCurrentRateLoad != 0)
        {
            return rbRevisedRateLoad / rbCurrentRateLoad;
        }
        return 0;
    }
}

It should be noted that in the following code, RetentionBank is of type List<RetentionBankItem>

My binding looks like this:

<ItemsControl ItemsSource="{Binding RetentionBank}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding rbRevisedRateLoad, Mode=TwoWay}"
                     Grid.Row="2"
                     Grid.Column="0" />

            <TextBox Text="{Binding rbCurrentRateLoad, Mode=TwoWay}"
                     Grid.Row="2"
                     Grid.Column="1" />

            <TextBox Text="{Binding Path=., Converter={StaticResource ConverterMethodToValue}, ConverterParameter='RateLoadDifference', Mode=OneWay}"
                     Grid.Row="2"
                     Grid.Column="2" />
         </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

The Current and Revised rate loads are getting set properly, but after they're set the RateLoadDifference is never getting called to update. I imagine that the class object itself needs to be called to update, since that's what the textbox is actually bound to (not necessarily the method itself), but I am unsure how to do that, or if it is even the proper way to do it. Any help or suggestions would be appreciated. Thanks!

Community
  • 1
  • 1
jmgardn2
  • 981
  • 2
  • 8
  • 21
  • What is PropertyChanged.ChangeAndNotify? – Sasha Sep 23 '14 at 14:47
  • It's essentially a cleaner (and more code-friendly by not using strings) way of calling `OnPropertyChanged`. I got that bit of code from [here](http://wpftutorial.net/INotifyPropertyChanged.html) – jmgardn2 Sep 23 '14 at 14:50
  • Does it work in regular way - _rbCurrentRateLoad = value; OnPropertyChanged()? – Sasha Sep 23 '14 at 14:54
  • Unfortunately not. Current and Revised rate load properties get set no problem, but after they are set the view isn't updating with the latest result from `RateLoadDifference` – jmgardn2 Sep 23 '14 at 15:18
  • 1
    May be you Need a getter for RateLoadDifference? – Sasha Sep 23 '14 at 15:33
  • See my comment on Histonivich's answer for why I wouldn't necessarily want to turn it into a property. – jmgardn2 Sep 23 '14 at 17:40

1 Answers1

2

Change the RateLoadDifference to a property:

public float RateLoadDifference
{
    get
    {
        if (rbCurrentRateLoad != 0)
        {
            return rbRevisedRateLoad / rbCurrentRateLoad;
        }

        return 0;
    }
}

Then change the binding to be

Binding="{Binding Path=RateLoadDifference, Mode=OneWay}"
Jack
  • 336
  • 1
  • 7
  • While this is an option, I try to stay away from using properties in such a way. Unfortunately it doesn't quite fit exactly into one category as mentioned in the [Choosing Between Properties and Methods](http://msdn.microsoft.com/en-us/library/vstudio/ms229054(v=vs.100).aspx) article. In this particular instance I would say a property wouldn't cause too much harm, but there are other instances where I could run into the same problem with something that I definitely wouldn't want to put into a property. – jmgardn2 Sep 23 '14 at 17:39
  • And that's why I'm here, to see if I'm being a little narrow minded, or if there is a way to do it without using properties. We shall see! – jmgardn2 Sep 23 '14 at 17:49
  • I think ViewModel functionality can sometimes be subjective. The way I code, is to think of the ViewModel as manipulating Model data for specific View requirements. Which as the View needs the RateLoadDifference, I don't find a problem in this case. What would be a different way @jmgardn2? – Jack Sep 23 '14 at 18:10
  • in general the idea of writing more code than is required just to follow an idea is a code smell - converters are expensive and in this case it can be avoided, therefore this is a code smell. – AwkwardCoder Sep 23 '14 at 19:32
  • Not to mention there is a certain performance penalty in converters, which ultimately should be a very simple binding. – Jack Sep 23 '14 at 21:06
  • Well it appears this is the best solution in this case. I'll just try to keep the simpler operations in a property, and if it gets too complex I'll move to a converter. Thanks again for everyone's help and suggestions! – jmgardn2 Sep 24 '14 at 13:49