Binding to local helper objects
"Hack" or "Good Thing" -- What do you all think?
I wanted to factor out some minor calculations from one of my screen, things like updating a total based on the sum of some other balances. To support this, I created an object named BatchCalculator and added some get/set properties and a couple of get-only calculated properties. I wired up INotifyPropertyChanged, and then added a private property to my page. In OnInitialize I set up the initial values, and in the command handler for the page's "save" command, I consume the values in building the calls to the other layers of the application. So far, so good... fairly clean design, everything's happy, right?
Then I tried to bind to that object. UGH! It's not a DependencyObject or connected as a DependencyProperty... nor does it feel to me like it should be, so I don't want to set up the Binding object with RelativeSource or ElementName. I have an instance already, so adding a page resource as all the examples point out doesn't help... or does it?
My only working approach was to build up the binding in Code, like this:
Binding b = new Binding();
b.Source = BatchCalculator;
b.Path = new PropertyPath("StartingBalance");
b.Mode = BindingMode.TwoWay;
b.UpdateSourceTrigger = UpdateSourceTrigger.Default;
_startingAmountTextBox.SetBinding(TextBox.TextProperty, b);
This, however is UGLY, and should be a single XAML line.
The Solution
Based on http://msdn2.microsoft.com/en-us/library/ms750950.aspx, I realized that I could add a resource to the page's collection in code behind, and then have it be available for a {StaticResource} or {DynamicResource} markup extension to target. Since StaticResource "strongly suggests" (AKA requires in most cases) that the object is already declared and isn't forward referenced, I added this to my constructor (names changed to protect... Me):
public MyPageClass()
{
// Must be added BEFORE InitializeComponent
Resources.Add("batchCalculator", BatchCalculator);
InitializeComponent();
RegisterCommands();
}
Then, everything happily works with XAML that looks like this (get/set properties):
<TextBox Text="{Binding Source={StaticResource batchCalculator}, Path=StartingBalance, Mode=TwoWay, UpdateSourceTrigger=Default}"/>
or, for the calculated fields,
<TextBox IsReadOnly="True" Text="{Binding Source={StaticResource batchCalculator}, Path=AmountOver, Mode=OneWay, UpdateSourceTrigger=Default}" />
Conclusion
So, for those out there with more wisdom than I, is this a good way of accomplishing the binding I need? Or, did I miss something obvious? Do I misunderstand how one of the other two binding source specifiers works?