MindFusion.Reporting for Silverlight Programmer's Guide
Tutorial 5: Custom Rendering

This tutorial illustrates how to specify multiple brushes for a PieChart as well as how to employ custom rendering in order to achieve particular effect. The following steps are explained in more details below:

Prerequisites

This tutorial extends Tutorial 4. Therefore it is expected that the reader has finished with Tutorial 4 before reading further.

1. Defining the custom brushes

In order to define the brushes in XAML we will need to create a strongly-typed brush collection. The following code snippet illustrates how:

C#  Copy Code

public class BrushCollection : ObservableCollection<Brush>
{
}

VB.NET  Copy Code

Public Class BrushCollection
    Inherits ObservableCollection(Of Brush)

End Class

We will define a collection of brushes in a separate resource dictionary, named Brushes.xaml. The code bellow shows the contents of this new dictionary:

XAML  Copy Code

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:MindFusion.Reporting.Silverlight.Samples.CS.Tutorial5;assembly=Tutorial5">

    <l:BrushCollection x:Key="PieBrushes">
        <SolidColorBrush Color="#FFFF00" />
        <SolidColorBrush Color="#FF0000" />
        <SolidColorBrush Color="#2EAB57" />
        <SolidColorBrush Color="#FF00FF" />
        <SolidColorBrush Color="#808080" />
        <SolidColorBrush Color="#1652B4" />
        <SolidColorBrush Color="#800080" />
        <SolidColorBrush Color="#00FF00" />
        <SolidColorBrush Color="#FFA500" />
        <SolidColorBrush Color="#20B2AA" />
        <SolidColorBrush Color="#006400" />
        <SolidColorBrush Color="#FFFFFF" />
        <SolidColorBrush Color="#808000" />
    </l:BrushCollection>

</ResourceDictionary>

The BrushCollection resource is merged in the report definition. Here is how:

XAML  Copy Code

<r:Report x:Key="myReport">
    <r:Report.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Tutorial5;component/Brushes.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </r:Report.Resources>

    <r:Page>

2. Setting the chart brushes

Now that the brushes are defined they can be easily referenced as a static resource and assigned to the Brushes property of the PieChart. The following XAML illustrates the modified declaration of the PieChart element within the report definition:

XAML  Copy Code

<r:PieChart Name="CheapProductsChart" Location="225,0" Size="250,250" TargetMember="UnitPrice" Brushes="{StaticResource PieBrushes}" PieStroke="Black" PieStrokeThickness="1" />

Running the report now will produce a colored pie chart. However it is not clear which products are represented by the chart pieces. To fix this, the background of the report entries can be modified to match the color of the corresponding pie chart pieces.

3. Custom-rendering DataRange entries

Custom rendering is performed by handling the Prerender event of the Report class. The following code illustrates handling of the event in C# and Visual Basic:

C#  Copy Code

myReport.Prerender += new EventHandler<PrerenderEventArgs>(myReport_Prerender);

VB.NET  Copy Code

AddHandler myReport.Prerender, AddressOf myReport_Prerender

The event can be handled at any point before the ReportLayout.RenderAllPages method is invoked. The event is raised for each individual item in the report after its visual representation is created but before it is added to the output. The rows in the DataRange are represented by ItemContainer objects. The DataContext property of each ItemContainer is set to the corresponding product row from the data set. The visual representation of the containers is specified through a Silverlight Border object. The custom-rendering code checks whether the current element is an ItemContainer and verifies if it corresponds to a "cheap product" by checking the UnitPrice field. If those conditions are at hand, the custom-rendering code sets the appropriate Brush to the background of the Border associated with the entry. The code of the event handler is listed below:

C#  Copy Code

private void myReport_Prerender(object sender, PrerenderEventArgs e)
{
    if (e.Item is ItemContainer)
    {
        var xelement = e.Item.DataContext as XElement;
        if (xelement != null)
        {
            if (double.Parse(xelement.Element("UnitPrice").Value, invariantCulture) < 10)
            {
                int index = cheapProducts.IndexOf(xelement);
                var border = e.RootVisual as Border;
                border.BorderBrush = new SolidColorBrush(Colors.Red);
                border.BorderThickness = new Thickness(1);
                border.Background = brushes[index];
            }
        }
    }
}

VB.NET  Copy Code

Private Sub myReport_Prerender(ByVal sender As Object, ByVal e As PrerenderEventArgs)

    If (Not TypeOf e.Item Is ItemContainer) Then
        Return
    End If

    If (Not TypeOf e.Item.DataContext Is XElement) Then
        Return
    End If

    Dim xelement = CType(e.Item.DataContext, XElement)

    If (Double.Parse(xelement.Element("UnitPrice").Value, invariantCulture) < 10) Then

        Dim index = cheapProducts.IndexOf(xelement)
        Dim border = CType(e.RootVisual, Border)
        border.BorderBrush = New SolidColorBrush(Colors.Red)
        border.BorderThickness = New Thickness(1)
        border.Background = brushes(index)

    End If

End Sub

The invariantCulture variable in the above code references the CultureInfo.InvariantCulture static member.

Running the report now and switching to two-page layout will bring the following result: