RadChart interoperability with ASP.NET

Thread is closed for posting
3 posts, 0 answers
  1. Telerik Admin
    Telerik Admin avatar
    1679 posts
    Member since:
    Oct 2004

    Posted 17 Mar 2009 Link to this post

    Requirements

    RadControls version

    2009.1.312.1020 and later.
    .NET version

    3.5
    Visual Studio version

    VS 2008 SP1
    programming language

    C#
    browser support

    all browsers supported by RadControls


    PROJECT DESCRIPTION

    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. We will try to provide a simple demonstration how you can take advantage of the RadChart for Silverlight and easily add it to your existing ASP.NET web applications. You'll also see how you can update some of the chart properties directly from the 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 (we will not go into the details of the auto-generation of the data model and the actual service that exposes it as this is pretty standard stuff and you can review it in the attached zip file).

     

    Instead we 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; 
       } 
    }  

    VB.NET
    Private Sub Page_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) 
     BeginATOMRequest() 
    End Sub 
    Private Sub BeginATOMRequest() 
     Dim context As New DataServiceContext(New Uri("NorthwindDataService.svc", UriKind.Relative)) 
     Dim query As DataServiceQuery(Of Category_Sales_for_1997) = context.CreateQuery(Of Category_Sales_for_1997)("Category_Sales_for_1997"
     ' Initializing asynchronous service request -- you cannot consume it synchronously in Silverlight. 
     query.BeginExecute(ATOMRequestCompleted, query) 
    End Sub 
    Private Sub ATOMRequestCompleted(asyncResult As IAsyncResult) 
     Dim query As DataServiceQuery(Of Category_Sales_for_1997) = TryCast(asyncResult.AsyncState, DataServiceQuery(Of Category_Sales_for_1997)) 
     ' Adding standard series / item mapping definitions in order to instruct the control how to map the data fields. 
     Dim seriesMapping As New SeriesMapping() 
     seriesMapping.LegendLabel = "Sales (Thousands)" 
     seriesMapping.SeriesDefinition = New BarSeriesDefinition() 
     Dim itemMapping As New ItemMapping("CategorySales", DataPointMember.YValue) 
     seriesMapping.ItemMappings.Add(itemMapping) 
     RadChart1.SeriesMappings.Add(seriesMapping) 
     Dim list As List(Of Category_Sales_for_1997) = query.EndExecute(asyncResult).ToList() 
     RadChart1.ItemsSource = list 
     ' Adding axis item label values to fill the corresponding axis. 
     Dim tickPoints As TickPointCollection = RadChart1.DefaultView.ChartArea.AxisX.TickPoints 
     Dim i As Integer = 0 
     While i < tickPoints.Count 
      Dim tickPoint As TickPoint = tickPoints(i) 
      tickPoint.Label = list(i).CategoryName 
      System.Math.Max(System.Threading.Interlocked.Increment(i),i - 1) 
     End While 
    End Sub 

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

    ASCX

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

    This enables us 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):

    ASCX

    <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). We 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 we need to register the Silverlight page for scriptable access and mark three scriptable members like this:

    C#

    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
    }   

    VB.NET

    Private Sub Page_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) 
     HtmlPage.RegisterScriptableObject("slChartPage"Me
     BeginATOMRequest() 
    End Sub 
    Private Sub BeginATOMRequest() 
     ' ... 
    End Sub 
    Private Sub ATOMRequestCompleted(asyncResult As IAsyncResult) 
     ' ... 
     Dim seriesMapping As New SeriesMapping() 
     ' ... 
     seriesMapping.SeriesDefinition.DefaultFormat = Me.SeriesItemLabelFormat 
     Dim itemMapping As New ItemMapping("CategorySales", DataPointMember.YValue) 
     seriesMapping.ItemMappings.Add(itemMapping) 
     RadChart1.SeriesMappings.Add(seriesMapping) 
     ' ... 
     RadChart1.DefaultView.ChartArea.AxisY.DefaultFormat = Me.AxisYLabelFormat 
     ' ... 
     RadChart1.DefaultView.ChartTitle.Content = Me.ChartTitle 
    End Sub 
    <ScriptableMember> _ 
    Public Property ChartTitle() As String 
     Get 
     End Get 
     Set 
     End Set 
    End Property 
    <ScriptableMember> _ 
    Public Property SeriesItemLabelFormat() As String 
     Get 
     End Get 
     Set 
     End Set 
    End Property 
    <ScriptableMember> _ 
    Public Property AxisYLabelFormat() As String 
     Get 
     End Get 
     Set 
     End Set 
    End Property 

    Now let's create the ASP.NET wrapper properties. Remember that we need to transfer the server-side values via the script bridge to the Silverlight managed runtime so for each user control property wrapper we are transferring the value to proxy JavaScript variable via Page.ClientScript.RegisterStartupScript(...) calls like this (note we are 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
       } 
    }   

    VB.NET

    Public Partial Class ChartUserControl 
     Inherits System.Web.UI.UserControl 
     Protected Sub Page_Load(sender As Object, e As EventArgs) 
      ' pass values to silverlight in HTML 
      If Not String.IsNullOrEmpty(Me.ChartTitle) Then 
       Page.ClientScript.RegisterStartupScript(GetType(Page), "SLPROXY_TITLE"String.Format("setTitleValue('{0}');"Me.ChartTitle), True
      End If 
      If Not String.IsNullOrEmpty(Me.SeriesItemLabelFormat) Then 
       Page.ClientScript.RegisterStartupScript(GetType(Page), "SLPROXY_FORMAT"String.Format("setFormatValue('{0}');"Me.SeriesItemLabelFormat), True
      End If 
      If Not String.IsNullOrEmpty(Me.AxisYLabelFormat) Then 
       Page.ClientScript.RegisterStartupScript(GetType(Page), "SLPROXY_AXISFORMAT"String.Format("setAxisFormatValue('{0}');"Me.AxisYLabelFormat), True
      End If 
     End Sub 
     Public Property ChartTitle() As String 
      Get 
      End Get 
      Set 
      End Set 
     End Property 
     Public Property SeriesItemLabelFormat() As String 
      Get 
      End Get 
      Set 
      End Set 
     End Property 
     Public Property AxisYLabelFormat() As String 
      Get 
      End Get 
      Set 
      End Set 
     End Property 
    End Class 

    Hope you will find this information useful.







  2. Timothy Delaney
    Timothy Delaney avatar
    2 posts
    Member since:
    Aug 2009

    Posted 17 Sep 2009 Link to this post

    How do you debug this application since the control is using the .xap file?
  3. Ves
    Admin
    Ves avatar
    2879 posts

    Posted 23 Sep 2009 Link to this post

    Hello Timothy,

    Please, check this online example. In the description section you will find a link to a runnable silverlight project to use with that example.

    Best regards,
    Ves
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Back to Top