Fast Silverlight Charts

Chirag

Hi,

You know that we are working on optimizing the performance of charts. I am happy to share that we are done optimizing the overall performance of the charts – QuickLine chart to start with. Both initial render (drawing chart for the first time) & real-time render (updating chart in real-time) are now blazing fast. With these changes, Visifire is one of the fastest Silverlight charts! This blog contains benchmark figures & samples to corroborate our claim.

You’d feel the need of faster charts only when there is high number of datapoints. For less datapoints any charting component would suffice. Time taken by a component to plot datapoints on a chart for the first time (initial render) is a key metric to decide the performance. We did a small exercise to calculate the number of datapoints a charting component could draw in one second. For comparison we are using Visiblox, a fairly quick chart from Scott Logic. We supplied 10,000 through 50,000 datapoints to both charting components. We repeated the exercise to get 10 sample figures. Later, took an average to find out the number of datapoints that could be drawn in a second. Visifire could draw anywhere between 14,500 to 13,200 datapoints in a second. Whereas Visiblox could draw a maximum of 6,800 datapoints & the performance degraded drastically as the datapoints increased. Below are the benchmark figures:

Visifire, Visiblox - Charting Performance Comparison

Note: More the datapoints per second, faster the chart.

Embedded below is the application used to calculate the benchmark figures. You can play around with it & decide who is fast!

Get Microsoft Silverlight

Get Microsoft Silverlight

Note: Lesser the time taken, faster the chart.

Measuring framerate is a good way of finding the real-time rendering performance of a chart. We have just borrowed some samples from Visiblox post. You can play around with the following sample & decide who is fast!

Get Microsoft Silverlight

Get Microsoft Silverlight

Note: More the frames per second, faster the chart.

The source code of the above samples is available in these archives [sample1, sample2] for you to verify. The samples don’t contain charting libraries & are to be downloaded separately. Feel free to comment on this exercise.

Cheers,
Chirag
Team Visifire
Fire up your imagination!


SharePoint Charts

Chirag

We are delighted to launch our brand new product – Visifire for SharePoint (VfS). You were able to use Visifire in SharePoint in a rather cumbersome way. Creating charts in SharePoint has never been easier. Visifire for SharePoint is a wizard driven solution to create charts in SharePoint without writing any code! Embedded below is a short video on creating chart in SharePoint in just few clicks.

Before I conclude, summarized below are the key features of “Visifire for SharePoint”

  • Create charts in just few clicks
  • No need to write any code
  • Full fledged Chart Designer to customize default chart
  • Chart Designer boasts slick UI
  • Easy to deploy
  • Works with Microsoft SharePoint 2007 & 2010 on Windows Server 2003/2008
  • Connects to SharePoint Lists
  • Wide range of 2D/3D chart types

Starts at an introductory price of $999 per server. Download a 30 day Trial here.

We are very excited about this release & would love to have your feedback.

Cheers,
Chirag
Team Visifire


WP7 (Windows Phone 7) App for Visifire

Chirag

Hi,

We are delighted to release a WP7 App to showcase Visifire charts & gauges. As you already know Visifire supports WP7. This App is to let you quickly try how Visifire controls run on WP7. Click here to download the App. Embedded below is a video tour of the App.

We are excited about this App. Please give it a spin & let us know your feedback.

Cheers,
Team Visifire


Silverlight and WPF Enterprise Dashboard

somnath

Enterprise dashboards provide rich data visualization for analyzing data. A dashboard – for eg. sales dashboard is a vital tool for C-level executives, business managers and sales persons. This sales dashboard is a demo application using rich set of Visifire controls to analyze product wise monthly revenue of a fictitious company. It also shows sales conversion ratio showing how successful the sales team is in converting the leads to sales. Based on several parameters shown in the dashboard the decision makers can make informed decisions. 

This dashboard application is built based on MVVM pattern and best practices. MVVM follows three basic blocks called Model, View and ViewModel. The figure below shows basic blocks of the dashboard application.

Model: The Model is also called DataModel which contains business objects and model classes. It is independent of the View(UI).

View: The View contains visual elements displayed to the user and allows the user to interact with it.

ViewModel: The ViewModel represents the “Model of the View” which is also a mediator between View and the Model. It exposes the model’s data that is needed by the View.

