Introduction
I am a huge fan of Silverlight, and have been looking for an excuse to feature it on the SetPower site. We decided to create a calculator that people who are considering SetPower can use to estimate the amount of energy it would save for them. Ideally, we wanted a set of sliders that people could use to adjust to match their environment (e.g., Computer Wattage/# of PCs/Energy Rate, and the percentage of time they wanted to allow their computers to sleep).
You can see it here.
Of course, I considered DOM scripting as a possible language for such an application, but doing things like dynamic charts is very time consuming (coupled with the fact that I spent so much of my career pushing the boundaries of JavaScript I pretty much hate coding in it).
I am also a huge fan of the MVVM pattern. In face, the SetPower Enterprise Manager is based on WPF MVVM. Initially, I found adhering to the pattern was difficult (especially with the complex UI), but, like everything else, after some experience, you figure out the patterns within the pattern, so to speak.
CalculatorView
– this is the RootVisual that gets instantiated by Silverlight. It is pure XAML, with the code-behind consisting of only the following:
public partial class CalculatorView : UserControl
{
public CalculatorView()
{
InitializeComponent();
txtWatts.TextChanged += new TextChangedEventHandler(txt_TextChanged);
txtComputerCount.TextChanged += new
TextChangedEventHandler(txt_TextChanged);
}
void txt_TextChanged(object sender, TextChangedEventArgs e)
{
BindingExpression be =
(sender as TextBox).GetBindingExpression(TextBox.TextProperty);
be.UpdateSource();
}
}
The code was necessary only to change the binding behavior of the TextBox
es. In Silverlight, TextBox
es binding updates are triggered when the TextBox
loses focus. In my case, I wanted it to happen as soon as the user pressed the key so that they could see the impact of their change right away. (Initially, I didn’t have it this way, but when I gave it to my wife to test, she changed the wattage and never left the TextBox
, then wondered why more wattage didn’t increase her savings.) Something I struggled with when initially learning MVVM is that code-behind is OK in the View, so long as the code pertains only to the View. A cleaner implementation here would have been a derived control from Textbox
.
The ViewModel, which is instantiated and set as the data context in the XAML itself, has properties that throw INotifyPropertyChanged
for the Wattage/SleepPercentage/Computer Count/Computer Type, and are bound to the four sliders on the screen. In addition, some of the adornments like the icons for laptop/desktop/power desktop are toggle buttons that are bound to properties on the view model.
I also implemented rounding on some of the properties (PercentSleep
and EnergyRate
) to avoid long decimal strings in the UI when moving the sliders. I probably should have done the rounding as an IValueConverter
, but instead, just performed the action in the properties setters.
This was a very straightforward application I was able to complete in a workday, but there were a couple of things that slowed me down.
- Styling of the Chart – I wanted a cleaner look for the pie chart. Normally, this sort of thing is trivial in Blend, but I was left with an empty template in Blend after choosing Edit Template –>Edit a Copy. I ended up extracting the XAML from the Toolkit Source Code. After doing so, I made some tweaks to the format of the chart itself and the legend.
- Picking the Colors – I found several examples of how to do this on various blogs, but none of them worked. The
StylePalette
object they referenced didn’t exist in the October 2009 library. Eventually, I found that StylePalette
had been renamed to Palette
and the Pallete
contained a ResourceDictionaryCollection
.
<charting:Chart x:Name="energyChart"
Margin="0,8,7,0" HorizontalAlignment="Right"
Width="276" Style="{StaticResource PieChartTemplate}"
BorderBrush="{x:Null}" >
<charting:PieSeries.Palette>
<datavis:ResourceDictionaryCollection>
<ResourceDictionary>
<Style x:Key="DataPointStyle" TargetType="Control">
<Setter Property="Background" Value="{StaticResource PurpleHighlight}"/>
</Style>
</ResourceDictionary>
<ResourceDictionary>
<Style x:Key="DataPointStyle" TargetType="Control">
<Setter Property="Background"
Value="{StaticResource GreenHighlight}"/></Style>
</ResourceDictionary>
</datavis:ResourceDictionaryCollection>
</charting:PieSeries.Palette>
</charting:PieSeries>
</charting:Chart>
Currency Format – Supposedly, you should be able specify a currency format in the chart’s Palette
. I couldn’t get this to work, and instead handled this with a small custom class called EnergyCost
that holds the data as well as provides some labels for binding to the chart. In my case, I wanted custom text to appear in the legend that indicated how much money was being saved (or how much it costs to operate the computers) as well as the formatted currency.
History
- 11-24-09: Initial submission.