Telerik blogs

Now that the RadChart control has officially joined the Silverlight party you are probably considering how to incorporate this jewel in all of your web projects. Probably most of you do not have the luxury to start over from scratch and implement pure Silverlight solutions abandoning all of your ASP.NET knowledge and legacy. With this blog post I will try to provide a simple demonstration how you can take advantage of the RadChart for Silverlight and easily add it to your current ASP.NET web applications. You'll also see how you can update some of the chart properties directly from your ASP.NET code.

Let's start with the Silverlight code -- for the sample application I will demonstrate databinding the chart control to ADO.NET data service that exposes the "Category Sales for 1997" view from the Northwind database. I will not go into the details of the auto-generation of the data model and the actual service that exposes it -- you can find all the details in the attached sample application.

Instead I will focus on the Silverlight code that enables RadChart to consume the data service:

XAML

<UserControl x:Class="ChartIntegrationApplication.Page"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:control
="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Charting">
   
<Grid x:Name="LayoutRoot" Background="White">
       
<control:RadChart x:Name="RadChart1" />
    </
Grid>
</UserControl>

C#

private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
   
BeginATOMRequest();
}

private void BeginATOMRequest()
{
   
DataServiceContext context = new DataServiceContext(new Uri("NorthwindDataService.svc", UriKind.Relative));
   
DataServiceQuery<Category_Sales_for_1997> query = context.CreateQuery<Category_Sales_for_1997>("Category_Sales_for_1997");
    
   
// Initializing asynchronous service request -- you cannot consume it synchronously in Silverlight.
    query.BeginExecute(ATOMRequestCompleted, query);
}

private void ATOMRequestCompleted(IAsyncResult asyncResult)
{
   
DataServiceQuery<Category_Sales_for_1997> query = asyncResult.AsyncState as DataServiceQuery<Category_Sales_for_1997>;

   
// Adding standard series / item mapping definitions in order to instruct the control how to map the data fields.
    SeriesMapping seriesMapping = new SeriesMapping();
   
seriesMapping.LegendLabel = "Sales (Thousands)";
   
seriesMapping.SeriesDefinition = new BarSeriesDefinition();

   
ItemMapping itemMapping = new ItemMapping("CategorySales", DataPointMember.YValue);

   
seriesMapping.ItemMappings.Add(itemMapping);
   
RadChart1.SeriesMappings.Add(seriesMapping);

   
List<Category_Sales_for_1997> list = query.EndExecute(asyncResult).ToList();
   
RadChart1.ItemsSource = list;

   
// Adding axis item label values to fill the corresponding axis.
    TickPointCollection tickPoints = RadChart1.DefaultView.ChartArea.AxisX.TickPoints;
   
for (int i = 0; i < tickPoints.Count; i++)
   
{
       
TickPoint tickPoint = tickPoints[i];
       
tickPoint.Label = list[i].CategoryName;
   
}
}

 

Now let's move to the ASP.NET part – I have set up a simple ASP.NET website with a singe page and a user control. As I need to wrap the Silverlight content inside the user control, first I need to add the following register directive in the ASCX file:

<%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls"
    TagPrefix
="asp" %>

This enables me to reference Silverlight content within the respective ASP.NET user control via the asp:Silverlight server control (the Source property for this control is set to the xap output produced by the Silverlight project discussed above):

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/ChartIntegrationApplication.xap" 
    MinimumVersion
="2.0.31005.0" Width="100%" Height="100%" />

 

Basically this is everything that is necessary to display the Silverlight content inside ASP.NET user control. However, let's spice it up a bit and add the option to customize certain properties of the Silverlight chart control directly from ASP.NET code.

First let's sort out what should be done in order to achieve the desired functionality -- ASP.NET is primarily server-side oriented technology, while the Siverlight operating ground is the client-side (the user browser). I need a mechanism that would transfer the server-side property values (from the user control) to the managed Silverlight code on the client. Fortunately the choice is easy: JavaScript! Silverlight allows you to create a bridge between the scripting and managed code worlds and calling managed code from JavaScript is fairly straightforward process.

There are two steps necessary in order to achieve the desired functionality:

- You need to decide which member items will be exposed for scriptable access -- you can do that by applying the System.Windows.Browser.ScriptableMemberAttribute on the respective members on the object you will register for scriptable access.
- You need to register the managed object for scriptable access by JavaScript code. You can do that via the HtmlPage.RegisterScriptableObject(...) method. This method allows you to give a class instance an alias that can be used from script. Generally the Silverlight content is exposed by the plug-in via its content property. You can access your scriptable object by first retrieving the plug-in, appending the alias onto the content property, and then referencing the ScriptableMember you want ([silverlight-plugin].content.[scriptable-object-alias].[scriptable-member] = myValue;).

Let's add the option to customize the following properties from ASP.NET code:
- The chart title.
- The format of the series item labels.
- The format of the vertical axis labels.


As discussed above I need to register the Silverlight page for scriptable access and mark three scriptable members like this:

private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
   
HtmlPage.RegisterScriptableObject("slChartPage", this);

   
BeginATOMRequest();
}

private void BeginATOMRequest()
{
   
// ...
}

private void ATOMRequestCompleted(IAsyncResult asyncResult)
{
   
// ...

   
SeriesMapping seriesMapping = new SeriesMapping();
    
   
// ...
    
   
seriesMapping.SeriesDefinition.DefaultFormat = this.SeriesItemLabelFormat;

   
ItemMapping itemMapping = new ItemMapping("CategorySales", DataPointMember.YValue);

   
seriesMapping.ItemMappings.Add(itemMapping);
   
RadChart1.SeriesMappings.Add(seriesMapping);

   
// ...

   
RadChart1.DefaultView.ChartArea.AxisY.DefaultFormat = this.AxisYLabelFormat;

   
// ...
    
   
RadChart1.DefaultView.ChartTitle.Content = this.ChartTitle;
}

[ScriptableMember]
public string ChartTitle
{
   
get;
    set;
}

[ScriptableMember]
public string SeriesItemLabelFormat
{
   
get;
   
set;
}

[ScriptableMember]
public string AxisYLabelFormat
{
   
get;
   
set;
}

 

Now let's create the ASP.NET wrapper properties. Remember that I need to transfer the server-side values via the script bridge to the Silverlight managed runtime so for each user control property wrapper I am transferring the value to proxy JavaScript variable via Page.ClientScript.RegisterStartupScript(...) calls like this (note I am handling the OnPluginLoaded client-side event of the asp:Silverlight control in order to ensure that when the script values are passed to the managed Silverlight runtime, the control is fully loaded and functional):

ASCX

<script type="text/javascript">
var chartTitle, labelFormat, axisLabelFormat;

function pluginLoaded(sender) 
{
   
// get reference to the silverlight control on the page
    var silverlightControl = sender.get_element();

   
// call scriptable method in silverlight application
    // we call it here to ensure silverlight controls is fully loaded.
    if (chartTitle != null)
       
silverlightControl.content.slChartPage.ChartTitle = chartTitle;

   
if (labelFormat != null)
       
silverlightControl.content.slChartPage.SeriesItemLabelFormat = labelFormat;

   
if (axisLabelFormat != null)
       
silverlightControl.content.slChartPage.AxisYLabelFormat = axisLabelFormat;
}

function setTitleValue(title) 
{
   
chartTitle = title;
}

function setFormatValue(format) 
{
   
labelFormat = format;
}

function setAxisFormatValue(format) 
{
   
axisLabelFormat = format;
}
</script>    

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/ChartIntegrationApplication.xap" 
    MinimumVersion
="2.0.31005.0" Width="100%" Height="100%" OnPluginLoaded="pluginLoaded" />

 

C#

public partial class ChartUserControl : System.Web.UI.UserControl
{
   
protected void Page_Load(object sender, EventArgs e)
   
{
       
// pass values to silverlight in HTML
        if (!string.IsNullOrEmpty(this.ChartTitle))
           
Page.ClientScript.RegisterStartupScript(typeof(Page), "SLPROXY_TITLE", string.Format("setTitleValue('{0}');", this.ChartTitle), true);

       
if (!string.IsNullOrEmpty(this.SeriesItemLabelFormat))
           
Page.ClientScript.RegisterStartupScript(typeof(Page), "SLPROXY_FORMAT", string.Format("setFormatValue('{0}');", this.SeriesItemLabelFormat), true);

       
if (!string.IsNullOrEmpty(this.AxisYLabelFormat))
           
Page.ClientScript.RegisterStartupScript(typeof(Page), "SLPROXY_AXISFORMAT", string.Format("setAxisFormatValue('{0}');", this.AxisYLabelFormat), true);

   
}

   
public string ChartTitle
   
{
       
get;
       
set;
   
}

   
public string SeriesItemLabelFormat
   
{
       
get;
       
set;
   
}

   
public string AxisYLabelFormat
   
{
       
get;
       
set;
   
}
}
 
 
Hope you will find this information useful.

Comments

Comments are disabled in preview mode.