In this Sales dashboard, the model represents business objects which include Model classes (Order and SalesConversion classes). View mainly represents user interface (XAML) and handles user interaction. “ProductWiseSalesView” contains chart controls to display product wise monthly revenue distribution, sales in volumes like sales conversion ratio, number of licenses sold with or without support and new licenses vs upgrades. The “ProductWiseSalesView” also contains two Gauge controls which displays annual revenue for a particular product. User interacts with the View. Content of the View is handled in the ViewModel through binding. The binding between View and ViewModel is done by setting ViewModel as the DataContext of the View. The ViewModel is derived from ModelBase class which in turn implements INotifyPropertyChanged interface to support DataBinding. Hence when ViewModel properties are changed, new changes are automatically reflected in the View.

Click here to view the dashboard.

You can download the source code from here.

Cheers,
Team Visifire


Windows Phone 7 Charts

Chirag

Hi,

You folks know that Windows Phone 7 Charts are possible with Visifire. Due to some breaking changes in the latest Beta release of Windows Phone Developer Tools users had issues using Visifire. We have decided to ship separate binaries for WP7 users. All that changes is that one has to provide reference to SLWpVisifire.Charts.dll instead of regular Visifire for Silverlight binaries. Listed below are few links to get you started quickly with Windows Phone 7 Charts:

Get Microsoft Silverlight

Download the latest version of Visifire here. We are very excited about this release & would love to have your feedback.

Cheers
Team Visifire


Silverlight/WPF Spline Chart

Chirag

Hi,

With this release Visifire introduces Spline Chart. A Spline Chart is similar to a Line Chart except that it draws a fitted curve through the data points. The spline interpolation and smoothing is for improved presentation of data. It allows one to take a limited set of known data points and approximate transitional values.

Demoed below is Messi’s path to glory!

Get Microsoft Silverlight

Cheers,
Team Visifire

http://www.visifire.com/blog/wp-content/post_xaps/GoalsScoredByMessiForBarcelonaClub.xap" height=" 680">Get Microsoft Silverlight


Silverlight/WPF Radar Chart

Chirag

Hi,

With this release Visifire introduces Radar Chart. A Radar Chart is a graphical method of displaying multivariate data in the form of a two-dimensional chart of three or more quantitative variables represented on axes starting from the same point. Radar Chart is also known as Web, Spider or Star Chart.

Shown below is the goals scored by top countries in FIFA World Cups 2006 & 2010 (till date).

Get Microsoft Silverlight

Cheers,
Team Visifire


Realtime Update Using DataBinding

somnath

DataBinding provides a simple way to manipulate and interact with data. DataBinding does the clear separation between UI implementation and business logic layer. The data can be imported from any data source like database, file etc. The UI element can be any framework element like DataGrid, Chart etc to visualize the data. Connection between UI and data object results in flow of data between them. When DataBinding is done, if the data changes then UI element which is bound to the data object also changes. In the case of two ways binding, changes made to UI element will cause data object to change.

In this post I will discuss about “How DataBinding takes place at real-time”. I prefer updating the chart at real-time without manipulating the Visifire chart elements directly. I will be doing multiple operations like add, delete, update with a collection and it’s good to see the changes reflecting in the chart at real-time.

Get Microsoft Silverlight

The figure shown below explains the conceptual representation of DataBinding between Visifire Chart and an ObservableCollection. DataRow is a class which holds Data for a DataPoint. A DataRow defines one or more number of properties to be mapped with DataPoints according to the data-mapping-rules defined at Series level. DataRows is a collection of one or more DataRow. Every record present in the DataRows collection represents a DataPoint.
Visifire-Chart-Realtime-Update-Using-DataBinding.xap
DataMapping rules which are to be specified in DataSeries are shown below:
<vc:DataSeries RenderAs="Column" LabelEnabled="True" Margin="-1,0,1,0">
    <vc:DataSeries.DataMappings>
        <vc:DataMapping MemberName="AxisXLabel" Path="AxisXLabel"></vc:DataMapping>
        <vc:DataMapping MemberName="YValue" Path="YValue">
    </vc:DataSeries.DataMappings>
 </vc:DataSeries>

In this example we are going to use dataRows as DataSource. Here DataSource property of the DataSeries has been set from managed code.

MyChart.Series[0].DataSource  = dataRows;

Please note that I  have used a DataGrid to dispaly the data present in dataRows in a tabular format. So I have bound dataRows collection with the DataGrid also. As DataGrid is bound with the collection, one can update the data present in collection just by editing the DataGrid cells. We can even directly perform Add, Remove operations with dataRows collection which will reflect in Chart as well as DataGrid.

