MindFusion.Wpf Pack 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

We define an array with brushes as a resource of the report itself. The array is defined in XAML using the x:Array extension. The code, which defines the brush array is highlighted in bold below:

XAML  Copy Code

<r:Report x:Key="myReport">
  <r:Report.Resources>
    <x:ArrayExtension Type="{x:Type Brush}" 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" />
    </x:ArrayExtension>
  </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 Location="225,0" Size="250,250" DataContext="{Binding CheapProducts}" 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 WPF 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 row = e.Item.DataContext as nwindDataSet.ProductsRow;
        if (row != null)
        {
            if (row.UnitPrice < 10)
            {
                int i = 0;
                int index = -1;
                foreach (nwindDataSet.CheapProductsRow cheapRow in dataset.CheapProducts)
                {
                    if (cheapRow.ProductName == row.ProductName)
                    {
                        index = i;
                        break;
                    }

                    i++;
                }

                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 (TypeOf e.Item Is ItemContainer) Then

        If TypeOf e.Item.DataContext Is nwindDataSet.ProductsRow Then

            Dim row = CType(e.Item.DataContext, nwindDataSet.ProductsRow)
            If (row IsNot Nothing) Then

                If (row.UnitPrice < 10) Then

                    Dim i As Integer = 0
                    Dim index As Integer = -1
                    For Each cheapRow As nwindDataSet.CheapProductsRow In dataset.CheapProducts

                        If (cheapRow.ProductName = row.ProductName) Then
                            index = i
                            Exit For
                        End If

                        i += 1

                    Next cheapRow

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

                End If

            End If

        End If

    End If

End Sub

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