Dynamic WP7 Charting: Static Resources versus Binding

In my current development project, my MVVM pivot app needed to create a pie chart from a collection of objects. I read David Anson’s (@DavidAns) blog about using Charts in Windows Phone 7 (WP7) development. His example uses a detailed Resource Dictionary for the style of the chart. I’m so new to Silverlight that the XAML markup of David’s example tripped me up. This blog post is for other newbies trying to rework static resources into dynamic binding.

Capture2

In Silverlight, static resources are those that are already defined, hence static. This is great for a known set or for working in the Visual Studio Design-time environment. Dynamic resources can only be viewed in the runtime environment where they can also be changed.

In this article, I’m using the Silverlight Toolkit, found here.

A chart is a parent with child nodes of legend and pieseries. Since the Chart is a parent with several children, I wasn’t sure where to bind my collection of dynamic objects which would determine the percentage of the pie slices. I also needed to move the code strictly not associated with the chart to a different file/class. The example below is similar to the real life problem I was trying to solve. The code is taken from David’s example.

Method 1: {StaticResource}

First it is helpful to explain the markup in David’s example that I didn’t understand. His example places the following data object in the code-behind for the page but outside the page class:
// Class for storing information about an activity
    public class ActivityInfo
    {
        public string Activity { get; set; }
        public int Count { get; set; }
    }

    // Class for storing activities
    public class Activities : List<ActivityInfo>
    {
        public Activities()
        {
            Add(new ActivityInfo { Activity = "SMS", Count = 31 });
            Add(new ActivityInfo { Activity = "Email", Count = 26 });
            Add(new ActivityInfo { Activity = "Calls", Count = 10 });
        }
    }

His Main.xaml connects these classes to the Chart control by adding a Resource listing above the <Grid> object at the top of the page.
<phone:PhoneApplicationPage.Resources>
        <!-- Data -->
        <local:Activities x:Key="Activities"/>
    </phone:PhoneApplicationPage.Resources>

In the <PieSeries> object, the ItemsSource attribute is tied to a static resource of Activities because it has been defined in the <phone.PhoneApplicationPage.Resources> object noted just above. A Pie Chart requires two data points, name and value, to draw the pie. These are Activity and Count in the ActivityInfo class. They are bound from the class to the PieChart via the DependentValuePath and the IndependentValuePath. David’s complete <Chart> object looks like:
<charting:Chart
                x:Name="myChart"
                Title="static chart"
                LegendTitle="legend"
                Style="{StaticResource PhoneChartStyle}"
                Template="{StaticResource PhoneChartPortraitTemplate}">

                <!-- Series -->
                <charting:PieSeries
                    ItemsSource="{StaticResource Activities}"
                    DependentValuePath="Count"
                    IndependentValuePath="Activity">
                    <charting:PieSeries.LegendItemStyle>
                        <Style TargetType="charting:LegendItem">
                            <Setter Property="Margin" Value="5 0 5 0"/>
                        </Style>
                    </charting:PieSeries.LegendItemStyle>
                </charting:PieSeries>

            </charting:Chart>
To be credit, his example works and is a great way of connecting code to an object via the StaticResource keyword. The nice thing about his method is that the PieChart displays in Visual Studio design time. 
Because I wanted the XAML and code-behind to follow the pattern of the app I had in progress, David’s approach wouldn’t work for me. My code was not all in the code-behind but spread across the model classes for better organization and maintenance. I needed to figure out how to switch the binding from:
ItemsSource="{StaticResource Activities}"  to ItemsSource="{Binding}" 

Method 2: {Binding}

Here is what I had to do to make this simple binding work:
  1. moved the Activity and ActivityInfo classes into their own class/file but same namespace and removed the Resource XAML above the Grid. 
  2. changed from StaticResource to Binding:
<!-- Chart sample -->
            <charting:Chart
                x:Name="myChart"
                Title="static chart"
                LegendTitle="legend"
                Style="{StaticResource PhoneChartStyle}"
                Template="{StaticResource PhoneChartPortraitTemplate}">

                <!-- Series -->
                <charting:PieSeries
                    ItemsSource="{Binding}"
                    DependentValuePath="Count"
                    IndependentValuePath="Activity">
                    <charting:PieSeries.LegendItemStyle>
                        <Style TargetType="charting:LegendItem">
                            <Setter Property="Margin" Value="5 0 5 0"/>
                        </Style>
                    </charting:PieSeries.LegendItemStyle>
                </charting:PieSeries>

            </charting:Chart>
  

  1. Bind via code, not to the PieSeries but instead to the parent Chart, add this line of code after the MainPage Constructor’s InitializeComponent() call.
    myChart.DataContext = new Activities();
    
This last step, #4, I hooked my data object, Activities, to the XAML object Chart. The good thing about this is that the exact data is connected to the exact object. The bad thing is that if I want to add more objects or different data elements to this page, this code is too restrictive. A better consideration for maintence would be to tie my App-level data model object to the page-level DataContext in the MainPage Constructor’s InitializeComponent() call:

DataContext = new App.Data();

Downloads:

I tweaked David’s project to show this code. You can grab the zipped file here

Thank you to David for getting me started in the right direction.

Comments

  1. Hi, was this for silverlight 3 for WP7 or silverlight4 for wp7?

    ReplyDelete
  2. Wow, this is exactly what I was trying to do. The DataContext part was where I was stuck.

    ReplyDelete
  3. good blog post....useful ...

    ReplyDelete

Post a Comment

Popular posts from this blog

Simple WP7 Mango App for Background Tasks, Toast, and Tiles: Code Explanation

Yet once more into the breech (of altered programming logic)

Error : /ScriptResource.axd : Invalid viewstate.