DataRow is the class which has two properties named  AxisXLabel and YValue. This class contains business logic which is required to interact with values of dataRows. You may wonder how does it know when the property value changes? The answer to this question lies in the interface called INotifyPropertyChanged which is in System.ComponentModel namespace. The DataRow class implements INotifyPropertyChanged which notifies when the business object changes. So, whenever the value changes in the DataSource, corresponding property will trigger PropertyChanged event.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace VisifireDataBinding
{ 

  public class DataRow : INotifyPropertyChanged
  {
    /// <summary>
    /// Selected property is used to know whether the DataRow is selected  or not
    /// </summary>
    public Boolean Selected
    {
       get
       {
          return _select;
       }
       set
       {
         _select = value;

        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("Select"));
        }
    }

    /// <summary>
    /// AxisXLabel property
    /// </summary>
    public String AxisXLabel
    {
        get
        {
            return _axisXLabel;
        }
        set
        {
           _axisXLabel = value;

           if (PropertyChanged != null)
               PropertyChanged(this, new PropertyChangedEventArgs("AxisXLabel"));
         }
     }

     /// <summary>
     /// YValue property
     /// </summary>
     public Double YValue
     {
         get
         {
             return _yValue;
         }
         set
         {
            _yValue = value;

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("YValue"));
         }
      }

      #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

      #endregion

      Double _yValue;
      String _axisXLabel;
      Boolean _select;
   }
}

You can find additional information about InotificationPropertyChanged here.

As a result, chart is displayed with chart contents as shown below.

DataBinding makes it easy to display “live” data.

Changes made in the DataSource also causes changes in the chart without requiring any coding on your part! Now manipulate the values in DataGrid which may include addition, removal, update of DataPoint properties.

The DataGrid after adding properties for one or more DataPoint will look like below.

The Output changes!

Above image shows the chart with newly added AxisXLabel and YValue at real-time. Notice as I change values in DataGrid, the chart gets updated automatically.

You can download the source code of the sample demo application here.

Cheers,
Team Visifire


Visifire Now Supports DataBinding

admin

Today we are releasing the much awaited DataBinding feature in Visifire 3.0.3 beta 3. Now you can Bind any DataSource at the Series level so that the Chart gets generated automatically and reflects any change. Below is a demonstration of DataBinding. You can change the Values in DataGrid and the Chart gets updated automatically.

Get Microsoft Silverlight

Here is the source code for the above sample. Also you can visit Visifire documentation here for more info.

You can download Visifire 3.0.3 beta 3 from our download page.

Cheers,
Team Visifire


Exporting Visifire Silverlight Chart as Image

Chirag

Exporting Silverlight charts to images has been the most coveted feature. In this tutorial, I am going to show you to export Visifire Silverlight chart as image from managed code. So before we start lets check out the live example below.

Get Microsoft Silverlight

Project Setup

Create a “Silverlight Application” project. Download the latest Visifire binaries from here. Extract the Zip file and add reference for the file named “SLVisifire.Charts.dll”. In this sample, I am going to use WriteableBitmap class in order to extract the pixel wise color information of the chart rendered inside Silverlight content. We will take help of JpegEncoder provided by a third party library called FJ.Core to encode the raster information to file stream.

Please download FJ.Core library from here and add the FJ.Core.dll as reference to the project.

Below are the steps that we are going to follow.

  1. Construct the Chart XAML inside MainPage.xaml.
  2. Exporting Chart as image.

Constructing Chart XAML

Open MainPage.xaml page, add a Chart and a button inside it as shown below:

<UserControl x:Class="SLSave2Image.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vc="clr-namespace:Visifire.Charts;assembly=SLVisifire.Charts"
    mc:Ignorable="d" Width="500" Height="480">
    <Grid x:Name="LayoutRoot">
        <StackPanel>
            <vc:Chart Name="MyChart" Width="500" Height="300" Theme="Theme1">

                <vc:Chart.Titles>
                    <vc:Title Text="Visifire Chart"/>
                </vc:Chart.Titles>

                <vc:Chart.Series>
                    <vc:DataSeries RenderAs="Column" LabelEnabled="True">
                        <vc:DataSeries.DataPoints>
                            <vc:DataPoint AxisXLabel="Jan" YValue="35"/>
                            <vc:DataPoint AxisXLabel="Feb" YValue="32"/>
                            <vc:DataPoint AxisXLabel="Mar" YValue="27"/>
                            <vc:DataPoint AxisXLabel="Apr" YValue="17"/>
                            <vc:DataPoint AxisXLabel="May" YValue="16"/>
                        </vc:DataSeries.DataPoints>
                    </vc:DataSeries>
                </vc:Chart.Series>
            </vc:Chart>
            <Button Name="ButtonSave" Height="25" Width="160" Content="Save Chart" ></Button>
        </StackPanel>
    </Grid>
</UserControl>

Exporting Chart as image

Now open MainPage.xaml.cs page and add the following namespaces.

using FluxJpeg.Core;
using FluxJpeg.Core.Encoder;
using System.Windows.Media.Imaging;
using System.IO;
using Visifire.Charts;

Now attach an event handler for Click event of Button inside the Page constructor.

public MainPage()
{
    InitializeComponent();

    ButtonSave.Click += new RoutedEventHandler(ButtonSave_Click);
}

void ButtonSave_Click(object sender, RoutedEventArgs e)
{
    SaveToImage(MyChart);
}

Inside the ButtonSave event handler declare a function called SaveToImage() which will accept Chart as parameter as shown above.

Now inside the function definition, create a WriteableBitmap out of a Chart and collect the raster information from it. Then encode the raster information to file stream using JpegEncoder present in FJ.Core library as shown below. Finally save the file stream as image into hard drive.

/// <summary>
/// Save Visifire chart as Image
/// </summary>
/// <param name="Chart">Visifire.Charts.Chart</param>
private void SaveToImage(Chart chart)
{
    try
    {
        WriteableBitmap bitmap = new WriteableBitmap(chart, null);

        if (bitmap != null)
        {
            SaveFileDialog saveDlg = new SaveFileDialog();
            saveDlg.Filter = "JPEG Files (*.jpeg)|*.jpeg";
            saveDlg.DefaultExt = ".jpeg";

            if ((bool)saveDlg.ShowDialog())
            {
                using (Stream fs = saveDlg.OpenFile())
                {
                    MemoryStream stream = GetImageStream(bitmap);

                    //Get Bytes from memory stream and write into IO stream
                    byte[] binaryData = new Byte[stream.Length];
                    long bytesRead = stream.Read(binaryData, 0, (int)stream.Length);
                    fs.Write(binaryData, 0, binaryData.Length);
                }
            }
        }
    }
    catch(Exception ex)
    {
        System.Diagnostics.Debug.WriteLine("Note: Please make sure that Height and Width of the chart is set properly.");
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
}

/// <summary>
/// Get image MemoryStream from WriteableBitmap
/// </summary>
/// <param name="bitmap">WriteableBitmap</param>
/// <returns>MemoryStream</returns>
public static MemoryStream GetImageStream(WriteableBitmap bitmap)
{
    byte[][,] raster = ReadRasterInformation(bitmap);
    return EncodeRasterInformationToStream(raster, ColorSpace.RGB);
} 

/// <summary>
/// Reads raster information from WriteableBitmap
/// </summary>
/// <param name="bitmap">WriteableBitmap</param>
/// <returns>Array of bytes</returns>
public static byte[][,] ReadRasterInformation(WriteableBitmap bitmap)
{
    int width = bitmap.PixelWidth;
    int height = bitmap.PixelHeight;
    int bands = 3;
    byte[][,] raster = new byte[bands][,];

    for (int i = 0; i < bands; i++)
    {
        raster[i] = new byte[width, height];
    }

    for (int row = 0; row < height; row++)
    {
        for (int column = 0; column < width; column++)
        {
            int pixel = bitmap.Pixels[width * row + column];
            raster[0][column, row] = (byte)(pixel >> 16);
            raster[1][column, row] = (byte)(pixel >> 8);
            raster[2][column, row] = (byte)pixel;
        }
    }

    return raster;
}

/// <summary>
/// Encode raster information to MemoryStream
/// </summary>
/// <param name="raster">Raster information (Array of bytes)</param>
/// <param name="colorSpace">ColorSpace used</param>
/// <returns>MemoryStream</returns>
public static MemoryStream EncodeRasterInformationToStream(byte[][,] raster, ColorSpace colorSpace)
{
    ColorModel model = new ColorModel { colorspace = ColorSpace.RGB };
    FluxJpeg.Core.Image img = new FluxJpeg.Core.Image(model, raster);

    //Encode the Image as a JPEG
    MemoryStream stream = new MemoryStream();
    FluxJpeg.Core.Encoder.JpegEncoder encoder = new FluxJpeg.Core.Encoder.JpegEncoder(img, 100, stream);
    encoder.Encode();

    // Back to the start
    stream.Seek(0, SeekOrigin.Begin);

    return stream;
}

You can download the complete solution here

(Hat tip to Visifire user Sagi Karni, Intel Corp)

Cheers,
Team Visifire


Next Page »